private void cmd_rotate(params object[] param) { int handle = (int)param[0]; double theta = (double)param[1]; polygon_lib[handle].trans = Mat3x3.RotateCounterClockwise(theta) * polygon_lib[handle].trans; }
public void ResetTransformLib() { for (int i = 0; i < polygon_lib.Count; i++) { polygon_lib[i].trans = Mat3x3.Eye(); } }
private void cmd_scale(params object[] param) { int handle = (int)param[0]; double scale_x = (double)param[1]; double scale_y = (double)param[2]; polygon_lib[handle].trans = Mat3x3.Scale(scale_x, scale_y) * polygon_lib[handle].trans; }
private void cmd_translate(params object[] param) { int handle = (int)param[0]; double translate_x = (double)param[1]; double translate_y = (double)param[2]; polygon_lib[handle].trans = Mat3x3.Translate(translate_x, translate_y) * polygon_lib[handle].trans; }
public static Ngons Clone(this Ngons polys, Mat3x3 T) { Ngons clone = new Ngons(polys.Count); for (int i = 0; i < polys.Count; i++) { clone.Add(polys[i].Clone(T)); } return(clone); }
public static Ngon Clone(this Ngon poly, Mat3x3 T) { Ngon clone = new Ngon(poly.Count); for (int i = 0; i < poly.Count; i++) { clone.Add(T * poly[i]); } return(clone); }
public int AddCanvasFitPolygon(IntRect canvas, int pattern_handle) { Ngon B = polygon_lib[pattern_handle].GetTransformedPoly()[0]; Ngon C = GeomUtility.CanFitInsidePolygon(canvas, B); polygon_lib.Add(new PolyRef() { poly = new Ngons() { C }, trans = Mat3x3.Eye() }); return(polygon_lib.Count - 1); }
public static Mat3x3 operator *(Mat3x3 A, Mat3x3 B) { Mat3x3 I = new Mat3x3(); I.x11 = A.x11 * B.x11 + A.x12 * B.x21 + A.x13 * B.x31; I.x12 = A.x11 * B.x12 + A.x12 * B.x22 + A.x13 * B.x32; I.x13 = A.x11 * B.x13 + A.x12 * B.x23 + A.x13 * B.x33; I.x21 = A.x21 * B.x11 + A.x22 * B.x21 + A.x23 * B.x31; I.x22 = A.x21 * B.x12 + A.x22 * B.x22 + A.x23 * B.x32; I.x23 = A.x21 * B.x13 + A.x22 * B.x23 + A.x23 * B.x33; I.x31 = A.x31 * B.x11 + A.x32 * B.x21 + A.x33 * B.x31; I.x32 = A.x31 * B.x12 + A.x32 * B.x22 + A.x33 * B.x32; I.x33 = A.x31 * B.x13 + A.x32 * B.x23 + A.x33 * B.x33; return(I); }
public static Mat3x3 Scale(double scale_x, double scale_y, double scale_z = 1.0) { Mat3x3 I = new Mat3x3(); I.x11 = scale_x; I.x12 = 0; I.x13 = 0; I.x21 = 0; I.x22 = scale_y; I.x23 = 0; I.x31 = 0; I.x32 = 0; I.x33 = scale_z; return(I); }
public static Mat3x3 Translate(double t_x, double t_y) { Mat3x3 I = new Mat3x3(); I.x11 = 1; I.x12 = 0; I.x13 = t_x; I.x21 = 0; I.x22 = 1; I.x23 = t_y; I.x31 = 0; I.x32 = 0; I.x33 = 1; return(I); }
public Mat3x3 Inverse() { double D = Determinant(); Mat3x3 I = new Mat3x3(); I.x11 = Det2x2(x22, x23, x32, x33) / D; I.x12 = Det2x2(x13, x12, x33, x32) / D; I.x13 = Det2x2(x12, x13, x22, x23) / D; I.x21 = Det2x2(x23, x21, x33, x31) / D; I.x22 = Det2x2(x11, x13, x31, x33) / D; I.x23 = Det2x2(x13, x11, x23, x21) / D; I.x31 = Det2x2(x21, x22, x31, x32) / D; I.x32 = Det2x2(x12, x11, x32, x31) / D; I.x33 = Det2x2(x11, x12, x21, x22) / D; return(I); }
public static Mat3x3 RotateCounterClockwise(double t) { Mat3x3 T = new Mat3x3(); double c = Math.Cos(t); double s = Math.Sin(t); T.x11 = c; T.x12 = -s; T.x13 = 0; T.x21 = s; T.x22 = c; T.x23 = 0; T.x31 = 0; T.x32 = 0; T.x33 = 1; return(T); }
public int AddMinkowskiSum(int subj_handle, int pattern_handle, NFPQUALITY quality, bool flip_pattern, int set_at = -1) { Ngons A = polygon_lib[subj_handle].GetTransformedPoly(); Ngons B = polygon_lib[pattern_handle].GetTransformedPoly(); Ngons C = GeomUtility.MinkowskiSum(B[0], A, quality, flip_pattern); PolyRef pref = new PolyRef() { poly = C, trans = Mat3x3.Eye() }; if (set_at < 0) { polygon_lib.Add(pref); } else { polygon_lib[set_at] = pref; } return(set_at < 0 ? polygon_lib.Count - 1 : set_at); }
private void cmd_optimal_rotation(int handle) { Ngon hull = polygon_lib[handle].GetTransformedPoly()[0]; int n = hull.Count; double best_t = 0; int best = 0; long best_area = long.MaxValue; bool flip_best = false; for (int i = 0; i < n; i++) { double t = GeomUtility.AlignToEdgeRotation(hull, i); Mat3x3 rot = Mat3x3.RotateCounterClockwise(t); Ngon clone = hull.Clone(rot); IntRect bounds = GeomUtility.GetBounds(clone); long area = bounds.Area(); double aspect = bounds.Aspect(); if (area < best_area) { best_area = area; best = i; best_t = t; flip_best = aspect > 1.0; } } double flip = flip_best ? Math.PI * 0.5 : 0; IntPoint around = hull[best]; cmd_translate(handle, (double)-around.X, (double)-around.Y); cmd_rotate(handle, best_t + flip); cmd_translate(handle, (double)around.X, (double)around.Y); }
/// <summary> /// Append a set triangulated polygons to the nester and get handles for each point to the correp. polygon island /// </summary> /// <param name="points"></param> /// <param name="tris"></param> /// <returns></returns> public int[] AddPolygons(IntPoint[] points, int[] tris, double miter_distance = 0.0) { // from points to clusters of tris int[] poly_map = new int[points.Length]; for (int i = 0; i < poly_map.Length; i++) { poly_map[i] = -1; } HashSet <int>[] graph = new HashSet <int> [points.Length]; for (int i = 0; i < graph.Length; i++) { graph[i] = new HashSet <int>(); } for (int i = 0; i < tris.Length; i += 3) { int t1 = tris[i]; int t2 = tris[i + 1]; int t3 = tris[i + 2]; graph[t1].Add(t2); graph[t1].Add(t3); graph[t2].Add(t1); graph[t2].Add(t3); graph[t3].Add(t1); graph[t3].Add(t2); } if (graph.Any(p => p.Count == 0)) { throw new Exception("No singular vertices should exist on mesh"); } int[] clust_ids = new int[points.Length]; HashSet <int> unmarked = new HashSet <int>(Enumerable.Range(0, points.Length)); int clust_cnt = 0; while (unmarked.Count > 0) { Queue <int> open = new Queue <int>(); int first = unmarked.First(); unmarked.Remove(first); open.Enqueue(first); while (open.Count > 0) { int c = open.Dequeue(); clust_ids[c] = clust_cnt; foreach (int n in graph[c]) { if (unmarked.Contains(n)) { unmarked.Remove(n); open.Enqueue(n); } } } clust_cnt++; } Ngons[] clusters = new Ngons[clust_cnt]; for (int i = 0; i < tris.Length; i += 3) { int clust = clust_ids[tris[i]]; if (clusters[clust] == null) { clusters[clust] = new Ngons(); } IntPoint p1 = points[tris[i]]; IntPoint p2 = points[tris[i + 1]]; IntPoint p3 = points[tris[i + 2]]; clusters[clust].Add(new Ngon() { p1, p2, p3 }); } List <Ngons> fulls = new List <Ngons>(); for (int i = 0; i < clust_cnt; i++) { Ngons cl = clusters[i]; Clipper c = new Clipper(); foreach (Ngon n in cl) { c.AddPath(n, PolyType.ptSubject, true); } Ngons full = new Ngons(); c.Execute(ClipType.ctUnion, full, PolyFillType.pftNonZero); full = Clipper.SimplifyPolygons(full, PolyFillType.pftNonZero); if (miter_distance > 0.00001) { Ngons full_miter = new Ngons(); ClipperOffset co = new ClipperOffset(); co.AddPaths(full, JoinType.jtMiter, EndType.etClosedPolygon); co.Execute(ref full_miter, miter_distance); full_miter = Clipper.SimplifyPolygons(full_miter, PolyFillType.pftNonZero); fulls.Add(full_miter); } else { fulls.Add(full); } } for (int i = 0; i < clust_ids.Length; i++) { clust_ids[i] += polygon_lib.Count; } for (int i = 0; i < fulls.Count; i++) { polygon_lib.Add(new PolyRef() { poly = fulls[i], trans = Mat3x3.Eye() }); } return(clust_ids); }