001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package plugins.kernel.roi.roi2d; 020 021import icy.painter.Anchor2D; 022import icy.painter.LineAnchor2D; 023import icy.resource.ResourceUtil; 024import icy.type.geom.Polygon2D; 025import icy.type.point.Point5D; 026import icy.util.XMLUtil; 027 028import java.awt.Color; 029import java.awt.Polygon; 030import java.awt.geom.Path2D; 031import java.awt.geom.Point2D; 032import java.util.ArrayList; 033import java.util.List; 034 035import org.w3c.dom.Element; 036import org.w3c.dom.Node; 037 038/** 039 * ROI 2D polygon class. 040 * 041 * @author Stephane 042 */ 043public class ROI2DPolygon extends ROI2DShape 044{ 045 protected class ROI2DPolygonAnchor2D extends LineAnchor2D 046 { 047 public ROI2DPolygonAnchor2D(Point2D position, Color color, Color selectedColor) 048 { 049 super(position, color, selectedColor); 050 } 051 052 @Override 053 protected Anchor2D getPreviousPoint() 054 { 055 final int ind = controlPoints.indexOf(this); 056 057 if (ind == 0) 058 { 059 if (controlPoints.size() > 1) 060 return controlPoints.get(1); 061 062 return null; 063 } 064 065 if (ind != -1) 066 return controlPoints.get(ind - 1); 067 068 return null; 069 } 070 } 071 072 public static final String ID_POINTS = "points"; 073 public static final String ID_POINT = "point"; 074 075 /** 076 * @deprecated 077 */ 078 @Deprecated 079 public ROI2DPolygon(Point2D pt, boolean cm) 080 { 081 this(pt); 082 } 083 084 public ROI2DPolygon(Point2D pt) 085 { 086 super(new Polygon2D()); 087 088 final Anchor2D point = createAnchor(pt); 089 point.setSelected(true); 090 addPoint(point); 091 092 // set icon (default name is defined by getDefaultName()) 093 setIcon(ResourceUtil.ICON_ROI_POLYGON); 094 } 095 096 /** 097 * Generic constructor for interactive mode 098 */ 099 public ROI2DPolygon(Point5D pt) 100 { 101 this(pt.toPoint2D()); 102 // getOverlay().setMousePos(pt); 103 } 104 105 public ROI2DPolygon(List<Point2D> points) 106 { 107 this(new Point2D.Double()); 108 109 setPoints(points); 110 unselectAllPoints(); 111 } 112 113 /** 114 * @deprecated Better to use {@link #ROI2DPolygon(Polygon2D)} instead to have double point precision 115 */ 116 @Deprecated 117 public ROI2DPolygon(Polygon polygon) 118 { 119 this(new Point2D.Double()); 120 121 setPolygon(polygon); 122 unselectAllPoints(); 123 } 124 125 public ROI2DPolygon(Polygon2D polygon) 126 { 127 this(new Point2D.Double()); 128 129 setPolygon2D(polygon); 130 unselectAllPoints(); 131 } 132 133 public ROI2DPolygon() 134 { 135 this(new Point2D.Double()); 136 } 137 138 @Override 139 public String getDefaultName() 140 { 141 return "Polygon2D"; 142 } 143 144 @Override 145 protected Anchor2D createAnchor(Point2D pos) 146 { 147 return new ROI2DPolygonAnchor2D(pos, getColor(), getFocusedColor()); 148 } 149 150 /** 151 * @deprecated Use {@link #getPolygon2D()} instead 152 */ 153 @Deprecated 154 protected Path2D getPath() 155 { 156 return new Path2D.Double(shape); 157 } 158 159 public void setPoints(List<Point2D> pts) 160 { 161 beginUpdate(); 162 try 163 { 164 removeAllPoint(); 165 for (Point2D pt : pts) 166 addNewPoint(pt, false); 167 } 168 finally 169 { 170 endUpdate(); 171 } 172 } 173 174 /** 175 * @deprecated Use {@link #setPoints(List)} instead. 176 */ 177 @Deprecated 178 public void setPoints(ArrayList<Point2D> pts) 179 { 180 setPoints((List<Point2D>) pts); 181 } 182 183 public Polygon2D getPolygon2D() 184 { 185 return (Polygon2D) shape; 186 } 187 188 public void setPolygon2D(Polygon2D polygon2D) 189 { 190 beginUpdate(); 191 try 192 { 193 removeAllPoint(); 194 for (int i = 0; i < polygon2D.npoints; i++) 195 addNewPoint(new Point2D.Double(polygon2D.xpoints[i], polygon2D.ypoints[i]), false); 196 } 197 finally 198 { 199 endUpdate(); 200 } 201 } 202 203 public Polygon getPolygon() 204 { 205 return getPolygon2D().getPolygon(); 206 } 207 208 public void setPolygon(Polygon polygon) 209 { 210 beginUpdate(); 211 try 212 { 213 removeAllPoint(); 214 for (int i = 0; i < polygon.npoints; i++) 215 addNewPoint(new Point2D.Double(polygon.xpoints[i], polygon.ypoints[i]), false); 216 } 217 finally 218 { 219 endUpdate(); 220 } 221 } 222 223 @Override 224 protected void updateShape() 225 { 226 final int len; 227 final double[] ptsX; 228 final double[] ptsY; 229 230 synchronized (controlPoints) 231 { 232 len = controlPoints.size(); 233 ptsX = new double[len]; 234 ptsY = new double[len]; 235 236 for (int i = 0; i < len; i++) 237 { 238 final Anchor2D pt = controlPoints.get(i); 239 240 ptsX[i] = pt.getX(); 241 ptsY[i] = pt.getY(); 242 } 243 } 244 245 final Polygon2D polygon2d = getPolygon2D(); 246 247 // we can have a problem here if we try to redraw while we are modifying the polygon points 248 synchronized (polygon2d) 249 { 250 polygon2d.npoints = len; 251 polygon2d.xpoints = ptsX; 252 polygon2d.ypoints = ptsY; 253 polygon2d.calculatePath(); 254 } 255 256 // call super method after shape has been updated 257 super.updateShape(); 258 } 259 260 @Override 261 public boolean loadFromXML(Node node) 262 { 263 beginUpdate(); 264 try 265 { 266 if (!super.loadFromXML(node)) 267 return false; 268 269 removeAllPoint(); 270 271 final List<Node> nodesPoint = XMLUtil.getChildren(XMLUtil.getElement(node, ID_POINTS), ID_POINT); 272 if (nodesPoint != null) 273 { 274 for (Node n : nodesPoint) 275 { 276 final Anchor2D pt = createAnchor(new Point2D.Double()); 277 pt.loadPositionFromXML(n); 278 addPoint(pt); 279 } 280 } 281 } 282 finally 283 { 284 endUpdate(); 285 } 286 287 return true; 288 } 289 290 @Override 291 public boolean saveToXML(Node node) 292 { 293 if (!super.saveToXML(node)) 294 return false; 295 296 final Element nodePoints = XMLUtil.setElement(node, ID_POINTS); 297 synchronized (controlPoints) 298 { 299 for (Anchor2D pt : controlPoints) 300 pt.savePositionToXML(XMLUtil.addElement(nodePoints, ID_POINT)); 301 } 302 return true; 303 } 304}