use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PointIOTest method test2ReadPoints.
@Test
public void test2ReadPoints() {
List<PathObject> pathObjects = null;
List<Double[]> pointsList = new ArrayList<>();
try {
pathObjects = PointIO.readPoints(file);
for (var pathObject : pathObjects) {
Point2 point = pathObject.getROI().getAllPoints().get(0);
pointsList.add(new Double[] { point.getX(), point.getY() });
}
} catch (IOException e) {
fail();
}
// Check that we have the same number of sets as originally
assertTrue(pathObjects.size() == 5);
// Check that all coordinates are the same
assertTrue(map.values().stream().allMatch(p -> {
return Arrays.stream(p).anyMatch(o -> pointsList.stream().anyMatch(m -> Arrays.equals(m, o)));
}));
// Check that classes were correctly assigned (Sets 3 & 5)
assertTrue(pathObjects.stream().filter(p -> isInside(map.get(3), p.getROI().getAllPoints().get(0))).allMatch(q -> q.getPathClass().getName().equals("Other")));
assertTrue(pathObjects.stream().filter(p -> isInside(map.get(5), p.getROI().getAllPoints().get(0))).allMatch(q -> q.getPathClass().getName().equals("Tumor")));
// Check that name were correctly assigned (Sets 4 & 5)
assertTrue(pathObjects.stream().filter(p -> isInside(map.get(4), p.getROI().getAllPoints().get(0))).allMatch(q -> q.getName().equals("foo")));
assertTrue(pathObjects.stream().filter(p -> isInside(map.get(5), p.getROI().getAllPoints().get(0))).allMatch(q -> q.getName().equals("bar")));
// Check C, Z and T
assertTrue(pathObjects.stream().allMatch(q -> {
if (isInside(map.get(2), q.getROI().getAllPoints().get(0)))
return (q.getROI().getC() == 2 && q.getROI().getZ() == 1 && q.getROI().getT() == 7);
else
return (q.getROI().getC() == -1 && q.getROI().getZ() == 0 && q.getROI().getT() == 0);
}));
file.delete();
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PointIOTest method test1WritePoints.
/**
* Uses the map generated in init() method and writes all its points down to a TSV file.
*/
@Test
public void test1WritePoints() {
List<PathObject> pathObjects = new ArrayList<>();
Integer[] colors = new Integer[] { -14336, -13487566, null, -3342337, -1305168 };
for (var entry : map.entrySet()) {
ArrayList<Point2> pointsList = new ArrayList<>();
int c = entry.getKey() == 2 ? 2 : -1;
int z = entry.getKey() == 2 ? 1 : 0;
int t = entry.getKey() == 2 ? 7 : 0;
for (var coord : entry.getValue()) {
pointsList.add(new Point2(coord[0], coord[1]));
}
ROI points = ROIs.createPointsROI(pointsList, ImagePlane.getPlaneWithChannel(c, z, t));
PathObject pathObject = PathObjects.createAnnotationObject(points);
if (entry.getKey() == 3)
pathObject.setPathClass(PathClassFactory.getPathClass("Other"));
if (entry.getKey() == 4)
pathObject.setName("foo");
else if (entry.getKey() == 5) {
pathObject.setPathClass(PathClassFactory.getPathClass("Tumor"));
pathObject.setName("bar");
}
pathObject.setColorRGB(colors[entry.getKey() - 1]);
pathObjects.add(pathObject);
}
try {
file = File.createTempFile("tmp", ".tsv");
PointIO.writePoints(file, pathObjects);
} catch (IOException e) {
fail();
}
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class ShapeSimplifier method simplifyPolygonPoints.
/**
* Create a simplified polygon (fewer coordinates) using method based on Visvalingam’s Algorithm.
* The input is a list of points (the vertices) belonging to a closed polygon.
* This list is modified in place.
* <p>
* See references:
* https://hydra.hull.ac.uk/resources/hull:8338
* https://www.jasondavies.com/simplify/
* http://bost.ocks.org/mike/simplify/
*
* @param points
* @param altitudeThreshold
*/
public static void simplifyPolygonPoints(final List<Point2> points, final double altitudeThreshold) {
if (points.size() <= 1)
return;
// Remove duplicates first
var iter = points.iterator();
Point2 lastPoint = iter.next();
while (iter.hasNext()) {
var nextPoint = iter.next();
if (nextPoint.equals(lastPoint))
iter.remove();
else
lastPoint = nextPoint;
}
if (lastPoint.equals(points.get(0)))
iter.remove();
if (points.size() <= 3)
return;
int n = points.size();
// Populate the priority queue
PriorityQueue<PointWithArea> queue = new PriorityQueue<>();
Point2 pPrevious = points.get(points.size() - 1);
Point2 pCurrent = points.get(0);
PointWithArea pwaPrevious = null;
PointWithArea pwaFirst = null;
for (int i = 0; i < n; i++) {
Point2 pNext = points.get((i + 1) % n);
PointWithArea pwa = new PointWithArea(pCurrent, calculateArea(pPrevious, pCurrent, pNext));
pwa.setPrevious(pwaPrevious);
if (pwaPrevious != null)
pwaPrevious.setNext(pwa);
queue.add(pwa);
pwaPrevious = pwa;
pPrevious = pCurrent;
pCurrent = pNext;
// Handle first and last cases for closed polygon
if (i == n - 1) {
pwa.setNext(pwaFirst);
pwaFirst.setPrevious(pwa);
} else if (i == 0)
pwaFirst = pwa;
}
double maxArea = 0;
int minSize = Math.max(n / 100, 3);
Set<Point2> toRemove = new HashSet<>();
while (queue.size() > minSize) {
PointWithArea pwa = queue.poll();
// logger.info("BEFORE: " + pwa + " (counter " + counter + ")");
// Altitude check (?)
double altitude = pwa.getArea() * 2 / pwa.getNext().getPoint().distance(pwa.getPrevious().getPoint());
if (altitude > altitudeThreshold)
break;
if (pwa.getArea() < maxArea)
pwa.setArea(maxArea);
else
maxArea = pwa.getArea();
// Remove the point & update accordingly
// points.remove(pwa.getPoint());
toRemove.add(pwa.getPoint());
pwaPrevious = pwa.getPrevious();
PointWithArea pwaNext = pwa.getNext();
pwaPrevious.setNext(pwaNext);
pwaPrevious.updateArea();
pwaNext.setPrevious(pwaPrevious);
pwaNext.updateArea();
// Reinsert into priority queue
queue.remove(pwaPrevious);
queue.remove(pwaNext);
queue.add(pwaPrevious);
queue.add(pwaNext);
// logger.info(pwa);
}
points.removeAll(toRemove);
}
Aggregations