package plugins.kernel.roi.tool; import icy.canvas.IcyCanvas; import icy.roi.ROI; import icy.roi.ROIUtil; import icy.sequence.Sequence; import icy.sequence.edit.ROIReplacesSequenceEdit; import icy.system.thread.ThreadUtil; import icy.type.point.Point5D; import icy.type.point.Point5D.Double; import icy.type.rectangle.Rectangle2DUtil; import java.awt.BasicStroke; import java.awt.Graphics2D; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; import java.util.ArrayList; import java.util.List; import plugins.kernel.roi.roi2d.ROI2DLine; /** * ROI Helper class for ROI cutting action * * @author Stephane */ public class ROILineCutter extends ROI2DLine { public class ROILineCutterPainter extends ROI2DLinePainter { @Override public void mouseReleased(MouseEvent e, Double imagePoint, IcyCanvas canvas) { super.mouseReleased(e, imagePoint, canvas); // do that in background as it can take sometime ThreadUtil.bgRun(new Runnable() { @Override public void run() { // get sequences where we are attached first final List<Sequence> sequences = getSequences(); // remove the ROI, we don't need it anymore... ROILineCutter.this.remove(false); // and do cutting now splitOverlappedROIs(sequences); } }); } @Override protected void drawShape(Graphics2D g, Sequence sequence, IcyCanvas canvas, boolean simplified) { final Line2D extendedLine = getExtendedLine(sequence); if (extendedLine != null) { final Graphics2D g2 = (Graphics2D) g.create(); // draw extended line g2.setStroke(new BasicStroke((float) (ROI.getAdjustedStroke(canvas, stroke) / 2f))); g2.setColor(getDisplayColor()); g2.draw(extendedLine); g2.dispose(); } super.drawShape(g, sequence, canvas, getLine(), simplified); } } public ROILineCutter(Point5D pt) { super(pt); } public ROILineCutter() { super(); } @Override protected ROI2DShapePainter createPainter() { return new ROILineCutterPainter(); } protected Line2D getExtendedLine(Sequence sequence) { return Rectangle2DUtil.getIntersectionLine(sequence.getBounds2D(), getLine()); } /** * This is a special function of this ROI, it cuts all overlapped ROI from given Sequences based on the current ROI * shape (line). * * @return <code>true</code> if some ROIS were cuts */ public boolean splitOverlappedROIs(List<Sequence> sequences) { boolean result = false; for (Sequence sequence : sequences) { final List<ROI> removedROI = new ArrayList<ROI>(); final List<ROI> addedROI = new ArrayList<ROI>(); sequence.beginUpdate(); try { for (ROI roi : sequence.getROIs()) { final List<ROI> resultRois = ROIUtil.split(roi, getLine()); // ROI was cut ? if (resultRois != null) { removedROI.add(roi); addedROI.addAll(resultRois); result = true; } } if (!removedROI.isEmpty()) { sequence.removeROIs(removedROI, false); sequence.addROIs(addedROI, false); // add undo operation sequence.addUndoableEdit(new ROIReplacesSequenceEdit(sequence, removedROI, addedROI)); } } finally { sequence.endUpdate(); } } return result; } }