void fitSpline() { Roi roi = imp.getRoi(); if (roi == null) { noRoi("Spline"); return; } int type = roi.getType(); boolean segmentedSelection = type == Roi.POLYGON || type == Roi.POLYLINE; if (!(segmentedSelection || type == Roi.FREEROI || type == Roi.TRACED_ROI || type == Roi.FREELINE)) { IJ.error("Spline", "Polygon or polyline selection required"); return; } if (roi instanceof EllipseRoi) return; PolygonRoi p = (PolygonRoi) roi; Undo.setup(Undo.ROI, imp); if (!segmentedSelection && p.getNCoordinates() > 3) { if (p.subPixelResolution()) p = trimFloatPolygon(p, p.getUncalibratedLength()); else p = trimPolygon(p, p.getUncalibratedLength()); } String options = Macro.getOptions(); if (options != null && options.indexOf("straighten") != -1) p.fitSplineForStraightening(); else if (options != null && options.indexOf("remove") != -1) p.removeSplineFit(); else p.fitSpline(); imp.draw(); LineWidthAdjuster.update(); }
PolygonRoi trimFloatPolygon(PolygonRoi roi, double length) { FloatPolygon poly = roi.getFloatPolygon(); float[] x = poly.xpoints; float[] y = poly.ypoints; int n = poly.npoints; x = smooth(x, n); y = smooth(y, n); float[] curvature = getCurvature(x, y, n); double threshold = rodbard(length); // IJ.log("trim: "+length+" "+threshold); double distance = Math.sqrt((x[1] - x[0]) * (x[1] - x[0]) + (y[1] - y[0]) * (y[1] - y[0])); int i2 = 1; double x1, y1, x2 = 0, y2 = 0; for (int i = 1; i < n - 1; i++) { x1 = x[i]; y1 = y[i]; x2 = x[i + 1]; y2 = y[i + 1]; distance += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) + 1; distance += curvature[i] * 2; if (distance >= threshold) { x[i2] = (float) x2; y[i2] = (float) y2; i2++; distance = 0.0; } } int type = roi.getType() == Roi.FREELINE ? Roi.POLYLINE : Roi.POLYGON; if (type == Roi.POLYLINE && distance > 0.0) { x[i2] = (float) x2; y[i2] = (float) y2; i2++; } PolygonRoi p = new PolygonRoi(x, y, i2, type); if (roi.getStroke() != null) p.setStrokeWidth(roi.getStrokeWidth()); p.setStrokeColor(roi.getStrokeColor()); p.setName(roi.getName()); imp.setRoi(p); return p; }
PolygonRoi trimPolygon(PolygonRoi roi, double length) { int[] x = roi.getXCoordinates(); int[] y = roi.getYCoordinates(); int n = roi.getNCoordinates(); x = smooth(x, n); y = smooth(y, n); float[] curvature = getCurvature(x, y, n); Rectangle r = roi.getBounds(); double threshold = rodbard(length); // IJ.log("trim: "+length+" "+threshold); double distance = Math.sqrt((x[1] - x[0]) * (x[1] - x[0]) + (y[1] - y[0]) * (y[1] - y[0])); x[0] += r.x; y[0] += r.y; int i2 = 1; int x1, y1, x2 = 0, y2 = 0; for (int i = 1; i < n - 1; i++) { x1 = x[i]; y1 = y[i]; x2 = x[i + 1]; y2 = y[i + 1]; distance += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) + 1; distance += curvature[i] * 2; if (distance >= threshold) { x[i2] = x2 + r.x; y[i2] = y2 + r.y; i2++; distance = 0.0; } } int type = roi.getType() == Roi.FREELINE ? Roi.POLYLINE : Roi.POLYGON; if (type == Roi.POLYLINE && distance > 0.0) { x[i2] = x2 + r.x; y[i2] = y2 + r.y; i2++; } PolygonRoi p = new PolygonRoi(x, y, i2, type); imp.setRoi(p); return p; }