use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PathHierarchyPaintingHelper method paintHandles.
/**
* Paint the handles onto a Graphics object.
*
* @param g2d
* @param handleSize The width & height of the shape used to draw the handles
* @param colorStroke
* @param colorFill
*/
/**
* Paint the handles onto a Graphics object, if we have a suitable (non-point) ROI.
* <p>
* The minimum and maximum handle size can be specified; if the same, all handles will have the same size. If different,
* then the distance between consecutive handles will be used to influence the actual handle size. This is helpful
* when handles are densely packed.
*
* @param handles
* @param g2d
* @param minHandleSize
* @param maxHandleSize
* @param colorStroke
* @param colorFill
*/
public static void paintHandles(final List<Point2> handles, final Graphics2D g2d, final double minHandleSize, final double maxHandleSize, final Color colorStroke, final Color colorFill) {
RectangularShape handleShape = new Rectangle2D.Double();
// handleShape = new Ellipse2D.Double();
int n = handles.size();
if (minHandleSize == maxHandleSize) {
for (Point2 p : handles) {
double handleSize = minHandleSize;
handleShape.setFrame(p.getX() - handleSize / 2, p.getY() - handleSize / 2, handleSize, handleSize);
if (colorFill != null) {
g2d.setColor(colorFill);
g2d.fill(handleShape);
}
if (colorStroke != null) {
g2d.setColor(colorStroke);
g2d.draw(handleShape);
}
}
return;
} else {
for (int i = 0; i < handles.size(); i++) {
var current = handles.get(i);
var before = handles.get((i + n - 1) % n);
var after = handles.get((i + 1) % n);
double distance = Math.sqrt(Math.min(current.distanceSq(before), current.distanceSq(after))) * 0.5;
double size = Math.max(minHandleSize, Math.min(distance, maxHandleSize));
var p = current;
handleShape.setFrame(p.getX() - size / 2, p.getY() - size / 2, size, size);
if (colorFill != null) {
g2d.setColor(colorFill);
g2d.fill(handleShape);
}
if (colorStroke != null) {
g2d.setColor(colorStroke);
g2d.draw(handleShape);
}
}
}
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class ROIConverterIJ method convertToPointsList.
private static List<Point2> convertToPointsList(FloatPolygon polygon, double xOrigin, double yOrigin, double downsampleFactor) {
List<Point2> points = new ArrayList<>();
for (int i = 0; i < polygon.npoints; i++) {
float x = (float) convertLocationfromIJ(polygon.xpoints[i], xOrigin, downsampleFactor);
float y = (float) convertLocationfromIJ(polygon.ypoints[i], yOrigin, downsampleFactor);
points.add(new Point2(x, y));
}
return points;
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class TestDistanceTools method test_detectionCentroidDistance2D.
@Test
public void test_detectionCentroidDistance2D() {
double radius = 5;
List<Point2> tumorCoordinates = Arrays.asList(new Point2(100, 100), new Point2(100, 200), new Point2(150, 150));
List<Point2> stromaCoordinates = Arrays.asList(new Point2(120, 100), new Point2(100, 210));
var planes = Arrays.asList(ImagePlane.getDefaultPlane(), ImagePlane.getPlane(2, 0), ImagePlane.getPlane(1, 1));
for (var sourcePlane : planes) {
for (var targetPlane : planes) {
var tumorDetections = tumorCoordinates.stream().map(p -> PathObjects.createDetectionObject(ROIs.createEllipseROI(p.getX() - radius, p.getY() - radius, radius * 2, radius * 2, sourcePlane), PathClassFactory.getPathClass(StandardPathClasses.TUMOR))).collect(Collectors.toList());
var stromaDetections = stromaCoordinates.stream().map(p -> PathObjects.createDetectionObject(ROIs.createEllipseROI(p.getX() - radius, p.getY() - radius, radius * 2, radius * 2, targetPlane), PathClassFactory.getPathClass(StandardPathClasses.STROMA))).collect(Collectors.toList());
if (sourcePlane.equals(targetPlane)) {
// Distance to stroma, default pixels
DistanceTools.centroidToCentroidDistance2D(tumorDetections, stromaDetections, 1.0, 1.0, "Distance to stroma");
assertEquals(tumorDetections.get(0).getMeasurementList().getMeasurementValue("Distance to stroma"), 20, 0.0001);
assertEquals(tumorDetections.get(1).getMeasurementList().getMeasurementValue("Distance to stroma"), 10, 0.0001);
assertEquals(tumorDetections.get(2).getMeasurementList().getMeasurementValue("Distance to stroma"), Math.sqrt(30 * 30 + 50 * 50), 0.0001);
// Distance to stroma, scaled pixels
DistanceTools.centroidToCentroidDistance2D(tumorDetections, stromaDetections, 2.0, 2.0, "Distance to stroma");
assertEquals(tumorDetections.get(0).getMeasurementList().getMeasurementValue("Distance to stroma"), 20 * 2, 0.0001);
assertEquals(tumorDetections.get(1).getMeasurementList().getMeasurementValue("Distance to stroma"), 10 * 2, 0.0001);
assertEquals(tumorDetections.get(2).getMeasurementList().getMeasurementValue("Distance to stroma"), Math.sqrt(30 * 30 * 4 + 50 * 50 * 4), 0.0001);
// Distance to stroma, scaled non-square pixels
DistanceTools.centroidToCentroidDistance2D(tumorDetections, stromaDetections, 1.4, 1.6, "Distance to stroma");
assertEquals(tumorDetections.get(0).getMeasurementList().getMeasurementValue("Distance to stroma"), 20 * 1.4, 0.0001);
assertEquals(tumorDetections.get(1).getMeasurementList().getMeasurementValue("Distance to stroma"), 10 * 1.6, 0.0001);
assertEquals(tumorDetections.get(2).getMeasurementList().getMeasurementValue("Distance to stroma"), Math.sqrt(30 * 30 * 1.4 * 1.4 + 50 * 50 * 1.6 * 1.6), 0.0001);
// Ensure no other measurements added
for (var stroma : stromaDetections) {
assertFalse(stroma.getMeasurementList().containsNamedMeasurement("Distance to stroma"));
assertTrue(Double.isNaN(stroma.getMeasurementList().getMeasurementValue("Distance to stroma")));
}
for (var tumor : tumorDetections) {
assertTrue(tumor.getMeasurementList().containsNamedMeasurement("Distance to stroma"));
}
} else {
// Ensure no measurements added
DistanceTools.centroidToCentroidDistance2D(tumorDetections, stromaDetections, 1.0, 1.0, "Distance to stroma");
for (var tumor : tumorDetections) {
// Currently, we don't add a measurement if not on the same plane
// assertTrue(tumor.getMeasurementList().containsNamedMeasurement("Distance to stroma"));
assertTrue(Double.isNaN(tumor.getMeasurementList().getMeasurementValue("Distance to stroma")));
}
for (var stroma : stromaDetections) {
assertFalse(stroma.getMeasurementList().containsNamedMeasurement("Distance to stroma"));
assertTrue(Double.isNaN(stroma.getMeasurementList().getMeasurementValue("Distance to stroma")));
}
}
}
}
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PointsTool method addPoint.
/**
* Add a point only if it has a separation of at least minimumSeparation from all other points
* currently stored, otherwise do nothing.
*
* @param x
* @param y
* @param minimumSeparation
*/
private ROI addPoint(final ROI points, final double x, final double y, final double minimumSeparation, final ImagePlane plane) {
// Can't add NaN points
if (Double.isNaN(x + y))
return points;
List<Point2> pointsList = points.getAllPoints();
if (minimumSeparation > 0) {
// Test for separation
double threshold = minimumSeparation * minimumSeparation;
for (Point2 p : pointsList) if (p.distanceSq(x, y) < threshold)
return points;
}
List<Point2> pointsList2 = new ArrayList<>(pointsList);
pointsList2.add(new Point2(x, y));
return ROIs.createPointsROI(pointsList2, plane);
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PointsROI method getNearest.
/**
* Identify the closest point within a specified distance to coordinates x,y - or null if no points are found.
* @param x
* @param y
* @param maxDist
* @return
*/
public Point2 getNearest(double x, double y, double maxDist) {
double maxDistSq = maxDist * maxDist;
Point2 pClosest = null;
double distClosestSq = Double.POSITIVE_INFINITY;
for (Point2 p : points) {
double distSq = p.distanceSq(x, y);
if (distSq <= maxDistSq && distSq < distClosestSq) {
pClosest = p;
distClosestSq = distSq;
}
}
return pClosest;
}
Aggregations