(ImagePlus imp)
| 991 | * closed curve. Commun. ACM 18, 7 (July 1975), 409–413. DOI:https://doi.org/10.1145/360881.360919 |
| 992 | */ |
| 993 | private void fitRectangle(ImagePlus imp) { |
| 994 | if (!imp.okToDeleteRoi()) return; |
| 995 | long startTime = System.currentTimeMillis(); |
| 996 | Roi roi = imp.getRoi(); |
| 997 | if (roi == null) |
| 998 | {noRoi("Fit Rectangle"); return;} |
| 999 | if (roi instanceof Line || roi.isDrawingTool()) |
| 1000 | {IJ.error("Fit Rectangle", "Area selection, point selection, or segmented or free line required"); return;} |
| 1001 | if (!roi.isArea()) { |
| 1002 | // check number of points and colinearity before proceeding |
| 1003 | FloatPolygon poly = roi.getFloatPolygon(); |
| 1004 | int n = poly.npoints; |
| 1005 | if (n < 3) |
| 1006 | {IJ.error("Fit Rectangle", "At least three points are required"); return;} |
| 1007 | float[] x = poly.xpoints; |
| 1008 | float[] y = poly.ypoints; |
| 1009 | boolean colinear = true; |
| 1010 | for(int i=2; i<n; i++) { |
| 1011 | float prod = (x[i] - x[0]) * (y[i] - y[0]) - (x[i] - x[1]) * (y[i] - y[1]); |
| 1012 | if (prod != 0) colinear = false; |
| 1013 | } |
| 1014 | if (colinear) |
| 1015 | {IJ.error("Fit Rectangle", "Points are colinear"); return;} |
| 1016 | } |
| 1017 | FloatPolygon p = roi.getFloatConvexHull(); |
| 1018 | if (p!=null) { |
| 1019 | int np = p.npoints; |
| 1020 | float[] xp = p.xpoints; |
| 1021 | float[] yp = p.ypoints; |
| 1022 | Rectangle r = roi.getBounds(); |
| 1023 | double minArea = 2 * r.width * r.height; // generous overestimation |
| 1024 | double minFD = 0; |
| 1025 | int imin = -1; |
| 1026 | int i2min = -1; |
| 1027 | int jmin = -1; |
| 1028 | double min_hmin = 0; |
| 1029 | double min_hmax = 0; |
| 1030 | for (int i = 0; i < np; i++) { |
| 1031 | double maxLD = 0; |
| 1032 | int imax = -1; |
| 1033 | int i2max = -1; |
| 1034 | int jmax = -1; |
| 1035 | int i2 = i + 1; |
| 1036 | if(i == np-1) i2 = 0; |
| 1037 | for (int j = 0; j < np; j++) { |
| 1038 | // distance based on vector cross product |
| 1039 | double d = Math.abs( ((xp[i2] - xp[i]) * (yp[j] - yp[i]) - (xp[j] - xp[i]) * (yp[i2] - yp[i])) / Math.sqrt(Math.pow(xp[i2] - xp[i], 2) + Math.pow(yp[i2] - yp [i], 2)) ); |
| 1040 | if (maxLD < d) { |
| 1041 | maxLD = d; |
| 1042 | imax = i; |
| 1043 | jmax = j; |
| 1044 | i2max = i2; |
| 1045 | } |
| 1046 | } |
| 1047 | double hmin = 0; |
| 1048 | double hmax = 0; |
| 1049 | for (int k = 0; k < np; k++) { // rotating calipers |
| 1050 | // projected distance based on vector dot product, includes sign |
no test coverage detected