1 package com.github.celldynamics.quimp.geom; 2 3 import java.awt.Shape; 4 import java.util.List; 5 6 import org.scijava.vecmath.Point2d; 7 8 import com.github.celldynamics.quimp.plugin.utils.QuimpDataConverter; 9 10 import ij.gui.PolygonRoi; 11 import ij.gui.Roi; 12 import ij.gui.ShapeRoi; 13 import ij.process.FloatPolygon; 14 15 /** 16 * Add some fields indicating that this Shape has been included already in any Snake chain. 17 * 18 * <p>Shapes among one chain have the same id. Chain id is set when following shape overlap current 19 * one 20 * 21 * @author p.baniukiewicz 22 * @see com.github.celldynamics.quimp.geom.TrackOutline 23 * @see com.github.celldynamics.quimp.plugin.binaryseg.BinarySegmentation 24 * 25 */ 26 public class SegmentedShapeRoi extends ShapeRoi { 27 28 /** 29 * The Constant NOT_COUNTED. 30 * 31 * <p>Code for not counted yet shape. 32 */ 33 public static final int NOT_COUNTED = -1; 34 35 /** 36 * The id of the shape. 37 * 38 * <p>positive if has any id assigned (thus it has been counted already) 39 */ 40 protected int id = NOT_COUNTED; 41 42 /** 43 * Frame number where this outline was found. 44 */ 45 protected int frame = 0; 46 /** 47 * Step during conversion outline to points. For 1 every point from outline is included in 48 * output list 49 */ 50 protected double step = 1; 51 /** 52 * true for using spline smoothing during interpolation. 53 */ 54 protected boolean splineSmooth = false; 55 /** 56 * true for using running average for smoothing. Will apply before {@link #splineSmooth} 57 */ 58 protected boolean runningAverageSmooth = false; 59 /** 60 * serialVersionUID. 61 */ 62 private static final long serialVersionUID = 1L; 63 64 /** 65 * Construct object from ij.gui.Roi. 66 * 67 * @param r Roi 68 */ 69 public SegmentedShapeRoi(Roi r) { 70 super(r); 71 } 72 73 /** 74 * Construct object from java.awt.Shape. 75 * 76 * @param s Shape 77 */ 78 public SegmentedShapeRoi(Shape s) { 79 super(s); 80 } 81 82 /** 83 * Construct object from array. 84 * 85 * @param shapeArray shapeArray 86 * @see ij.gui.ShapeRoi#ShapeRoi(float[]) 87 */ 88 public SegmentedShapeRoi(float[] shapeArray) { 89 super(shapeArray); 90 } 91 92 /** 93 * Constructs a ShapeRoi from a Shape. 94 * 95 * @param x x 96 * @param y y 97 * @param s s 98 * @see ij.gui.ShapeRoi#ShapeRoi(int x, int y, Shape s) 99 */ 100 public SegmentedShapeRoi(int x, int y, Shape s) { 101 super(x, y, s); 102 } 103 104 /** 105 * Get id. 106 * 107 * @return the id 108 */ 109 public int getId() { 110 return id; 111 } 112 113 /** 114 * Set Roi id. 115 * 116 * @param id the id to set 117 */ 118 public void setId(int id) { 119 this.id = id; 120 } 121 122 /** 123 * Get Roi frame. 124 * 125 * @return the frame 126 */ 127 public int getFrame() { 128 return frame; 129 } 130 131 /** 132 * Set Roi frame. 133 * 134 * @param frame the frame to set 135 */ 136 public void setFrame(int frame) { 137 this.frame = frame; 138 } 139 140 /** 141 * Convert this ROI to list of points using smoothing and step. 142 * 143 * <p>First this method converts shape to {@link PolygonRoi} using step and running average 144 * smoothing set up by 145 * {@link SegmentedShapeRoi#setInterpolationParameters(double, boolean, boolean)}. Then if 146 * {@link #splineSmooth} was set, spline is fitted to ROI and result is converted to list. By 147 * default step is set to 1 and without smoothing. 148 * 149 * <p>Step of 1 does not mean one point resolution. Still interpolation can apply. Use 150 * {@link #getOutlineasRawPoints()} for obtaining pure coordinates without smoothing nor 151 * interpolation. Depending on interpolation step, last point in list can overlap with first. 152 * 153 * @return List of List of ROIs 154 * @see #getOutlineasRawPoints() 155 * @see #setInterpolationParameters(double, boolean, boolean) 156 */ 157 public List<Point2d> getOutlineasPoints() { 158 List<Point2d> ret; 159 FloatPolygon fp; 160 PolygonRoi pr; 161 // convert to PolygonRoi as it supports spline fitting 162 pr = new PolygonRoi(getInterpolatedPolygon(step, runningAverageSmooth), Roi.FREEROI); 163 if (splineSmooth == true) { // fit spline 164 pr.fitSpline(); 165 fp = pr.getFloatPolygon(); // get FloatPolygon to have access to x[],y[] 166 ret = new QuimpDataConverter(fp.xpoints, fp.ypoints).getList(); // x[],y[] are fitted 167 } else { 168 fp = pr.getFloatPolygon(); 169 ret = new QuimpDataConverter(fp.xpoints, fp.ypoints).getList(); // x[],y[] not fitted 170 } 171 return ret; 172 } 173 174 /** 175 * Convert this ROI to list of points without any interpolation. 176 * 177 * @return List of List of ROIs 178 * @see #getOutlineasPoints() 179 */ 180 public List<Point2d> getOutlineasRawPoints() { 181 FloatPolygon fp = this.getFloatPolygon(); 182 if (fp.xpoints != null && fp.ypoints != null) { 183 return new QuimpDataConverter(fp.xpoints, fp.ypoints).getList(); 184 } else { 185 return null; 186 } 187 } 188 189 /** 190 * Allow to set non-standard parameters used during conversion from outline (ROI) to list of 191 * points. Do not use runing average smoothing. 192 * 193 * <pre> 194 * <code> 195 * for (ArrayList<SegmentedShapeRoi> asS : ret) { 196 * for (SegmentedShapeRoi ss : asS) { 197 * ss.setInterpolationParameters(1, false); 198 * } 199 * } 200 * </code> 201 * </pre> 202 * 203 * @param step interpolation step. Step = 1 does not stand for no interpolation. Use 204 * {@link #getOutlineasRawPoints()} instead. 205 * @param splineSmooth true to use Spline smoothing 206 * 207 * @see #getOutlineasPoints() 208 * @see #getOutlineasRawPoints() 209 */ 210 public void setInterpolationParameters(double step, boolean splineSmooth) { 211 this.step = step; 212 this.splineSmooth = splineSmooth; 213 this.runningAverageSmooth = false; 214 } 215 216 /** 217 * Allow to set non-standard parameters used during conversion from outline (ROI) to list of 218 * points. 219 * 220 * <pre> 221 * <code> 222 * for (ArrayList<SegmentedShapeRoi> asS : ret) { 223 * for (SegmentedShapeRoi ss : asS) { 224 * ss.setInterpolationParameters(1, false,true); 225 * } 226 * } 227 * </code> 228 * </pre> 229 * 230 * @param step interpolation step. Step = 1 does not stand for no interpolation. Use 231 * {@link #getOutlineasRawPoints()} instead. 232 * @param splineSmooth true to use Spline smoothing 233 * @param runningAverageSmooth true for using 3 point running average smoothing. This will apply 234 * before spline smoothing. 235 * 236 * @see #getOutlineasPoints() 237 * @see #getOutlineasRawPoints() 238 */ 239 public void setInterpolationParameters(double step, boolean splineSmooth, 240 boolean runningAverageSmooth) { 241 this.step = step; 242 this.splineSmooth = splineSmooth; 243 this.runningAverageSmooth = runningAverageSmooth; 244 } 245 246 }