Search in sources :

Example 1 with PathObjectConnectionGroup

use of qupath.lib.objects.PathObjectConnectionGroup in project qupath by qupath.

the class PathHierarchyPaintingHelper method paintConnections.

/**
 * Paint connections between objects (e.g. from Delaunay triangulation).
 *
 * @param connections
 * @param hierarchy
 * @param g2d
 * @param color
 * @param downsampleFactor
 */
public static void paintConnections(final PathObjectConnections connections, final PathObjectHierarchy hierarchy, Graphics2D g2d, final Color color, final double downsampleFactor) {
    if (hierarchy == null || connections == null || connections.isEmpty())
        return;
    float alpha = (float) (1f - downsampleFactor / 5);
    alpha = Math.min(alpha, 0.25f);
    float thickness = PathPrefs.detectionStrokeThicknessProperty().get();
    if (alpha < .1f || thickness / downsampleFactor <= 0.5)
        return;
    g2d = (Graphics2D) g2d.create();
    // Shape clipShape = g2d.getClip();
    g2d.setStroke(getCachedStroke(thickness));
    // g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha * .5f));
    // g2d.setColor(ColorToolsAwt.getColorWithOpacity(getPreferredOverlayColor(), 1));
    g2d.setColor(ColorToolsAwt.getColorWithOpacity(color.getRGB(), alpha));
    // g2d.setColor(Color.BLACK);
    Line2D line = new Line2D.Double();
    // We can have trouble whenever two objects are outside the clip, but their connections would be inside it
    // Here, we just enlarge the region (by quite a lot)
    // It's not guaranteed to work, but it usually does... and avoids much expensive computations
    Rectangle bounds = g2d.getClipBounds();
    int factor = 1;
    Rectangle bounds2 = factor > 0 ? new Rectangle(bounds.x - bounds.width * factor, bounds.y - bounds.height * factor, bounds.width * (factor * 2 + 1), bounds.height * (factor * 2 + 1)) : bounds;
    ImageRegion imageRegion = AwtTools.getImageRegion(bounds2, 0, 0);
    // ImageRegion imageRegion = AwtTools.getImageRegion(bounds, 0, 0);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
    // g2d.draw(g2d.getClipBounds());
    Collection<PathObject> pathObjects = hierarchy.getObjectsForRegion(PathDetectionObject.class, imageRegion, null);
    // double threshold = downsampleFactor*downsampleFactor*4;
    for (PathObject pathObject : pathObjects) {
        ROI roi = PathObjectTools.getROI(pathObject, true);
        double x1 = roi.getCentroidX();
        double y1 = roi.getCentroidY();
        for (PathObjectConnectionGroup dt : connections.getConnectionGroups()) {
            for (PathObject siblingObject : dt.getConnectedObjects(pathObject)) {
                ROI roi2 = PathObjectTools.getROI(siblingObject, true);
                double x2 = roi2.getCentroidX();
                double y2 = roi2.getCentroidY();
                if (bounds.intersectsLine(x1, y1, x2, y2)) {
                    line.setLine(x1, y1, x2, y2);
                    g2d.draw(line);
                }
            }
        }
    }
    g2d.dispose();
}
Also used : PathObject(qupath.lib.objects.PathObject) Rectangle(java.awt.Rectangle) ImageRegion(qupath.lib.regions.ImageRegion) PathObjectConnectionGroup(qupath.lib.objects.PathObjectConnectionGroup) Line2D(java.awt.geom.Line2D) EllipseROI(qupath.lib.roi.EllipseROI) PointsROI(qupath.lib.roi.PointsROI) RectangleROI(qupath.lib.roi.RectangleROI) LineROI(qupath.lib.roi.LineROI) ROI(qupath.lib.roi.interfaces.ROI)

Aggregations

Rectangle (java.awt.Rectangle)1 Line2D (java.awt.geom.Line2D)1 PathObject (qupath.lib.objects.PathObject)1 PathObjectConnectionGroup (qupath.lib.objects.PathObjectConnectionGroup)1 ImageRegion (qupath.lib.regions.ImageRegion)1 EllipseROI (qupath.lib.roi.EllipseROI)1 LineROI (qupath.lib.roi.LineROI)1 PointsROI (qupath.lib.roi.PointsROI)1 RectangleROI (qupath.lib.roi.RectangleROI)1 ROI (qupath.lib.roi.interfaces.ROI)1