// Generates a new polygon by dragging a polygon through an angle, and taking all the points it // touched (and a few extras for overestimation) // Only valid for convex polygons, and small rotations (20 degrees or less) // stroke from theta1 to theta2 public static Polygon strokeRot(double theta1, double theta2, Polygon poly) { Polygon poly1 = mul(Mat.rotation(theta1), poly); Polygon poly2 = mul(Mat.rotation(theta2), poly); Polygon stroked = combine(poly1, poly2); ArrayList<Mat> cornerVerts; Polygon corner; int thisVertex, prevVertex, nextVertex; Mat origin = Mat.encodePoint(0, 0); Mat cornerVert1a, cornerVert1b; Mat cornerVert2a, cornerVert2b; double actualDist, desiredDist; Mat cornerTransform; for (thisVertex = 0; thisVertex < poly.vertices.size(); thisVertex++) { if (thisVertex == 0) { prevVertex = poly.vertices.size() - 1; } else { prevVertex = thisVertex - 1; } if (thisVertex == poly.vertices.size() - 1) { nextVertex = 0; } else { nextVertex = thisVertex + 1; } cornerVerts = new ArrayList<Mat>(); cornerVerts.add(poly2.vertices.get(nextVertex)); cornerVerts.add(origin); cornerVerts.add(poly1.vertices.get(prevVertex)); cornerVert1a = poly1.vertices.get(thisVertex); cornerVert2a = poly2.vertices.get(thisVertex); actualDist = ptSegDistance(cornerVert1a, cornerVert2a, origin); desiredDist = Mat.dist(cornerVert1a, Mat.encodePoint(0, 0)); cornerTransform = Mat.mul(desiredDist / actualDist, Mat.eye(4)); cornerVert1b = Mat.mul(cornerTransform, cornerVert1a); cornerVert2b = Mat.mul(cornerTransform, cornerVert2a); cornerVert1b = lineSegIntersection( cornerVert1b, cornerVert2b, poly1.vertices.get(prevVertex), cornerVert1a); cornerVert2b = lineSegIntersection( cornerVert1b, cornerVert2b, poly2.vertices.get(nextVertex), cornerVert2a); cornerVerts.add(cornerVert1b); cornerVerts.add(cornerVert2b); corner = new Polygon(cornerVerts); stroked = combine(stroked, corner); } return stroked; }
public static double ptSegDistance(Mat e0, Mat e1, Mat p) { double x0 = e0.data[0][0]; double y0 = e0.data[1][0]; double x1 = e1.data[0][0]; double y1 = e1.data[1][0]; double xp = p.data[0][0]; double yp = p.data[1][0]; e0 = new Mat(2, 1); e0.data[0][0] = x0; e0.data[1][0] = y0; e1 = new Mat(2, 1); e1.data[0][0] = x1; e1.data[1][0] = y1; p = new Mat(2, 1); p.data[0][0] = xp; p.data[1][0] = yp; e1 = Mat.sub(e1, e0); p = Mat.sub(p, e0); e0.data[0][0] = 0; e0.data[1][0] = 0; Mat e0b = Mat.sub(e0, e1); Mat pb = Mat.sub(p, e1); Mat e1b = new Mat(2, 1); e1b.data[0][0] = 0; e1b.data[1][0] = 0; if (Mat.dot(e1, p) > 0) { if (Mat.dot(e0b, pb) > 0) { Mat e1u = Mat.mul(1 / Mat.l2(e1), e1); return Mat.dist(p, Mat.mul(Mat.dot(e1u, p), e1u)); } else { return Mat.dist(p, e1); } } else { return Mat.dist(p, e0); } }
public static boolean ptsEqual(Mat p0, Mat p1, double tolerance) { return tolerance > Mat.dist(p0, p1); }