Search in sources :

Example 71 with ROI

use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.

the class MoveTool method mousePressed.

@Override
public void mousePressed(MouseEvent e) {
    if (mover != null)
        mover.stopMoving();
    super.mousePressed(e);
    if (!e.isPrimaryButtonDown() || e.isConsumed())
        return;
    var viewer = getViewer();
    boolean snapping = false;
    Point2D p = mouseLocationToImage(e, false, snapping);
    double xx = p.getX();
    double yy = p.getY();
    // TODO: Consider whether Alt & the Shortcut key should both have the same effect
    if (e.getClickCount() > 1 || e.isAltDown() || e.isShortcutDown()) {
        boolean selected = false;
        if (e.isAltDown() || e.isShortcutDown())
            selected = tryToSelect(xx, yy, e.getClickCount() - 1, true, true);
        else
            selected = tryToSelect(xx, yy, e.getClickCount() - 2, false);
        e.consume();
        pDragging = null;
        if (!selected && PathPrefs.doubleClickToZoomProperty().get()) {
            double downsample = viewer.getDownsampleFactor();
            if (e.isAltDown() || e.isShortcutDown())
                downsample *= 2;
            else
                downsample /= 2;
            viewer.setDownsampleFactor(downsample, e.getX(), e.getY());
        }
        return;
    }
    if (!viewer.isSpaceDown() && viewer.getHierarchy() != null) {
        // Set the current parent object based on the first click
        PathObject currentObject = viewer.getSelectedObject();
        // PathObject parent = currentObject == null ? null : currentObject.getParent();
        // if (parent != null && parent.isDetection())
        // parent = null;
        // setConstrainedAreaParent(viewer.getHierarchy(), parent, currentObject);
        setConstrainedAreaParent(viewer.getHierarchy(), xx, yy, Collections.singleton(currentObject));
        // See if we can get a handle to edit the ROI
        // Don't want to edit detections / TMA cores
        ROI currentROI = viewer.getCurrentROI();
        RoiEditor editor = viewer.getROIEditor();
        // Try dealing with having a ROI first
        if (currentROI != null) {
            if (editor.getROI() == currentROI) {
                // 1.5 increases the range; the handle radius alone is too small a distance, especially if the handles are painted as squares -
                // because 1.5 >~ sqrt(2) it ensures that at least the entire square is 'active' (and a bit beyond it)
                double search = viewer.getMaxROIHandleSize() * 0.75;
                // search = 1;
                if (editor.grabHandle(xx, yy, search, e.isShiftDown()))
                    e.consume();
            }
            if (!e.isConsumed() && canAdjust(currentObject) && (RoiTools.areaContains(currentROI, xx, yy) || getSelectableObjectList(xx, yy).contains(currentObject))) {
                // If we have a translatable ROI, try starting translation
                if (editor.startTranslation(xx, yy, PathPrefs.usePixelSnappingProperty().get() && currentROI.isArea()))
                    e.consume();
            }
            if (e.isConsumed()) {
                pDragging = null;
                return;
            }
        }
    }
    // Store point for drag-to-pan
    pDragging = p;
// viewer.setDoFasterRepaint(true); // Turn on if dragging is too slow
}
Also used : PathObject(qupath.lib.objects.PathObject) RoiEditor(qupath.lib.roi.RoiEditor) Point2D(java.awt.geom.Point2D) ROI(qupath.lib.roi.interfaces.ROI)

Example 72 with ROI

use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.

the class MoveTool method mouseDragged.

@Override
public void mouseDragged(MouseEvent e) {
    if (mover != null)
        mover.stopMoving();
    super.mouseDragged(e);
    if (!e.isPrimaryButtonDown() || e.isConsumed())
        return;
    // Handle ROIs if the spacebar isn't down
    var viewer = getViewer();
    if (!viewer.isSpaceDown()) {
        RoiEditor editor = viewer.getROIEditor();
        Point2D p = mouseLocationToImage(e, true, false);
        // Try moving handle
        if (editor != null && editor.hasActiveHandle()) {
            double x = p.getX();
            double y = p.getY();
            if (PathPrefs.usePixelSnappingProperty().get() && editor.getROI() != null && editor.getROI().isArea()) {
                x = (int) x;
                y = (int) y;
            }
            ROI updatedROI = editor.setActiveHandlePosition(x, y, viewer.getDownsampleFactor() / 2.0, e.isShiftDown());
            if (updatedROI == null)
                // This shouldn't occur...?
                logger.warn("Updated ROI is null! Will be skipped...");
            else {
                PathObject selectedObject = viewer.getSelectedObject();
                if (selectedObject.getROI() != updatedROI && selectedObject instanceof PathROIObject)
                    ((PathROIObject) selectedObject).setROI(updatedROI);
                // TODO: Check event firing frequency!
                viewer.getHierarchy().fireObjectsChangedEvent(this, Collections.singleton(selectedObject), true);
                // viewer.repaint();
                e.consume();
                return;
            }
        }
        // Try to translate, if that's what is happening
        ROI currentROI = viewer.getCurrentROI();
        if (editor != null && editor.isTranslating()) {
            Rectangle2D boundsBefore = AwtTools.getBounds2D(currentROI);
            ROI translatedROI = editor.updateTranslation(p.getX(), p.getY(), viewer.getServerBounds());
            if (translatedROI != null) {
                Rectangle2D boundsAfter = AwtTools.getBounds2D(currentROI);
                Rectangle2D boundsIntersection = new Rectangle2D.Double();
                Rectangle2D.union(boundsBefore, boundsAfter, boundsIntersection);
                ((PathROIObject) viewer.getSelectedObject()).setROI(translatedROI);
                viewer.getHierarchy().fireObjectsChangedEvent(this, Collections.singleton(viewer.getSelectedObject()), true);
            // System.err.println("Changing... " + viewer.getHierarchy().nObjects());
            // viewer.repaintImageRegion(boundsIntersection, false);
            }
            pDragging = null;
            return;
        }
        // Try to select objects, if alt is down
        if (e.isAltDown()) {
            tryToSelect(p.getX(), p.getY(), e.getClickCount() - 1, true, false);
            e.consume();
            return;
        }
    }
    // Don't allow dragging if 'zoom to fit' selected
    if (viewer.getZoomToFit())
        return;
    // If we don't have a previous point, we aren't dragging (e.g. there was an alt-click)
    if (pDragging == null)
        return;
    // Extract previous coordinates so we can reuse the Point2D object
    double xPrevious = pDragging.getX();
    double yPrevious = pDragging.getY();
    // Calculate how much the image was dragged
    pDragging = mouseLocationToImage(e, false, false);
    dx = pDragging.getX() - xPrevious;
    dy = pDragging.getY() - yPrevious;
    // Update the viewer
    viewer.setDoFasterRepaint(true);
    viewer.setCenterPixelLocation(viewer.getCenterPixelX() - dx, viewer.getCenterPixelY() - dy);
    // viewer.setDoFasterRepaint(false);
    pDragging = mouseLocationToImage(e, false, false);
    lastDragTimestamp = System.currentTimeMillis();
}
Also used : PathObject(qupath.lib.objects.PathObject) RoiEditor(qupath.lib.roi.RoiEditor) Point2D(java.awt.geom.Point2D) Rectangle2D(java.awt.geom.Rectangle2D) PathROIObject(qupath.lib.objects.PathROIObject) ROI(qupath.lib.roi.interfaces.ROI)

Example 73 with ROI

use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.

the class AbstractPathDraggingROITool method mouseDragged.

@Override
public void mouseDragged(MouseEvent e) {
    super.mouseDragged(e);
    if (!e.isPrimaryButtonDown()) {
        return;
    }
    var viewer = getViewer();
    ROI currentROI = viewer.getCurrentROI() instanceof ROI ? (ROI) viewer.getCurrentROI() : null;
    RoiEditor editor = viewer.getROIEditor();
    if (currentROI != null && editor.getROI() == currentROI && editor.hasActiveHandle()) {
        PathObject pathObject = viewer.getSelectedObject();
        Point2D p = mouseLocationToImage(e, true, requestPixelSnapping());
        ROI roiUpdated = editor.setActiveHandlePosition(p.getX(), p.getY(), 0.25, e.isShiftDown());
        if (roiUpdated != currentROI) {
            ((PathROIObject) pathObject).setROI(roiUpdated);
            viewer.repaint();
        }
        viewer.getHierarchy().fireObjectsChangedEvent(this, Collections.singleton(pathObject), true);
        // editor.setActiveHandlePosition(x, y, minDisplacement, shiftDown)
        // currentROI.updateAdjustment(p.getX(), p.getY(), e.isShiftDown());
        viewer.repaint();
    }
}
Also used : PathObject(qupath.lib.objects.PathObject) RoiEditor(qupath.lib.roi.RoiEditor) Point2D(java.awt.geom.Point2D) PathROIObject(qupath.lib.objects.PathROIObject) ROI(qupath.lib.roi.interfaces.ROI)

Example 74 with ROI

use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.

the class BrushTool method mousePressed.

@Override
public void mousePressed(MouseEvent e) {
    // super.mousePressed(e);
    if (!e.isPrimaryButtonDown() || e.isConsumed()) {
        return;
    }
    ensureCursorType(getRequestedCursor());
    var viewer = getViewer();
    PathObjectHierarchy hierarchy = viewer.getHierarchy();
    if (hierarchy == null)
        return;
    PathObject currentObject = viewer.getSelectedObject();
    // Determine if we are creating a new object
    // boolean createNew = currentObject == null || e.getClickCount() > 1;// || (!currentObject.getROI().contains(p.getX(), p.getY()) && !e.isAltDown());
    Point2D p = mouseLocationToImage(e, false, requestPixelSnapping());
    double xx = p.getX();
    double yy = p.getY();
    if (xx < 0 || yy < 0 || xx >= viewer.getServerWidth() || yy >= viewer.getServerHeight())
        return;
    // boolean createNew = currentObject == null || !(currentObject instanceof PathAnnotationObject) || (currentObject.hasChildren()) || (PathPrefs.getBrushCreateNewObjects() && !ROIHelpers.areaContains(currentObject.getROI(), p.getX(), p.getY()) && !isSubtractMode(e));
    boolean createNew = currentObject == null || PathPrefs.selectionModeProperty().get() || !(currentObject instanceof PathAnnotationObject) || (!currentObject.isEditable()) || currentObject.getROI().getZ() != viewer.getZPosition() || currentObject.getROI().getT() != viewer.getTPosition() || (!e.isShiftDown() && PathPrefs.brushCreateNewObjectsProperty().get() && !RoiTools.areaContains(currentObject.getROI(), p.getX(), p.getY()) && !isSubtractMode(e));
    if (isSubtractMode(e))
        createNew = false;
    // See if, rather than creating something, we can instead reactivate a current object
    boolean multipleClicks = e.getClickCount() > 1;
    if (!PathPrefs.selectionModeProperty().get() && (multipleClicks || (createNew && !e.isShiftDown()))) {
        // See if, rather than creating something, we can instead reactivate a current object
        if (multipleClicks) {
            PathObject objectSelectable = getSelectableObject(p.getX(), p.getY(), e.getClickCount() - 1);
            if (objectSelectable != null && objectSelectable.isEditable() && objectSelectable.hasROI() && objectSelectable.getROI().isArea()) {
                createNew = false;
                viewer.setSelectedObject(objectSelectable);
                currentObject = objectSelectable;
            } else if (createNew) {
                viewer.setSelectedObject(null);
                currentObject = null;
            }
        } else if (!PathPrefs.selectionModeProperty().get()) {
            List<PathObject> listSelectable = getSelectableObjectList(p.getX(), p.getY());
            PathObject objectSelectable = null;
            for (int i = listSelectable.size() - 1; i >= 0; i--) {
                PathObject temp = listSelectable.get(i);
                if (temp.isEditable() && temp instanceof PathAnnotationObject && temp.hasROI() && temp.getROI().isArea()) {
                    // temp.getROI() instanceof AreaROI) {
                    objectSelectable = temp;
                    break;
                }
            }
            if (objectSelectable != null) {
                createNew = false;
                viewer.setSelectedObject(objectSelectable);
                currentObject = objectSelectable;
            } else if (createNew) {
                viewer.setSelectedObject(null);
                currentObject = null;
            }
        }
    }
    // Can only modify annotations
    if (!createNew && !(currentObject != null && currentObject.isAnnotation() && currentObject.isEditable() && RoiTools.isShapeROI(currentObject.getROI())))
        return;
    // Get the parent, in case we need to constrain the shape
    // PathObject parent = null;
    // if (currentObject != null) {
    // parent = currentObject.getParent();
    // }
    // var currentObject2 = currentObject;
    // if (parent == null || parent.isDetection()) {
    // parent = getSelectableObjectList(p.getX(), p.getY())
    // .stream()
    // .filter(o -> !o.isDetection() && o != currentObject2)
    // .findFirst()
    // .orElseGet(() -> null);
    // }
    // setConstrainedAreaParent(hierarchy, parent, currentObject);
    setConstrainedAreaParent(hierarchy, xx, yy, Collections.singleton(currentObject));
    // Need to remove the object from the hierarchy while editing it
    if (!createNew && currentObject != null) {
        hierarchy.removeObjectWithoutUpdate(currentObject, true);
    }
    ROI shapeROI = createNew ? null : currentObject.getROI();
    if (createNew) {
        // Reset this
        creatingTiledROI = false;
        this.currentObject = createNewAnnotation(e, p.getX(), p.getY());
        viewer.getROIEditor().setROI(null);
    } else {
        this.currentObject = getUpdatedObject(e, shapeROI, currentObject, -1);
        viewer.setSelectedObject(this.currentObject);
        // Avoids handles appearing?
        viewer.getROIEditor().setROI(null);
    }
    lastPoint = p;
}
Also used : PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) Point2D(java.awt.geom.Point2D) List(java.util.List) RectangleROI(qupath.lib.roi.RectangleROI) ROI(qupath.lib.roi.interfaces.ROI)

Example 75 with ROI

use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.

the class PointsTool method handleAltClick.

/**
 * Alt-clicks remove the selected point, or selects a new 'family' of points (i.e. a different object) if
 * a point from the current object isn't clicked.
 *
 * @param x
 * @param y
 * @param currentObject
 * @return
 */
private boolean handleAltClick(double x, double y, PathObject currentObject) {
    var viewer = getViewer();
    var viewerPlane = viewer.getImagePlane();
    PathObjectHierarchy hierarchy = viewer.getHierarchy();
    double distance = PathPrefs.pointRadiusProperty().get();
    // Remove a point if the current selection has one
    if (currentObject != null && PathObjectTools.hasPointROI(currentObject)) {
        PointsROI points = (PointsROI) currentObject.getROI();
        if (points.getImagePlane().equals(viewerPlane)) {
            ROI points2 = removeNearbyPoint(points, x, y, distance);
            if (points != points2) {
                ((PathROIObject) currentObject).setROI(points2);
                hierarchy.updateObject(currentObject, false);
                // hierarchy.fireHierarchyChangedEvent(this, currentObject);
                return true;
            }
        }
    }
    // Activate a points object if there is one
    for (PathObject pathObject : hierarchy.getPointObjects(PathObject.class)) {
        // Don't check the current object again
        if (pathObject == currentObject || !pathObject.getROI().getImagePlane().equals(viewerPlane))
            continue;
        // See if we've almost clicked on a point
        if (((PointsROI) pathObject.getROI()).getNearest(x, y, distance) != null) {
            viewer.setSelectedObject(pathObject);
            // hierarchy.getSelectionModel().setSelectedPathObject(pathObject);
            return true;
        }
    }
    // Select nothing
    viewer.setSelectedObject(null);
    return true;
}
Also used : PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) PathObject(qupath.lib.objects.PathObject) PointsROI(qupath.lib.roi.PointsROI) PathROIObject(qupath.lib.objects.PathROIObject) ROI(qupath.lib.roi.interfaces.ROI) PointsROI(qupath.lib.roi.PointsROI)

Aggregations

ROI (qupath.lib.roi.interfaces.ROI)87 PathObject (qupath.lib.objects.PathObject)61 ArrayList (java.util.ArrayList)31 BufferedImage (java.awt.image.BufferedImage)24 PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)24 IOException (java.io.IOException)20 RegionRequest (qupath.lib.regions.RegionRequest)19 List (java.util.List)17 Collectors (java.util.stream.Collectors)17 RectangleROI (qupath.lib.roi.RectangleROI)17 Logger (org.slf4j.Logger)16 LoggerFactory (org.slf4j.LoggerFactory)16 PolygonROI (qupath.lib.roi.PolygonROI)16 PathAnnotationObject (qupath.lib.objects.PathAnnotationObject)15 Point2D (java.awt.geom.Point2D)14 Collection (java.util.Collection)14 Collections (java.util.Collections)14 Geometry (org.locationtech.jts.geom.Geometry)14 PathClass (qupath.lib.objects.classes.PathClass)14 ImagePlane (qupath.lib.regions.ImagePlane)13