public Mesh Build(Func <Vertex2D, Vector3> coord) { var mesh = new Mesh(); var vertices = P.Select(p => { return(coord(p)); }).ToArray(); var triangles = new List <int>(); for (int i = 0, n = T.Count; i < n; i++) { var t = T[i]; int a = P.IndexOf(t.a), b = P.IndexOf(t.b), c = P.IndexOf(t.c); if (a < 0 || b < 0 || c < 0) { // Debug.Log(a + " : " + b + " : " + c); continue; } if (Utils2D.LeftSide(t.a.Coordinate, t.b.Coordinate, t.c.Coordinate)) { triangles.Add(a); triangles.Add(c); triangles.Add(b); } else { triangles.Add(a); triangles.Add(b); triangles.Add(c); } } mesh.vertices = vertices; mesh.SetTriangles(triangles.ToArray(), 0); mesh.RecalculateNormals(); return(mesh); }
bool CheckUnique() { var flag = false; for (int i = 0, n = P.Count; i < n; i++) { var v0 = P[i]; for (int j = i + 1; j < n; j++) { var v1 = P[j]; if (Utils2D.CheckEqual(v0, v1)) { Debug.LogWarning("vertex " + i + " equals " + j); flag = true; } } } for (int i = 0, n = E.Count; i < n; i++) { var s0 = E[i]; for (int j = i + 1; j < n; j++) { var s1 = E[j]; if (Utils2D.CheckEqual(s0, s1)) { Debug.LogWarning("segment " + i + " equals " + j); flag = true; } } } for (int i = 0, n = T.Count; i < n; i++) { var t0 = T[i]; for (int j = i + 1; j < n; j++) { var t1 = T[j]; if (Utils2D.CheckEqual(t0, t1)) { Debug.LogWarning("triangle " + i + " equals " + j); flag = true; } } } for (int i = 0, n = T.Count; i < n; i++) { var t = T[i]; if (Utils2D.CheckEqual(t.s0, t.s1) || Utils2D.CheckEqual(t.s0, t.s2) || Utils2D.CheckEqual(t.s1, t.s2)) { Debug.LogWarning("triangle " + i + " has duplicated segments"); flag = true; } } return(flag); }
/* * slow incremental approach * O(n * log(n)) */ public static Polygon2D ConvexHull(Vector2[] points) { var ordered = points.ToList().OrderBy(p => p.x).ToList(); var upper = new List <Vector2>(); upper.Add(ordered[0]); upper.Add(ordered[1]); for (int i = 2, n = ordered.Count; i < n; i++) { upper.Add(ordered[i]); int l = upper.Count; if (l > 2) { var p = upper[l - 3]; var r = upper[l - 2]; var q = upper[l - 1]; if (Utils2D.LeftSide(p, q, r)) // r is left side of pq { upper.RemoveAt(l - 2); } } } var lower = new List <Vector2>(); lower.Add(ordered[ordered.Count - 1]); lower.Add(ordered[ordered.Count - 2]); for (int i = ordered.Count - 3; i >= 0; i--) { lower.Add(ordered[i]); int l = lower.Count; if (l > 2) { var p = lower[l - 3]; var r = lower[l - 2]; var q = lower[l - 1]; if (Utils2D.LeftSide(p, q, r)) // r is left side of pq { lower.RemoveAt(l - 2); } } } lower.RemoveAt(lower.Count - 1); lower.RemoveAt(0); upper.AddRange(lower); return(new Polygon2D(upper.ToArray())); }
// Disable to intersect more than two edges static List <HalfEdge2D> SplitEdges(List <HalfEdge2D> edges) { HalfEdge2D start = edges[0]; HalfEdge2D cur = start; while (true) { HalfEdge2D from = cur, to = from.to; HalfEdge2D from2 = to.to, to2 = from2.to; int intersections = 0; while (to2 != from.from) { if (Utils2D.Intersect(from.p, to.p, from2.p, to2.p)) { intersections++; if (intersections >= 2) { break; } } // next from2 = from2.to; to2 = to2.to; } if (intersections >= 2) { edges.Add(cur.Split()); } else { // next cur = cur.to; if (cur == start) { break; } } } return(edges); }
public Mesh Build() { var mesh = new Mesh(); var vertices = P.Select(p => { var xy = p.Coordinate; var v = new Vector3(xy.x, xy.y, 0f); return(v); }).ToArray(); var triangles = new int[T.Count * 3]; for (int i = 0, n = T.Count; i < n; i++) { var t = T[i]; var i3 = i * 3; int a = P.IndexOf(t.a), b = P.IndexOf(t.b), c = P.IndexOf(t.c); if (Utils2D.LeftSide(t.a.Coordinate, t.b.Coordinate, t.c.Coordinate)) { triangles[i3] = a; triangles[i3 + 1] = c; triangles[i3 + 2] = b; } else { triangles[i3] = a; triangles[i3 + 1] = b; triangles[i3 + 2] = c; } } mesh.vertices = vertices; mesh.SetTriangles(triangles, 0); mesh.RecalculateNormals(); return(mesh); }
public static Polygon2D Contour(Vector2[] points) { var n = points.Length; var edges = new List <HalfEdge2D>(); for (int i = 0; i < n; i++) { edges.Add(new HalfEdge2D(points[i])); } for (int i = 0; i < n; i++) { var e = edges[i]; e.from = edges[(i == 0) ? (n - 1) : (i - 1)]; e.to = edges[(i + 1) % n]; } edges = Polygon2D.SplitEdges(edges); var result = new List <Vector2>(); HalfEdge2D start = edges[0]; result.Add(start.p); HalfEdge2D current = start; while (true) { HalfEdge2D from = current, to = current.to; HalfEdge2D from2 = to.to, to2 = from2.to; bool flag = false; while (from2 != start && to2 != from) { if (flag = Utils2D.Intersect(from.p, to.p, from2.p, to2.p)) { break; } from2 = to2; to2 = to2.to; } if (!flag) { result.Add(to.p); current = to; // step to next } else { result.Add(from2.p); // reconnect from.to = from2; from2.to = from; // invert this edge later to.from = to2; to.Invert(); to2.from = to; HalfEdge2D e = from2; while (e != to) { e.Invert(); e = e.to; } current = from2; } if (current == start) { break; } } result.RemoveAt(result.Count - 1); // remove last return(new Polygon2D(result.ToArray())); }
public bool Contains(Vector2 p) { return(Utils2D.Contains(p, vertices)); }
bool ExternalPSLG(Vector2 p) { return(!Utils2D.Contains(p, V)); }