/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Icy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package plugins.kernel.roi.roi2d;
import icy.painter.Anchor2D;
import icy.painter.LineAnchor2D;
import icy.resource.ResourceUtil;
import icy.roi.ROI;
import icy.type.geom.Polyline2D;
import icy.type.point.Point2DUtil;
import icy.type.point.Point5D;
import icy.util.XMLUtil;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* @author Stephane
*/
public class ROI2DPolyLine extends ROI2DShape
{
protected class ROI2DPolyLineAnchor2D extends LineAnchor2D
{
public ROI2DPolyLineAnchor2D(Point2D position, Color color, Color selectedColor)
{
super(position, color, selectedColor);
}
@Override
protected Anchor2D getPreviousPoint()
{
final int ind = controlPoints.indexOf(this);
if (ind == 0)
{
if (controlPoints.size() > 1)
return controlPoints.get(1);
return null;
}
if (ind != -1)
return controlPoints.get(ind - 1);
return null;
}
}
public static final String ID_POINTS = "points";
public static final String ID_POINT = "point";
/**
* @deprecated
*/
@Deprecated
public ROI2DPolyLine(Point2D pt, boolean cm)
{
this(pt);
}
/**
*
*/
public ROI2DPolyLine(Point2D pt)
{
super(new Polyline2D());
final Anchor2D point = createAnchor(pt);
point.setSelected(true);
addPoint(point);
// set icon (default name is defined by getDefaultName())
setIcon(ResourceUtil.ICON_ROI_POLYLINE);
}
/**
* Generic constructor for interactive mode
*/
public ROI2DPolyLine(Point5D pt)
{
this(pt.toPoint2D());
// getOverlay().setMousePos(pt);
}
public ROI2DPolyLine(Polygon polygon)
{
this(new Point2D.Double());
setPolygon(polygon);
}
public ROI2DPolyLine(Polyline2D polyline)
{
this(new Point2D.Double());
setPolyline2D(polyline);
}
public ROI2DPolyLine(List<Point2D> points)
{
this(new Point2D.Double());
setPoints(points);
}
public ROI2DPolyLine()
{
this(new Point2D.Double());
}
@Override
public String getDefaultName()
{
return "PolyLine2D";
}
@Override
protected Anchor2D createAnchor(Point2D pos)
{
return new ROI2DPolyLineAnchor2D(pos, getColor(), getFocusedColor());
}
// @Override
// protected ROI2DPolyLinePainter createPainter()
// {
// return new ROI2DPolyLinePainter();
// }
/**
* @deprecated Use {@link #getPolyline2D()} instead
*/
@Deprecated
protected Path2D getPath()
{
return new Path2D.Double(shape);
}
public void setPoints(List<Point2D> pts)
{
beginUpdate();
try
{
removeAllPoint();
for (Point2D pt : pts)
addNewPoint(pt, false);
}
finally
{
endUpdate();
}
}
/**
* @deprecated Use {@link #setPoints(List)} instead.
*/
@Deprecated
public void setPoints(ArrayList<Point2D> pts)
{
setPoints((List<Point2D>) pts);
}
public Polyline2D getPolyline2D()
{
return (Polyline2D) shape;
}
public void setPolyline2D(Polyline2D polyline2D)
{
beginUpdate();
try
{
removeAllPoint();
for (int i = 0; i < polyline2D.npoints; i++)
addNewPoint(new Point2D.Double(polyline2D.xpoints[i], polyline2D.ypoints[i]), false);
}
finally
{
endUpdate();
}
}
public Polygon getPolygon()
{
return getPolyline2D().getPolygon2D().getPolygon();
}
public void setPolygon(Polygon polygon)
{
beginUpdate();
try
{
removeAllPoint();
for (int i = 0; i < polygon.npoints; i++)
addNewPoint(new Point2D.Double(polygon.xpoints[i], polygon.ypoints[i]), false);
}
finally
{
endUpdate();
}
}
@Override
public boolean contains(double x, double y)
{
return false;
}
@Override
public boolean contains(Point2D p)
{
return false;
}
@Override
public boolean contains(double x, double y, double w, double h)
{
return false;
}
@Override
public boolean contains(Rectangle2D r)
{
return false;
}
@Override
public boolean contains(ROI roi)
{
return false;
}
@Override
protected double getTotalDistance(List<Point2D> points, double factorX, double factorY)
{
// for polyline the total length don't need last point connection
return Point2DUtil.getTotalDistance(points, factorX, factorY, false);
}
@Override
public double computeNumberOfPoints()
{
return 0d;
}
@Override
protected void updateShape()
{
final int len;
final double[] ptsX;
final double[] ptsY;
synchronized (controlPoints)
{
len = controlPoints.size();
ptsX = new double[len];
ptsY = new double[len];
for (int i = 0; i < len; i++)
{
final Anchor2D pt = controlPoints.get(i);
ptsX[i] = pt.getX();
ptsY[i] = pt.getY();
}
}
final Polyline2D polyline2d = getPolyline2D();
// we can have a problem here if we try to redraw while we are modifying the polygon points
synchronized (polyline2d)
{
polyline2d.npoints = len;
polyline2d.xpoints = ptsX;
polyline2d.ypoints = ptsY;
polyline2d.calculatePath();
}
// call super method after shape has been updated
super.updateShape();
}
@Override
public boolean[] getBooleanMask(int x, int y, int w, int h, boolean inclusive)
{
if ((w <= 0) || (h <= 0))
return new boolean[0];
// this ROI doesn't contains area
if (!inclusive)
return new boolean[w * h];
final BufferedImage maskImg = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
final Graphics2D g = maskImg.createGraphics();
// draw shape in image
g.setColor(Color.white);
g.translate(-x, -y);
g.draw(shape);
g.dispose();
// use the image to define the mask
final byte[] maskData = ((DataBufferByte) maskImg.getRaster().getDataBuffer()).getData();
final boolean[] result = new boolean[w * h];
for (int i = 0; i < result.length; i++)
result[i] = (maskData[i] != 0);
return result;
}
@Override
public boolean loadFromXML(Node node)
{
beginUpdate();
try
{
if (!super.loadFromXML(node))
return false;
removeAllPoint();
final ArrayList<Node> nodesPoint = XMLUtil.getChildren(XMLUtil.getElement(node, ID_POINTS), ID_POINT);
if (nodesPoint != null)
{
for (Node n : nodesPoint)
{
final Anchor2D pt = createAnchor(new Point2D.Double());
pt.loadPositionFromXML(n);
addPoint(pt);
}
}
}
finally
{
endUpdate();
}
return true;
}
@Override
public boolean saveToXML(Node node)
{
if (!super.saveToXML(node))
return false;
final Element dependances = XMLUtil.setElement(node, ID_POINTS);
synchronized (controlPoints)
{
for (Anchor2D pt : controlPoints)
pt.savePositionToXML(XMLUtil.addElement(dependances, ID_POINT));
}
return true;
}
}