/*-
*******************************************************************************
* Copyright (c) 2011, 2014 Diamond Light Source Ltd.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Peter Chang - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.dawnsci.analysis.dataset.roi;
import java.io.Serializable;
import org.eclipse.dawnsci.analysis.api.fitting.IConicSectionFitter;
import org.eclipse.dawnsci.analysis.api.roi.IFitROI;
import org.eclipse.dawnsci.analysis.api.roi.IPolylineROI;
import org.eclipse.dawnsci.analysis.dataset.roi.fitting.CircleFitter;
import org.eclipse.january.dataset.IDataset;
/**
* A circular region of interest which fits the points in a polygonal region of interest
*/
public class CircularFitROI extends CircularROI implements IFitROI, Serializable {
private IPolylineROI proi;
private IConicSectionFitter fitter;
private double residual;
private CircularFitROI(double radius, double ptx, double pty) {
super(radius, ptx, pty);
residual = 0;
}
public CircularFitROI(IPolylineROI points) {
super(1, 0, 0);
setPoints(points);
}
@Override
public void downsample(double subFactor) {
super.downsample(subFactor);
proi.downsample(subFactor);
}
@Override
public CircularFitROI copy() {
CircularFitROI c = new CircularFitROI(getRadius(), getPointX(), getPointY());
c.name = name;
c.proi = proi.copy();
c.plot = plot;
return c;
}
/**
* Fit a circle to given polygon
* @param polyline
* @return fitter
*/
public static IConicSectionFitter fit(IPolylineROI polyline) {
IDataset[] xy = polyline.makeCoordinateDatasets();
IConicSectionFitter f = new CircleFitter();
f.geometricFit(xy[0], xy[1], null);
return f;
}
/**
* Set points which are then used to fit circle
* @param points
*/
@Override
public void setPoints(IPolylineROI points) {
proi = points;
if (fitter == null) {
fitter = fit(points);
} else {
IDataset[] xy = points.makeCoordinateDatasets();
final double[] p = fitter.getParameters();
p[0] = getRadius();
p[1] = getPointX();
p[2] = getPointY();
fitter.geometricFit(xy[0], xy[1], p);
}
final double[] p = fitter.getParameters();
residual = fitter.getRMS();
setRadius(p[0]);
setPoint(p[1], p[2]);
}
/**
* @return root mean squared of residuals
*/
@Override
public double getRMS() {
return residual;
}
/**
* @return fitter used
*/
public IConicSectionFitter getFitter() {
return fitter;
}
/**
* @return points in polygon for fitting
*/
@Override
public IPolylineROI getPoints() {
return proi;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((fitter == null) ? 0 : fitter.hashCode());
result = prime * result + ((proi == null) ? 0 : proi.hashCode());
long temp;
temp = Double.doubleToLongBits(residual);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
CircularFitROI other = (CircularFitROI) obj;
if (fitter == null) {
if (other.fitter != null)
return false;
} else if (!fitter.equals(other.fitter))
return false;
if (proi == null) {
if (other.proi != null)
return false;
} else if (!proi.equals(other.proi))
return false;
if (Double.doubleToLongBits(residual) != Double.doubleToLongBits(other.residual))
return false;
return true;
}
}