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);
            }
Example #2
0
        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();
            }
        }
Example #5
0
        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;
            }
        }
Example #6
0
        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)));
 }
Example #8
0
        //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);
        }