Search in sources :

Example 6 with RoiEditor

use of qupath.lib.roi.RoiEditor in project qupath by qupath.

the class PointsTool method mouseReleased.

@Override
public void mouseReleased(MouseEvent e) {
    super.mouseReleased(e);
    if (e.getButton() != MouseButton.PRIMARY || e.isConsumed()) {
        return;
    }
    PointsROI points = getCurrentPoints();
    if (points == null)
        return;
    var viewer = getViewer();
    RoiEditor editor = viewer.getROIEditor();
    editor.resetActiveHandle();
    var currentObject = viewer.getSelectedObject();
    viewer.getHierarchy().updateObject(currentObject, false);
// viewer.getHierarchy().fireHierarchyChangedEvent(this, vcurrentObject);
// // Find out the coordinates in the image domain & update the adjustment
// Point2D p = viewer.componentPointToImagePoint(e.getX(), e.getY(), null, false);
// points.finishAdjusting(p.getX(), p.getY(), e.isShiftDown());
// points.resetMeasurements();
}
Also used : RoiEditor(qupath.lib.roi.RoiEditor) PointsROI(qupath.lib.roi.PointsROI)

Example 7 with RoiEditor

use of qupath.lib.roi.RoiEditor in project qupath by qupath.

the class MoveTool method mouseReleased.

@Override
public void mouseReleased(MouseEvent e) {
    super.mouseReleased(e);
    if (e.isConsumed())
        return;
    var viewer = getViewer();
    RoiEditor editor = viewer.getROIEditor();
    if (editor != null && (editor.hasActiveHandle() || editor.isTranslating())) {
        boolean roiChanged = (editor.isTranslating() && editor.finishTranslation()) || editor.hasActiveHandle();
        editor.resetActiveHandle();
        // if (editor.isTranslating())
        // editor.finishTranslation();
        e.consume();
        PathObject pathObject = viewer.getSelectedObject();
        if (requestParentClipping(e) && pathObject instanceof PathAnnotationObject) {
            ROI roiNew = refineROIByParent(pathObject.getROI());
            ((PathAnnotationObject) pathObject).setROI(roiNew);
        }
        if (pathObject != null && pathObject.hasROI() && pathObject.getROI().isEmpty()) {
            if (pathObject.getParent() != null)
                viewer.getHierarchy().removeObject(pathObject, true);
            viewer.setSelectedObject(null);
        } else {
            PathObjectHierarchy hierarchy = viewer.getHierarchy();
            if (pathObject instanceof TMACoreObject) {
                hierarchy.fireHierarchyChangedEvent(pathObject);
            } else if (pathObject != null) {
                // Handle ROI changes only if required
                if (roiChanged) {
                    var updatedROI = editor.getROI();
                    if (pathObject.getROI() != updatedROI && pathObject instanceof PathROIObject)
                        ((PathROIObject) pathObject).setROI(updatedROI);
                    // PathObject parentPrevious = pathObject.getParent();
                    hierarchy.removeObjectWithoutUpdate(pathObject, true);
                    if (getCurrentParent() == null || !PathPrefs.clipROIsForHierarchyProperty().get() || e.isShiftDown())
                        hierarchy.addPathObject(pathObject);
                    else
                        hierarchy.addPathObjectBelowParent(getCurrentParent(), pathObject, true);
                // PathObject parentNew = pathObject.getParent();
                // if (parentPrevious == parentNew)
                // hierarchy.fireHierarchyChangedEvent(this, parentPrevious);
                // else
                // hierarchy.fireHierarchyChangedEvent(this);
                }
            }
            viewer.setSelectedObject(pathObject);
        }
    }
    // Optionally continue a dragging movement until the canvas comes to a standstill
    if (pDragging != null && requestDynamicDragging && System.currentTimeMillis() - lastDragTimestamp < 100 && (dx * dx + dy * dy > viewer.getDownsampleFactor())) {
        mover = new ViewerMover(viewer);
        mover.startMoving(dx, dy, false);
    } else
        viewer.setDoFasterRepaint(false);
    // Make sure we don't have a previous point (to prevent weird dragging artefacts)
    pDragging = null;
// // If we were translating, stop
// if (editor.isTranslating()) {
// editor.finishTranslation();
// // TODO: Make this more efficient!
// viewer.getPathObjectHierarchy().fireHierarchyChangedEvent();
// return;
// }
}
Also used : PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) RoiEditor(qupath.lib.roi.RoiEditor) TMACoreObject(qupath.lib.objects.TMACoreObject) PathROIObject(qupath.lib.objects.PathROIObject) ROI(qupath.lib.roi.interfaces.ROI)

Example 8 with RoiEditor

use of qupath.lib.roi.RoiEditor in project qupath by qupath.

the class AbstractPathROITool method mousePressed.

@Override
public void mousePressed(MouseEvent e) {
    super.mousePressed(e);
    if (!e.isPrimaryButtonDown() || e.isConsumed()) {
        return;
    }
    var viewer = getViewer();
    PathObjectHierarchy hierarchy = viewer.getHierarchy();
    if (hierarchy == null)
        return;
    PathObject currentObject = viewer.getSelectedObject();
    ROI currentROI = currentObject == null ? null : currentObject.getROI();
    RoiEditor editor = viewer.getROIEditor();
    boolean adjustingPolygon = (currentROI instanceof PolygonROI || currentROI instanceof PolylineROI) && editor.getROI() == currentROI && (editor.isTranslating() || editor.hasActiveHandle());
    // If we're adjusting a polygon/polyline with an appropriate tool, return at leave it up to the tool to handle the custom things
    if (adjustingPolygon) {
        if (viewer.getActiveTool() == PathTools.POLYGON || viewer.getActiveTool() == PathTools.POLYLINE)
            return;
        else {
            viewer.getHierarchy().getSelectionModel().clearSelection();
            viewer.getHierarchy().fireHierarchyChangedEvent(currentObject);
        }
    }
    // Find out the coordinates in the image domain
    Point2D p2 = mouseLocationToImage(e, false, requestPixelSnapping());
    double xx = p2.getX();
    double yy = p2.getY();
    if (xx < 0 || yy < 0 || xx >= viewer.getServerWidth() || yy >= viewer.getServerHeight())
        return;
    // If we are double-clicking & we don't have a polygon, see if we can access a ROI
    if (!PathPrefs.selectionModeProperty().get() && e.getClickCount() > 1) {
        // Reset parent... for now
        resetConstrainedAreaParent();
        tryToSelect(xx, yy, e.getClickCount() - 2, false);
        e.consume();
        return;
    }
    // Set the current parent object based on the first click
    setConstrainedAreaParent(hierarchy, xx, yy, Collections.emptyList());
    // Create a new annotation
    PathObject pathObject = createNewAnnotation(e, xx, yy);
    if (pathObject == null)
        return;
    // Start editing the ROI immediately
    editor.setROI(pathObject.getROI());
    editor.grabHandle(xx, yy, viewer.getMaxROIHandleSize() * 1.5, e.isShiftDown());
}
Also used : PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) PolygonROI(qupath.lib.roi.PolygonROI) PathObject(qupath.lib.objects.PathObject) RoiEditor(qupath.lib.roi.RoiEditor) PolylineROI(qupath.lib.roi.PolylineROI) Point2D(java.awt.geom.Point2D) PolylineROI(qupath.lib.roi.PolylineROI) ROI(qupath.lib.roi.interfaces.ROI) PolygonROI(qupath.lib.roi.PolygonROI)

Example 9 with RoiEditor

use of qupath.lib.roi.RoiEditor 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 10 with RoiEditor

use of qupath.lib.roi.RoiEditor 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)

Aggregations

RoiEditor (qupath.lib.roi.RoiEditor)13 PathObject (qupath.lib.objects.PathObject)11 ROI (qupath.lib.roi.interfaces.ROI)11 Point2D (java.awt.geom.Point2D)10 PathROIObject (qupath.lib.objects.PathROIObject)9 PolygonROI (qupath.lib.roi.PolygonROI)5 PolylineROI (qupath.lib.roi.PolylineROI)5 PointsROI (qupath.lib.roi.PointsROI)3 PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)2 Rectangle2D (java.awt.geom.Rectangle2D)1 PathAnnotationObject (qupath.lib.objects.PathAnnotationObject)1 TMACoreObject (qupath.lib.objects.TMACoreObject)1 ImagePlane (qupath.lib.regions.ImagePlane)1