public int Compare(PartialHull hull, Event edge) { var d = 0; if (hull.A.x < edge.A.x) { d = Sign(Robust.Orientation(hull.A, hull.B, edge.A)); } else { d = Sign(Robust.Orientation(edge.B, edge.A, hull.A)); } if (d != 0) { return(d); } if (edge.B.x < hull.B.x) { d = Sign(Robust.Orientation(hull.A, hull.B, edge.B)); } else { d = Sign(Robust.Orientation(edge.B, edge.A, hull.B)); } if (d != 0) { return(d); } return(hull.Index - edge.Index); }
private void TestFlip(List <Vector3> points, Triangles triangles, WorkBuffer <Int2> stack, int a, int b, int x) { var y = triangles.Opposite(a, b); //Test boundary edge if (y < 0) { return; } //Swap edge if order flipped if (b < a) { var tmp = a; a = b; b = tmp; tmp = x; x = y; y = tmp; } //Test if edge is constrained if (triangles.IsConstraint(a, b)) { return; } //Test if edge is delaunay if (Robust.InSphere(points[a], points[b], points[x], points[y]) < 0f) { var v = new Int2(a, b); stack.Push(ref v); } }
//This is used to compare events for the sweep line procedure // Points are: // 1. sorted lexicographically // 2. sorted by type (point < end < start) // 3. segments sorted by winding order // 4. sorted by index public int CompareTo(Event b) { var d = 0; d = Sign(A.x - b.A.x); if (d != 0) { return(d); } d = Sign(A.y - b.A.y); if (d != 0) { return(d); } d = Type - b.Type; if (d != 0) { return(d); } if (Type != EventType.Point) { d = Sign(Robust.Orientation(A, B, b.B)); if (d != 0) { return(d); } } return(Index - b.Index); }
private void AddPoint(List <int> cells, WorkBuffer <PartialHull> hulls, List <Vector3> points, Vector2 p, int idx) { var lo = BinarySearch.LT(hulls.Data, p, TestPoint.Default, 0, hulls.UsedSize - 1); var hi = BinarySearch.GT(hulls.Data, p, TestPoint.Default, 0, hulls.UsedSize - 1); for (var i = lo; i < hi; ++i) { var hull = hulls.Data[i]; //Insert p into lower hull { var lowerIds = hull.LowerIds; var m = lowerIds.UsedSize; var lowerIdsData = lowerIds.Data; while (m > 1 && Robust.Orientation(points[lowerIdsData[m - 2]], points[lowerIdsData[m - 1]], p) > 0f) { cells.Add(lowerIdsData[m - 1]); cells.Add(lowerIdsData[m - 2]); cells.Add(idx); m -= 1; } if (m < lowerIds.UsedSize) { lowerIds.RemoveLast(lowerIds.UsedSize - m); } lowerIds.Push(ref idx); } //Insert p into upper hull { var upperIds = hull.UpperIds; var m = upperIds.UsedSize; var upperIdsData = upperIds.Data; while (m > 1 && Robust.Orientation(points[upperIdsData[m - 2]], points[upperIdsData[m - 1]], p) < 0f) { cells.Add(upperIdsData[m - 2]); cells.Add(upperIdsData[m - 1]); cells.Add(idx); m -= 1; } if (m < upperIds.UsedSize) { upperIds.RemoveLast(upperIds.UsedSize - m); } upperIds.Push(ref idx); } } if (Verbose) { Debug.Log("Add"); DumpHulls(hulls); hulls.Dump(); } }
public void Orientation() { Assert.IsTrue(Robust.Orientation( new Vector2(0.1f, 0.1f), new Vector2(0.1f, 0.1f), new Vector2(0.3f, 0.7f) ) == 0f); Assert.IsTrue(Robust.Orientation( new Vector2(0f, 0f), new Vector2(-1e-32f, 0f), new Vector2(0f, 1f) ) > 0f); Assert.IsTrue(Robust.Orientation( new Vector2(0f, 0f), new Vector2(1e-32f, 1e-32f), new Vector2(1f, 1f) ) == 0f); Assert.IsTrue(Robust.Orientation( new Vector2(0f, 0f), new Vector2(1e-32f, 0f), new Vector2(0f, 1f) ) < 0f); var x = 1e-32f; for (var i = 0; i < 32; ++i) { Assert.IsTrue(Robust.Orientation( new Vector2(-x, 0f), new Vector2(0f, 1f), new Vector2(x, 0f) ) > 0f); Assert.IsTrue(Robust.Orientation( new Vector2(-x, 0f), new Vector2(0f, 0f), new Vector2(x, 0f) ) == 0f); Assert.IsTrue(Robust.Orientation( new Vector2(-x, 0f), new Vector2(0f, -1f), new Vector2(x, 0f) ) < 0f, "x=" + x); Assert.IsTrue(Robust.Orientation( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(x, x) ) < 0f, "x=" + x); x *= 10f; } }
public void InSphere() { Assert.IsTrue(Robust.InSphere( new Vector2(0f, -1f), new Vector2(1f, 0f), new Vector2(0f, 1f), new Vector2(-0.5f, 0f)) > 0f); Assert.IsTrue(Robust.InSphere( new Vector2(0f, -1f), new Vector2(1f, 0f), new Vector2(0f, 1f), new Vector2(-1f, 0f)) == 0f); Assert.IsTrue(Robust.InSphere( new Vector2(0f, -1f), new Vector2(1f, 0f), new Vector2(0f, 1f), new Vector2(-1.5f, 0f)) < 0f); var x = 1e-4f; for (var i = 0; i < 8; ++i) { Assert.IsTrue(Robust.InSphere( new Vector2(0f, x), new Vector2(-x, -x), new Vector2(x, -x), new Vector2(0f, 0f)) > 0f, "sphere test:" + x); Assert.IsTrue(Robust.InSphere( new Vector2(0f, x), new Vector2(-x, -x), new Vector2(x, -x), new Vector2(0f, 2f * x)) < 0f, "sphere test:" + x); Assert.IsTrue(Robust.InSphere( new Vector2(0f, x), new Vector2(-x, -x), new Vector2(x, -x), new Vector2(0f, x)) == 0f, "sphere test:" + x); x *= 10f; } }
public int Compare(PartialHull hull, Vector2 p) { return(Sign(Robust.Orientation(hull.A, hull.B, p))); }
//Assume edges are sorted lexicographically public void RefineTriangles(Triangles triangles) { var stack = WorkBufferPool.Get <Int2>(); var points = triangles.Vertices; var numPoints = points.Count; var stars = triangles.Stars; for (var a = 0; a < numPoints; ++a) { var star = stars[a]; var starData = star.Data; var sl = star.UsedSize; for (var j = 0; j < sl; ++j) { var s = starData[j]; var b = s.y; //If order is not consistent, then skip edge if (b < a) { continue; } //Check if edge is constrained if (triangles.IsConstraint(a, b)) { continue; } //Find opposite edge var x = s.x; var y = -1; for (var k = 0; k < sl; ++k) { if (starData[k].x == b) { y = starData[k].y; break; } } //If this is a boundary edge, don't flip it if (y < 0) { continue; } //If edge is in circle, flip it if (Robust.InSphere(points[a], points[b], points[x], points[y]) < 0f) { var v = new Int2(a, b); stack.Push(ref v); } } } while (stack.UsedSize > 0) { var v = stack.Pop(); var a = v.x; var b = v.y; //Find opposite pairs var x = -1; var y = -1; var star = stars[a]; var starData = star.Data; var sl = star.UsedSize; for (var i = 0; i < sl; ++i) { var s = starData[i].x; var t = starData[i].y; if (s == b) { y = t; } else if (t == b) { x = s; } } //If x/y are both valid then skip edge if (x < 0 || y < 0) { continue; } //If edge is now delaunay, then don't flip it if (Robust.InSphere(points[a], points[b], points[x], points[y]) >= 0f) { continue; } //Flip the edge triangles.Flip(a, b); //Test flipping neighboring edges TestFlip(points, triangles, stack, x, a, y); TestFlip(points, triangles, stack, a, y, x); TestFlip(points, triangles, stack, y, b, x); TestFlip(points, triangles, stack, b, x, y); } WorkBufferPool.Release(ref stack); }