/*-
*******************************************************************************
* 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.util.Arrays;
import org.eclipse.dawnsci.analysis.api.roi.IROI;
public class ROIUtils {
/**
* @param clazz
* @return new list to hold ROIs of same class
* @throws UnsupportedOperationException when there is no list class
*/
public static ROIList<?> createNewROIList(Class<? extends IROI> clazz) {
if (clazz == null)
return null;
// be aware that order of tests is important as must be determined by class hierarchy
if (PolygonalROI.class.isAssignableFrom(clazz))
return new PolygonalROIList();
// to-do add free draw
else if (PolylineROI.class.isAssignableFrom(clazz))
return new PolylineROIList();
else if (PointROI.class.isAssignableFrom(clazz))
return new PointROIList();
// to-do add line 3D
else if (LinearROI.class.isAssignableFrom(clazz))
return new LinearROIList();
else if (XAxisBoxROI.class.isAssignableFrom(clazz))
return new XAxisBoxROIList();
else if (XAxisLineBoxROI.class.isAssignableFrom(clazz))
return new XAxisLineBoxROIList();
else if (YAxisBoxROI.class.isAssignableFrom(clazz))
return new YAxisBoxROIList();
else if (YAxisLineBoxROI.class.isAssignableFrom(clazz))
return new YAxisLineBoxROIList();
else if (PerimeterBoxROI.class.isAssignableFrom(clazz))
return new PerimeterBoxROIList();
// to-do add grid
else if (RectangularROI.class.isAssignableFrom(clazz))
return new RectangularROIList();
else if (RingROI.class.isAssignableFrom(clazz))
return new RingROIList();
else if (SectorROI.class.isAssignableFrom(clazz))
return new SectorROIList();
// to-do add circular fit
else if (CircularROI.class.isAssignableFrom(clazz))
return new CircularROIList();
else if (EllipticalFitROI.class.isAssignableFrom(clazz))
return new EllipticalFitROIList();
else if (EllipticalROI.class.isAssignableFrom(clazz))
return new EllipticalROIList();
else if (ParabolicROI.class.isAssignableFrom(clazz))
return new ParabolicROIList();
else if (HyperbolicROI.class.isAssignableFrom(clazz))
return new HyperbolicROIList();
// to-do add surface plot
throw new UnsupportedOperationException("No corresponding ROI list class");
}
/**
* @param roi
* @return new list to hold ROIs of same type
*/
public static ROIList<?> createNewROIList(IROI roi) {
if (roi == null)
return null;
return createNewROIList(roi.getClass());
}
/**
* Convert int array of two numbers to double array
* @param pt
* @return double array
*/
public static double[] convertToDoubleArray(int[] pt) {
assert pt.length == 2;
return new double[] { pt[0], pt[1] };
}
/**
* Check if point (x, y) is close to a line segment given by direction (dx, dy) and length
* @param dx
* @param dy
* @param l
* @param x
* @param y
* @param distance
* @return true if given point is within distance of segment
*/
public static boolean isNearSegment(double dx, double dy, double l, double x, double y, double distance) {
double t = x * dx + y * dy; // parameter on segment
if (t < 0 || t > l)
return false;
return Math.abs(x * dy - y * dx) <= distance;
}
/**
* Check if point (x, y) is close to a line segment given by vector (vx, vy)
* @param vx
* @param vy
* @param x
* @param y
* @param distance
* @return true if given point is within distance of segment
*/
public static boolean isNearSegment(double vx, double vy, double x, double y, double distance) {
double l = Math.hypot(vx, vy);
return isNearSegment(vx/l, vy/l, l, x, y, distance);
}
/**
* Update maximum and minimum values according to point
* @param max
* @param min
* @param pt
*/
public static void updateMaxMin(double[] max, double[] min, double[] pt) {
updateMaxMin(max, min, pt[0], pt[1]);
}
/**
* Update maximum and minimum values according to x and y
* @param max
* @param min
* @param x
* @param y
*/
public static void updateMaxMin(double[] max, double[] min, double x, double y) {
if (x > max[0])
max[0] = x;
if (y > max[1])
max[1] = y;
if (x < min[0])
min[0] = x;
if (y < min[1])
min[1] = y;
}
/**
* Find intersect of horizontal line with a line segment
* @param spt start point of segment
* @param ept end point of segment
* @param y ordinate
* @return abscissa can be null for non-intersecting case, else one or two values
*/
public static double[] findYIntersection(final double[] spt, final double[] ept, final double y) {
double[] xi = null;
double dy = ept[1] - spt[1];
if (dy == 0) {
if (y == spt[1]) {
xi = new double[] { spt[0], ept[0] };
Arrays.sort(xi);
}
} else {
double ny = y - spt[1];
if ((ny >= 0 && ny <= dy) || (ny <= 0 && ny >= dy)) {
xi = new double[] { spt[0] + (ept[0] - spt[0]) * ny / dy};
}
}
return xi;
}
}