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;
}
}