예제 #1
0
        public void TestOnext()
        {
            var triangles = CreateExampleMesh();

            Otri t = default;

            // Start with the bottom right triangle.
            t.tri = triangles[2];

            // Start with edge  1 -> 2.
            t.orient = 0;

            // Make sure we're on the correct edge.
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(2, t.Dest().ID);

            t.Onext();
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(4, t.Dest().ID);
            Assert.AreEqual(1, t.tri.ID);

            t.Onext();
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(3, t.Dest().ID);
            Assert.AreEqual(0, t.tri.ID);

            // Out of mesh.
            t.Onext();
            Assert.AreEqual(-1, t.tri.ID);
        }
        private void BuildCache(Vertex vertex, bool vertices)
        {
            cache.Clear();

            Otri init = vertex.tri;
            Otri next = default(Otri);
            Otri prev = default(Otri);

            init.Copy(ref next);

            // Move counter-clockwise around the vertex.
            while (next.tri.id != TriangleNetMesh.DUMMY)
            {
                cache.Add(next);

                next.Copy(ref prev);
                next.Onext();

                if (next.Equals(init))
                {
                    break;
                }
            }

            if (next.tri.id == TriangleNetMesh.DUMMY)
            {
                // We reached the boundary. To get all adjacent triangles, start
                // again at init triangle and now move clockwise.
                init.Copy(ref next);

                if (vertices)
                {
                    // Don't forget to add the vertex lying on the boundary.
                    prev.Lnext();
                    cache.Add(prev);
                }

                next.Oprev();

                while (next.tri.id != TriangleNetMesh.DUMMY)
                {
                    cache.Insert(0, next);

                    next.Oprev();

                    if (next.Equals(init))
                    {
                        break;
                    }
                }
            }
        }
예제 #3
0
        SplayNode FrontLocate(SplayNode splayroot, Otri bottommost, Vertex searchvertex,
                              ref Otri searchtri, ref bool farright)
        {
            bool farrightflag;

            bottommost.Copy(ref searchtri);
            splayroot = Splay(splayroot, searchvertex, ref searchtri);

            farrightflag = false;
            while (!farrightflag && RightOfHyperbola(ref searchtri, searchvertex))
            {
                searchtri.Onext();
                farrightflag = searchtri.Equals(bottommost);
            }
            farright = farrightflag;
            return(splayroot);
        }
예제 #4
0
        private void InvokePrimitive(string name)
        {
            if (name == "sym")
            {
                current.Sym();
            }
            else if (name == "lnext")
            {
                current.Lnext();
            }
            else if (name == "lprev")
            {
                current.Lprev();
            }
            else if (name == "onext")
            {
                current.Onext();
            }
            else if (name == "oprev")
            {
                current.Oprev();
            }
            else if (name == "dnext")
            {
                current.Dnext();
            }
            else if (name == "dprev")
            {
                current.Dprev();
            }
            else if (name == "rnext")
            {
                current.Rnext();
            }
            else if (name == "rprev")
            {
                current.Rprev();
            }

            renderControl.Update(current);
            topoControlView.SetTriangle(current.Triangle);
        }
예제 #5
0
        /// <summary>
        /// Construct Voronoi region for given vertex.
        /// </summary>
        /// <param name="vertex"></param>
        /// <returns>The circumcenter indices which make up the cell.</returns>
        private void ConstructVoronoiRegion(Vertex vertex)
        {
            VoronoiRegion region = new VoronoiRegion(vertex);

            regions.Add(region);

            List <Point> vpoints = new List <Point>();

            Otri f      = default(Otri);
            Otri f_init = default(Otri);
            Otri f_next = default(Otri);
            Otri f_prev = default(Otri);

            Osub sub = default(Osub);

            // Call f_init a triangle incident to x
            vertex.tri.Copy(ref f_init);

            f_init.Copy(ref f);
            f_init.Onext(ref f_next);

            // Check if f_init lies on the boundary of the triangulation.
            if (f_next.triangle == Mesh.dummytri)
            {
                f_init.Oprev(ref f_prev);

                if (f_prev.triangle != Mesh.dummytri)
                {
                    f_init.Copy(ref f_next);
                    // Move one triangle clockwise
                    f_init.OprevSelf();
                    f_init.Copy(ref f);
                }
            }

            // Go counterclockwise until we reach the border or the initial triangle.
            while (f_next.triangle != Mesh.dummytri)
            {
                // Add circumcenter of current triangle
                vpoints.Add(points[f.triangle.id]);

                if (f_next.Equal(f_init))
                {
                    // Voronoi cell is complete (bounded case).
                    region.Add(vpoints);
                    return;
                }

                f_next.Copy(ref f);
                f_next.OnextSelf();
            }

            // Voronoi cell is unbounded
            region.Bounded = false;

            Vertex torg, tdest, tapex, intersection;
            int    sid, n = mesh.triangles.Count;

            // Find the boundary segment id.
            f.Lprev(ref f_next);
            f_next.SegPivot(ref sub);
            sid = sub.seg.hash;

            // Last valid f lies at the boundary. Add the circumcenter.
            vpoints.Add(points[f.triangle.id]);

            // Check if the intersection with the bounding box has already been computed.
            if (rayPoints.ContainsKey(sid))
            {
                vpoints.Add(rayPoints[sid]);
            }
            else
            {
                torg  = f.Org();
                tapex = f.Apex();
                BoxRayIntersection(points[f.triangle.id], torg.y - tapex.y, tapex.x - torg.x, out intersection);

                // Set the correct id for the vertex
                intersection.id = n + rayIndex;

                points[n + rayIndex] = intersection;

                rayIndex++;

                vpoints.Add(intersection);
                rayPoints.Add(sid, intersection);
            }

            // Now walk from f_init clockwise till we reach the boundary.
            vpoints.Reverse();

            f_init.Copy(ref f);
            f.Oprev(ref f_prev);

            while (f_prev.triangle != Mesh.dummytri)
            {
                vpoints.Add(points[f_prev.triangle.id]);

                f_prev.Copy(ref f);
                f_prev.OprevSelf();
            }

            // Find the boundary segment id.
            f.SegPivot(ref sub);
            sid = sub.seg.hash;

            if (rayPoints.ContainsKey(sid))
            {
                vpoints.Add(rayPoints[sid]);
            }
            else
            {
                // Intersection has not been computed yet.
                torg  = f.Org();
                tdest = f.Dest();

                BoxRayIntersection(points[f.triangle.id], tdest.y - torg.y, torg.x - tdest.x, out intersection);

                // Set the correct id for the vertex
                intersection.id = n + rayIndex;

                points[n + rayIndex] = intersection;

                rayIndex++;

                vpoints.Add(intersection);
                rayPoints.Add(sid, intersection);
            }

            // Add the new points to the region (in counter-clockwise order)
            vpoints.Reverse();
            region.Add(vpoints);
        }
예제 #6
0
        /// <summary>
        /// Construct Voronoi region for given vertex.
        /// </summary>
        /// <param name="region"></param>
        private void ConstructCell(VoronoiRegion region)
        {
            var vertex = region.Generator as Vertex;

            var vpoints = new List <Point>();

            Otri f      = default(Otri);
            Otri f_init = default(Otri);
            Otri f_next = default(Otri);
            Otri f_prev = default(Otri);

            Osub sub = default(Osub);

            // Call f_init a triangle incident to x
            vertex.tri.Copy(ref f_init);

            f_init.Copy(ref f);
            f_init.Onext(ref f_next);

            // Check if f_init lies on the boundary of the triangulation.
            if (f_next.tri.id == Mesh.DUMMY)
            {
                f_init.Oprev(ref f_prev);

                if (f_prev.tri.id != Mesh.DUMMY)
                {
                    f_init.Copy(ref f_next);
                    // Move one triangle clockwise
                    f_init.Oprev();
                    f_init.Copy(ref f);
                }
            }

            // Go counterclockwise until we reach the border or the initial triangle.
            while (f_next.tri.id != Mesh.DUMMY)
            {
                // Add circumcenter of current triangle
                vpoints.Add(points[f.tri.id]);

                region.AddNeighbor(f.tri.id, regions[f.Apex().id]);

                if (f_next.Equals(f_init))
                {
                    // Voronoi cell is complete (bounded case).
                    region.Add(vpoints);
                    return;
                }

                f_next.Copy(ref f);
                f_next.Onext();
            }

            // Voronoi cell is unbounded
            region.Bounded = false;

            Vertex torg, tdest, tapex;
            Point  intersection;
            int    sid, n = mesh.triangles.Count;

            // Find the boundary segment id (we use this id to number the endpoints of infinit rays).
            f.Lprev(ref f_next);
            f_next.Pivot(ref sub);
            sid = sub.seg.hash;

            // Last valid f lies at the boundary. Add the circumcenter.
            vpoints.Add(points[f.tri.id]);
            region.AddNeighbor(f.tri.id, regions[f.Apex().id]);

            // Check if the intersection with the bounding box has already been computed.
            if (!rayPoints.TryGetValue(sid, out intersection))
            {
                torg         = f.Org();
                tapex        = f.Apex();
                intersection = IntersectionHelper.BoxRayIntersection(bounds, points[f.tri.id], torg.y - tapex.y, tapex.x - torg.x);

                // Set the correct id for the vertex
                intersection.id = n + rayIndex;

                points[n + rayIndex] = intersection;
                rayIndex++;

                rayPoints.Add(sid, intersection);
            }

            vpoints.Add(intersection);

            // Now walk from f_init clockwise till we reach the boundary.
            vpoints.Reverse();

            f_init.Copy(ref f);
            f.Oprev(ref f_prev);

            while (f_prev.tri.id != Mesh.DUMMY)
            {
                vpoints.Add(points[f_prev.tri.id]);
                region.AddNeighbor(f_prev.tri.id, regions[f_prev.Apex().id]);

                f_prev.Copy(ref f);
                f_prev.Oprev();
            }

            // Find the boundary segment id.
            f.Pivot(ref sub);
            sid = sub.seg.hash;

            if (!rayPoints.TryGetValue(sid, out intersection))
            {
                // Intersection has not been computed yet.
                torg  = f.Org();
                tdest = f.Dest();

                intersection = IntersectionHelper.BoxRayIntersection(bounds, points[f.tri.id], tdest.y - torg.y, torg.x - tdest.x);

                // Set the correct id for the vertex
                intersection.id = n + rayIndex;

                rayPoints.Add(sid, intersection);

                points[n + rayIndex] = intersection;
                rayIndex++;
            }

            vpoints.Add(intersection);
            region.AddNeighbor(intersection.id, regions[f.Dest().id]);

            // Add the new points to the region (in counter-clockwise order)
            vpoints.Reverse();
            region.Add(vpoints);
        }
        private void ConstructBoundaryCell(Vertex vertex)
        {
            VoronoiRegion region = new VoronoiRegion(vertex);

            regions.Add(region);

            Otri f      = default(Otri);
            Otri f_init = default(Otri);
            Otri f_next = default(Otri);
            Otri f_prev = default(Otri);
            Osub sf     = default(Osub);
            Osub sfn    = default(Osub);

            Vertex torg, tdest, tapex, sorg, sdest;
            Point  cc_f, cc_f_next, p;

            int n = _TriangleNetMesh.triangles.Count;

            // Call P the polygon (cell) in construction
            List <Point> vpoints = new List <Point>();

            // Call f_init a triangle incident to x
            vertex.tri.Copy(ref f_init);

            if (f_init.Org() != vertex)
            {
                throw new Exception("ConstructBoundaryCell: inconsistent topology.");
            }
            // Let f be initialized to f_init
            f_init.Copy(ref f);
            // Call f_next the next triangle counterclockwise around x
            f_init.Onext(ref f_next);

            f_init.Oprev(ref f_prev);

            // Is the border to the left?
            if (f_prev.tri.id != TriangleNetMesh.DUMMY)
            {
                // Go clockwise until we reach the border (or the initial triangle)
                while (f_prev.tri.id != TriangleNetMesh.DUMMY && !f_prev.Equals(f_init))
                {
                    f_prev.Copy(ref f);
                    f_prev.Oprev();
                }

                f.Copy(ref f_init);
                f.Onext(ref f_next);
            }

            if (f_prev.tri.id == TriangleNetMesh.DUMMY)
            {
                // For vertices on the domain boundaray, add the vertex. For
                // internal boundaries don't add it.
                p = new Point(vertex.x, vertex.y);

                p.id = n + segIndex++;
                segPoints.Add(p);
                vpoints.Add(p);
            }

            // Add midpoint of start triangles' edge.
            torg  = f.Org();
            tdest = f.Dest();
            p     = new Point((torg.x + tdest.x) / 2, (torg.y + tdest.y) / 2);

            p.id = n + segIndex++;
            segPoints.Add(p);
            vpoints.Add(p);

            // repeat ... until f = f_init
            do
            {
                // Call Lffnext the line going through the circumcenters of f and f_next
                cc_f = points[f.tri.id];

                if (f_next.tri.id == TriangleNetMesh.DUMMY)
                {
                    if (!f.tri.infected)
                    {
                        // Add last circumcenter
                        vpoints.Add(cc_f);
                    }

                    // Add midpoint of last triangles' edge (chances are it has already
                    // been added, so post process cell to remove duplicates???)
                    torg  = f.Org();
                    tapex = f.Apex();
                    p     = new Point((torg.x + tapex.x) / 2, (torg.y + tapex.y) / 2);

                    p.id = n + segIndex++;
                    segPoints.Add(p);
                    vpoints.Add(p);

                    break;
                }

                cc_f_next = points[f_next.tri.id];

                // if f is tagged non-blind then
                if (!f.tri.infected)
                {
                    // Insert the circumcenter of f into P
                    vpoints.Add(cc_f);

                    if (f_next.tri.infected)
                    {
                        // Call S_fnext the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // Insert point Lf,f_next /\ Sf_next into P
                        if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                }
                else
                {
                    // Call Sf the constrained edge blinding f
                    sf.seg = subsegMap[f.tri.hash];

                    sorg  = sf.Org();
                    sdest = sf.Dest();

                    // if f_next is tagged non-blind then
                    if (!f_next.tri.infected)
                    {
                        tdest = f.Dest();
                        tapex = f.Apex();

                        // Both circumcenters lie on the blinded side, but we
                        // have to add the intersection with the segment.

                        // Center of f edge dest->apex
                        Point bisec = new Point((tdest.x + tapex.x) / 2, (tdest.y + tapex.y) / 2);

                        // Find intersection of seg with line through f's bisector and circumcenter
                        if (SegmentsIntersect(sorg, sdest, bisec, cc_f, out p, false))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }

                        // Insert point Lf,f_next /\ Sf into P
                        if (SegmentsIntersect(sorg, sdest, cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                    else
                    {
                        // Call Sf_next the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // if Sf != Sf_next then
                        if (!sf.Equal(sfn))
                        {
                            // Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
                            if (SegmentsIntersect(sorg, sdest, cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }

                            if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }
                        }
                        else
                        {
                            // Both circumcenters lie on the blinded side, but we
                            // have to add the intersection with the segment.

                            // Center of f_next edge org->dest
                            Point bisec = new Point((torg.x + tdest.x) / 2, (torg.y + tdest.y) / 2);

                            // Find intersection of seg with line through f_next's bisector and circumcenter
                            if (SegmentsIntersect(sorg, sdest, bisec, cc_f_next, out p, false))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }
                        }
                    }
                }

                // f <- f_next
                f_next.Copy(ref f);

                // Call f_next the next triangle counterclockwise around x
                f_next.Onext();
            }while (!f.Equals(f_init));

            // Output: Bounded Voronoi cell of x in counterclockwise order.
            region.Add(vpoints);
        }
        private void ConstructCell(Vertex vertex)
        {
            VoronoiRegion region = new VoronoiRegion(vertex);

            regions.Add(region);

            Otri f      = default(Otri);
            Otri f_init = default(Otri);
            Otri f_next = default(Otri);
            Osub sf     = default(Osub);
            Osub sfn    = default(Osub);

            Point cc_f, cc_f_next, p;

            int n = _TriangleNetMesh.triangles.Count;

            // Call P the polygon (cell) in construction
            List <Point> vpoints = new List <Point>();

            // Call f_init a triangle incident to x
            vertex.tri.Copy(ref f_init);

            if (f_init.Org() != vertex)
            {
                throw new Exception("ConstructCell: inconsistent topology.");
            }

            // Let f be initialized to f_init
            f_init.Copy(ref f);
            // Call f_next the next triangle counterclockwise around x
            f_init.Onext(ref f_next);

            // repeat ... until f = f_init
            do
            {
                // Call Lffnext the line going through the circumcenters of f and f_next
                cc_f      = points[f.tri.id];
                cc_f_next = points[f_next.tri.id];

                // if f is tagged non-blind then
                if (!f.tri.infected)
                {
                    // Insert the circumcenter of f into P
                    vpoints.Add(cc_f);

                    if (f_next.tri.infected)
                    {
                        // Call S_fnext the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // Insert point Lf,f_next /\ Sf_next into P
                        if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                }
                else
                {
                    // Call Sf the constrained edge blinding f
                    sf.seg = subsegMap[f.tri.hash];

                    // if f_next is tagged non-blind then
                    if (!f_next.tri.infected)
                    {
                        // Insert point Lf,f_next /\ Sf into P
                        if (SegmentsIntersect(sf.Org(), sf.Dest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                    else
                    {
                        // Call Sf_next the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // if Sf != Sf_next then
                        if (!sf.Equal(sfn))
                        {
                            // Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
                            if (SegmentsIntersect(sf.Org(), sf.Dest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }

                            if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }
                        }
                    }
                }

                // f <- f_next
                f_next.Copy(ref f);

                // Call f_next the next triangle counterclockwise around x
                f_next.Onext();
            }while (!f.Equals(f_init));

            // Output: Bounded Voronoi cell of x in counterclockwise order.
            region.Add(vpoints);
        }
예제 #9
0
        public int Triangulate(Mesh mesh)
        {
            SweepLine.SweepEvent[] sweepEventArray;
            SweepLine.SweepEvent   sweepEvent;
            Vertex vertex;
            Vertex vertex1;
            Vertex vertex2;
            Vertex vertex3;

            this.mesh        = mesh;
            this.xminextreme = 10 * mesh.bounds.Xmin - 9 * mesh.bounds.Xmax;
            Otri otri  = new Otri();
            Otri otri1 = new Otri();
            Otri otri2 = new Otri();
            Otri otri3 = new Otri();
            Otri otri4 = new Otri();
            Otri otri5 = new Otri();
            Otri otri6 = new Otri();
            bool i     = false;

            this.splaynodes = new List <SweepLine.SplayNode>();
            SweepLine.SplayNode splayNode = null;
            this.CreateHeap(out sweepEventArray);
            int num = mesh.invertices;

            mesh.MakeTriangle(ref otri2);
            mesh.MakeTriangle(ref otri3);
            otri2.Bond(ref otri3);
            otri2.LnextSelf();
            otri3.LprevSelf();
            otri2.Bond(ref otri3);
            otri2.LnextSelf();
            otri3.LprevSelf();
            otri2.Bond(ref otri3);
            Vertex vertex4 = sweepEventArray[0].vertexEvent;

            this.HeapDelete(sweepEventArray, num, 0);
            num--;
            do
            {
                if (num == 0)
                {
                    SimpleLog.Instance.Error("Input vertices are all identical.", "SweepLine.SweepLineDelaunay()");
                    throw new Exception("Input vertices are all identical.");
                }
                vertex = sweepEventArray[0].vertexEvent;
                this.HeapDelete(sweepEventArray, num, 0);
                num--;
                if (vertex4.x != vertex.x || vertex4.y != vertex.y)
                {
                    continue;
                }
                if (Behavior.Verbose)
                {
                    SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored.", "SweepLine.SweepLineDelaunay().1");
                }
                vertex.type = VertexType.UndeadVertex;
                Mesh mesh1 = mesh;
                mesh1.undeads = mesh1.undeads + 1;
            }while (vertex4.x == vertex.x && vertex4.y == vertex.y);
            otri2.SetOrg(vertex4);
            otri2.SetDest(vertex);
            otri3.SetOrg(vertex);
            otri3.SetDest(vertex4);
            otri2.Lprev(ref otri);
            Vertex vertex5 = vertex;

            while (num > 0)
            {
                SweepLine.SweepEvent sweepEvent1 = sweepEventArray[0];
                this.HeapDelete(sweepEventArray, num, 0);
                num--;
                bool flag = true;
                if (sweepEvent1.xkey >= mesh.bounds.Xmin)
                {
                    Vertex vertex6 = sweepEvent1.vertexEvent;
                    if (vertex6.x != vertex5.x || vertex6.y != vertex5.y)
                    {
                        vertex5   = vertex6;
                        splayNode = this.FrontLocate(splayNode, otri, vertex6, ref otri1, ref i);
                        otri.Copy(ref otri1);
                        for (i = false; !i && this.RightOfHyperbola(ref otri1, vertex6); i = otri1.Equal(otri))
                        {
                            otri1.OnextSelf();
                        }
                        this.Check4DeadEvent(ref otri1, sweepEventArray, ref num);
                        otri1.Copy(ref otri5);
                        otri1.Sym(ref otri4);
                        mesh.MakeTriangle(ref otri2);
                        mesh.MakeTriangle(ref otri3);
                        Vertex vertex7 = otri5.Dest();
                        otri2.SetOrg(vertex7);
                        otri2.SetDest(vertex6);
                        otri3.SetOrg(vertex6);
                        otri3.SetDest(vertex7);
                        otri2.Bond(ref otri3);
                        otri2.LnextSelf();
                        otri3.LprevSelf();
                        otri2.Bond(ref otri3);
                        otri2.LnextSelf();
                        otri3.LprevSelf();
                        otri2.Bond(ref otri4);
                        otri3.Bond(ref otri5);
                        if (!i && otri5.Equal(otri))
                        {
                            otri2.Copy(ref otri);
                        }
                        if (this.randomnation(SweepLine.SAMPLERATE) == 0)
                        {
                            splayNode = this.SplayInsert(splayNode, otri2, vertex6);
                        }
                        else if (this.randomnation(SweepLine.SAMPLERATE) == 0)
                        {
                            otri3.Lnext(ref otri6);
                            splayNode = this.SplayInsert(splayNode, otri6, vertex6);
                        }
                    }
                    else
                    {
                        if (Behavior.Verbose)
                        {
                            SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored.", "SweepLine.SweepLineDelaunay().2");
                        }
                        vertex6.type = VertexType.UndeadVertex;
                        Mesh mesh2 = mesh;
                        mesh2.undeads = mesh2.undeads + 1;
                        flag          = false;
                    }
                }
                else
                {
                    Otri otri7 = sweepEvent1.otriEvent;
                    otri7.Oprev(ref otri4);
                    this.Check4DeadEvent(ref otri4, sweepEventArray, ref num);
                    otri7.Onext(ref otri5);
                    this.Check4DeadEvent(ref otri5, sweepEventArray, ref num);
                    if (otri4.Equal(otri))
                    {
                        otri7.Lprev(ref otri);
                    }
                    mesh.Flip(ref otri7);
                    otri7.SetApex(null);
                    otri7.Lprev(ref otri2);
                    otri7.Lnext(ref otri3);
                    otri2.Sym(ref otri4);
                    if (this.randomnation(SweepLine.SAMPLERATE) == 0)
                    {
                        otri7.SymSelf();
                        vertex1   = otri7.Dest();
                        vertex2   = otri7.Apex();
                        vertex3   = otri7.Org();
                        splayNode = this.CircleTopInsert(splayNode, otri2, vertex1, vertex2, vertex3, sweepEvent1.ykey);
                    }
                }
                if (!flag)
                {
                    continue;
                }
                vertex1 = otri4.Apex();
                vertex2 = otri2.Dest();
                vertex3 = otri2.Apex();
                double num1 = Primitives.CounterClockwise(vertex1, vertex2, vertex3);
                if (num1 > 0)
                {
                    sweepEvent = new SweepLine.SweepEvent()
                    {
                        xkey      = this.xminextreme,
                        ykey      = this.CircleTop(vertex1, vertex2, vertex3, num1),
                        otriEvent = otri2
                    };
                    this.HeapInsert(sweepEventArray, num, sweepEvent);
                    num++;
                    otri2.SetOrg(new SweepLine.SweepEventVertex(sweepEvent));
                }
                vertex1 = otri3.Apex();
                vertex2 = otri3.Org();
                vertex3 = otri5.Apex();
                double num2 = Primitives.CounterClockwise(vertex1, vertex2, vertex3);
                if (num2 <= 0)
                {
                    continue;
                }
                sweepEvent = new SweepLine.SweepEvent()
                {
                    xkey      = this.xminextreme,
                    ykey      = this.CircleTop(vertex1, vertex2, vertex3, num2),
                    otriEvent = otri5
                };
                this.HeapInsert(sweepEventArray, num, sweepEvent);
                num++;
                otri5.SetOrg(new SweepLine.SweepEventVertex(sweepEvent));
            }
            this.splaynodes.Clear();
            otri.LprevSelf();
            return(this.RemoveGhosts(ref otri));
        }
예제 #10
0
        /// <summary>
        /// Spread the virus from all infected triangles to any neighbors not
        /// protected by subsegments. Delete all infected triangles.
        /// </summary>
        /// <remarks>
        /// This is the procedure that actually creates holes and concavities.
        ///
        /// This procedure operates in two phases. The first phase identifies all
        /// the triangles that will die, and marks them as infected. They are
        /// marked to ensure that each triangle is added to the virus pool only
        /// once, so the procedure will terminate.
        ///
        /// The second phase actually eliminates the infected triangles. It also
        /// eliminates orphaned vertices.
        /// </remarks>
        void Plague()
        {
            Otri   testtri        = default(Otri);
            Otri   neighbor       = default(Otri);
            Osub   neighborsubseg = default(Osub);
            Vertex testvertex;
            Vertex norg, ndest;

            bool killorg;

            // Loop through all the infected triangles, spreading the virus to
            // their neighbors, then to their neighbors' neighbors.
            for (int i = 0; i < viri.Count; i++)
            {
                // WARNING: Don't use foreach, mesh.viri list may get modified.

                testtri.triangle = viri[i];
                // A triangle is marked as infected by messing with one of its pointers
                // to subsegments, setting it to an illegal value.  Hence, we have to
                // temporarily uninfect this triangle so that we can examine its
                // adjacent subsegments.
                // TODO: Not true in the C# version (so we could skip this).
                testtri.Uninfect();

                // Check each of the triangle's three neighbors.
                for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
                {
                    // Find the neighbor.
                    testtri.Sym(ref neighbor);
                    // Check for a subsegment between the triangle and its neighbor.
                    testtri.SegPivot(ref neighborsubseg);
                    // Check if the neighbor is nonexistent or already infected.
                    if ((neighbor.triangle == Mesh.dummytri) || neighbor.IsInfected())
                    {
                        if (neighborsubseg.seg != Mesh.dummysub)
                        {
                            // There is a subsegment separating the triangle from its
                            // neighbor, but both triangles are dying, so the subsegment
                            // dies too.
                            mesh.SubsegDealloc(neighborsubseg.seg);
                            if (neighbor.triangle != Mesh.dummytri)
                            {
                                // Make sure the subsegment doesn't get deallocated again
                                // later when the infected neighbor is visited.
                                neighbor.Uninfect();
                                neighbor.SegDissolve();
                                neighbor.Infect();
                            }
                        }
                    }
                    else
                    {   // The neighbor exists and is not infected.
                        if (neighborsubseg.seg == Mesh.dummysub)
                        {
                            // There is no subsegment protecting the neighbor, so
                            // the neighbor becomes infected.
                            neighbor.Infect();
                            // Ensure that the neighbor's neighbors will be infected.
                            viri.Add(neighbor.triangle);
                        }
                        else
                        {
                            // The neighbor is protected by a subsegment.
                            // Remove this triangle from the subsegment.
                            neighborsubseg.TriDissolve();
                            // The subsegment becomes a boundary.  Set markers accordingly.
                            if (neighborsubseg.seg.boundary == 0)
                            {
                                neighborsubseg.seg.boundary = 1;
                            }
                            norg  = neighbor.Org();
                            ndest = neighbor.Dest();
                            if (norg.mark == 0)
                            {
                                norg.mark = 1;
                            }
                            if (ndest.mark == 0)
                            {
                                ndest.mark = 1;
                            }
                        }
                    }
                }
                // Remark the triangle as infected, so it doesn't get added to the
                // virus pool again.
                testtri.Infect();
            }

            foreach (var virus in viri)
            {
                testtri.triangle = virus;

                // Check each of the three corners of the triangle for elimination.
                // This is done by walking around each vertex, checking if it is
                // still connected to at least one live triangle.
                for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
                {
                    testvertex = testtri.Org();
                    // Check if the vertex has already been tested.
                    if (testvertex != null)
                    {
                        killorg = true;
                        // Mark the corner of the triangle as having been tested.
                        testtri.SetOrg(null);
                        // Walk counterclockwise about the vertex.
                        testtri.Onext(ref neighbor);
                        // Stop upon reaching a boundary or the starting triangle.
                        while ((neighbor.triangle != Mesh.dummytri) &&
                               (!neighbor.Equal(testtri)))
                        {
                            if (neighbor.IsInfected())
                            {
                                // Mark the corner of this triangle as having been tested.
                                neighbor.SetOrg(null);
                            }
                            else
                            {
                                // A live triangle.  The vertex survives.
                                killorg = false;
                            }
                            // Walk counterclockwise about the vertex.
                            neighbor.OnextSelf();
                        }
                        // If we reached a boundary, we must walk clockwise as well.
                        if (neighbor.triangle == Mesh.dummytri)
                        {
                            // Walk clockwise about the vertex.
                            testtri.Oprev(ref neighbor);
                            // Stop upon reaching a boundary.
                            while (neighbor.triangle != Mesh.dummytri)
                            {
                                if (neighbor.IsInfected())
                                {
                                    // Mark the corner of this triangle as having been tested.
                                    neighbor.SetOrg(null);
                                }
                                else
                                {
                                    // A live triangle.  The vertex survives.
                                    killorg = false;
                                }
                                // Walk clockwise about the vertex.
                                neighbor.OprevSelf();
                            }
                        }
                        if (killorg)
                        {
                            // Deleting vertex
                            testvertex.type = VertexType.UndeadVertex;
                            mesh.undeads++;
                        }
                    }
                }

                // Record changes in the number of boundary edges, and disconnect
                // dead triangles from their neighbors.
                for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
                {
                    testtri.Sym(ref neighbor);
                    if (neighbor.triangle == Mesh.dummytri)
                    {
                        // There is no neighboring triangle on this edge, so this edge
                        // is a boundary edge. This triangle is being deleted, so this
                        // boundary edge is deleted.
                        mesh.hullsize--;
                    }
                    else
                    {
                        // Disconnect the triangle from its neighbor.
                        neighbor.Dissolve();
                        // There is a neighboring triangle on this edge, so this edge
                        // becomes a boundary edge when this triangle is deleted.
                        mesh.hullsize++;
                    }
                }
                // Return the dead triangle to the pool of triangles.
                mesh.TriangleDealloc(testtri.triangle);
            }

            // Empty the virus pool.
            viri.Clear();
        }
예제 #11
0
        private void ConstructVoronoiRegion(Vertex vertex)
        {
            Vertex        vertex1;
            Vertex        vertex2;
            VoronoiRegion voronoiRegion = new VoronoiRegion(vertex);

            this.regions.Add(voronoiRegion);
            List <Point> points = new List <Point>();
            Otri         otri   = new Otri();
            Otri         otri1  = new Otri();
            Otri         otri2  = new Otri();
            Otri         otri3  = new Otri();
            Osub         osub   = new Osub();

            vertex.tri.Copy(ref otri1);
            otri1.Copy(ref otri);
            otri1.Onext(ref otri2);
            if (otri2.triangle == Mesh.dummytri)
            {
                otri1.Oprev(ref otri3);
                if (otri3.triangle != Mesh.dummytri)
                {
                    otri1.Copy(ref otri2);
                    otri1.OprevSelf();
                    otri1.Copy(ref otri);
                }
            }
            while (otri2.triangle != Mesh.dummytri)
            {
                points.Add(this.points[otri.triangle.id]);
                if (otri2.Equal(otri1))
                {
                    voronoiRegion.Add(points);
                    return;
                }
                otri2.Copy(ref otri);
                otri2.OnextSelf();
            }
            voronoiRegion.Bounded = false;
            int count = this.mesh.triangles.Count;

            otri.Lprev(ref otri2);
            otri2.SegPivot(ref osub);
            int num = osub.seg.hash;

            points.Add(this.points[otri.triangle.id]);
            if (!this.rayPoints.ContainsKey(num))
            {
                vertex1 = otri.Org();
                Vertex vertex3 = otri.Apex();
                this.BoxRayIntersection(this.points[otri.triangle.id], vertex1.y - vertex3.y, vertex3.x - vertex1.x, out vertex2);
                vertex2.id = count + this.rayIndex;
                this.points[count + this.rayIndex] = vertex2;
                this.rayIndex = this.rayIndex + 1;
                points.Add(vertex2);
                this.rayPoints.Add(num, vertex2);
            }
            else
            {
                points.Add(this.rayPoints[num]);
            }
            points.Reverse();
            otri1.Copy(ref otri);
            otri.Oprev(ref otri3);
            while (otri3.triangle != Mesh.dummytri)
            {
                points.Add(this.points[otri3.triangle.id]);
                otri3.Copy(ref otri);
                otri3.OprevSelf();
            }
            otri.SegPivot(ref osub);
            num = osub.seg.hash;
            if (!this.rayPoints.ContainsKey(num))
            {
                vertex1 = otri.Org();
                Vertex vertex4 = otri.Dest();
                this.BoxRayIntersection(this.points[otri.triangle.id], vertex4.y - vertex1.y, vertex1.x - vertex4.x, out vertex2);
                vertex2.id = count + this.rayIndex;
                this.points[count + this.rayIndex] = vertex2;
                this.rayIndex = this.rayIndex + 1;
                points.Add(vertex2);
                this.rayPoints.Add(num, vertex2);
            }
            else
            {
                points.Add(this.rayPoints[num]);
            }
            points.Reverse();
            voronoiRegion.Add(points);
        }
예제 #12
0
        /// <summary>
        ///     Find the intersection of an existing segment and a segment that is being
        ///     inserted. Insert a vertex at the intersection, splitting an existing subsegment.
        /// </summary>
        /// <param name="splittri"></param>
        /// <param name="splitsubseg"></param>
        /// <param name="endpoint2"></param>
        /// <remarks>
        ///     The segment being inserted connects the apex of splittri to endpoint2.
        ///     splitsubseg is the subsegment being split, and MUST adjoin splittri.
        ///     Hence, endpoints of the subsegment being split are the origin and
        ///     destination of splittri.
        ///     On completion, splittri is a handle having the newly inserted
        ///     intersection point as its origin, and endpoint1 as its destination.
        /// </remarks>
        private void SegmentIntersection(ref Otri splittri, ref Osub splitsubseg, Vertex endpoint2)
        {
            Osub               opposubseg = default(Osub);
            Vertex             endpoint1;
            Vertex             torg, tdest;
            Vertex             leftvertex, rightvertex;
            Vertex             newvertex;
            InsertVertexResult success;

            var dummysub = mesh.dummysub;

            double ex, ey;
            double tx, ty;
            double etx, ety;
            double split, denom;

            // Find the other three segment endpoints.
            endpoint1 = splittri.Apex();
            torg      = splittri.Org();
            tdest     = splittri.Dest();
            // Segment intersection formulae; see the Antonio reference.
            tx    = tdest.X - torg.X;
            ty    = tdest.Y - torg.Y;
            ex    = endpoint2.X - endpoint1.X;
            ey    = endpoint2.Y - endpoint1.Y;
            etx   = torg.X - endpoint2.X;
            ety   = torg.Y - endpoint2.Y;
            denom = ty * ex - tx * ey;
            if (denom == 0.0)
            {
                throw new Exception("Attempt to find intersection of parallel segments.");
            }
            split = (ey * etx - ex * ety) / denom;

            // Create the new vertex.
            newvertex = new Vertex(
                torg.X + split * (tdest.X - torg.X),
                torg.Y + split * (tdest.Y - torg.Y),
                splitsubseg.seg.boundary);

            newvertex.Id = mesh.hash_vtx++;

            mesh.vertices.Add(newvertex.Id, newvertex);

            // Insert the intersection vertex.  This should always succeed.
            success = mesh.InsertVertex(newvertex, ref splittri, ref splitsubseg, false, false);
            if (success != InsertVertexResult.Successful)
            {
                throw new Exception("Failure to split a segment.");
            }
            // Record a triangle whose origin is the new vertex.
            newvertex.tri = splittri;
            if (mesh.steinerleft > 0)
            {
                mesh.steinerleft--;
            }

            // Divide the segment into two, and correct the segment endpoints.
            splitsubseg.Sym();
            splitsubseg.Pivot(ref opposubseg);
            splitsubseg.Dissolve(dummysub);
            opposubseg.Dissolve(dummysub);
            do
            {
                splitsubseg.SetSegOrg(newvertex);
                splitsubseg.Next();
            } while (splitsubseg.seg.hash != Mesh.DUMMY);
            do
            {
                opposubseg.SetSegOrg(newvertex);
                opposubseg.Next();
            } while (opposubseg.seg.hash != Mesh.DUMMY);

            // Inserting the vertex may have caused edge flips.  We wish to rediscover
            // the edge connecting endpoint1 to the new intersection vertex.
            FindDirection(ref splittri, endpoint1);

            rightvertex = splittri.Dest();
            leftvertex  = splittri.Apex();
            if ((leftvertex.X == endpoint1.X) && (leftvertex.Y == endpoint1.Y))
            {
                splittri.Onext();
            }
            else if ((rightvertex.X != endpoint1.X) || (rightvertex.Y != endpoint1.Y))
            {
                throw new Exception("Topological inconsistency after splitting a segment.");
            }
            // 'splittri' should have destination endpoint1.
        }
예제 #13
0
        /// <summary>
        ///     Find the first triangle on the path from one point to another.
        /// </summary>
        /// <param name="searchtri"></param>
        /// <param name="searchpoint"></param>
        /// <returns>
        ///     The return value notes whether the destination or apex of the found
        ///     triangle is collinear with the two points in question.
        /// </returns>
        /// <remarks>
        ///     Finds the triangle that intersects a line segment drawn from the
        ///     origin of 'searchtri' to the point 'searchpoint', and returns the result
        ///     in 'searchtri'. The origin of 'searchtri' does not change, even though
        ///     the triangle returned may differ from the one passed in. This routine
        ///     is used to find the direction to move in to get from one point to
        ///     another.
        /// </remarks>
        private FindDirectionResult FindDirection(ref Otri searchtri, Vertex searchpoint)
        {
            Otri   checktri = default(Otri);
            Vertex startvertex;
            Vertex leftvertex, rightvertex;
            double leftccw, rightccw;
            bool   leftflag, rightflag;

            startvertex = searchtri.Org();
            rightvertex = searchtri.Dest();
            leftvertex  = searchtri.Apex();
            // Is 'searchpoint' to the left?
            leftccw  = RobustPredicates.CounterClockwise(searchpoint, startvertex, leftvertex);
            leftflag = leftccw > 0.0;
            // Is 'searchpoint' to the right?
            rightccw  = RobustPredicates.CounterClockwise(startvertex, searchpoint, rightvertex);
            rightflag = rightccw > 0.0;
            if (leftflag && rightflag)
            {
                // 'searchtri' faces directly away from 'searchpoint'. We could go left
                // or right. Ask whether it's a triangle or a boundary on the left.
                searchtri.Onext(ref checktri);
                if (checktri.tri.Id == Mesh.DUMMY)
                {
                    leftflag = false;
                }
                else
                {
                    rightflag = false;
                }
            }
            while (leftflag)
            {
                // Turn left until satisfied.
                searchtri.Onext();
                if (searchtri.tri.Id == Mesh.DUMMY)
                {
                    throw new Exception("Unable to find a triangle on path.");
                }
                leftvertex = searchtri.Apex();
                rightccw   = leftccw;
                leftccw    = RobustPredicates.CounterClockwise(searchpoint, startvertex, leftvertex);
                leftflag   = leftccw > 0.0;
            }
            while (rightflag)
            {
                // Turn right until satisfied.
                searchtri.Oprev();
                if (searchtri.tri.Id == Mesh.DUMMY)
                {
                    throw new Exception("Unable to find a triangle on path.");
                }
                rightvertex = searchtri.Dest();
                leftccw     = rightccw;
                rightccw    = RobustPredicates.CounterClockwise(startvertex, searchpoint, rightvertex);
                rightflag   = rightccw > 0.0;
            }
            if (leftccw == 0.0)
            {
                return(FindDirectionResult.Leftcollinear);
            }
            if (rightccw == 0.0)
            {
                return(FindDirectionResult.Rightcollinear);
            }
            return(FindDirectionResult.Within);
        }
예제 #14
0
        private void ConstructBoundaryBvdCell(Vertex vertex)
        {
            Vertex        vertex1;
            Point         point;
            VoronoiRegion voronoiRegion = new VoronoiRegion(vertex);

            this.regions.Add(voronoiRegion);
            Otri         otri   = new Otri();
            Otri         otri1  = new Otri();
            Otri         otri2  = new Otri();
            Otri         otri3  = new Otri();
            Osub         item   = new Osub();
            Osub         osub   = new Osub();
            int          count  = this.mesh.triangles.Count;
            List <Point> points = new List <Point>();

            vertex.tri.Copy(ref otri1);
            if (otri1.Org() != vertex)
            {
                throw new Exception("ConstructBoundaryBvdCell: inconsistent topology.");
            }
            otri1.Copy(ref otri);
            otri1.Onext(ref otri2);
            otri1.Oprev(ref otri3);
            if (otri3.triangle != Mesh.dummytri)
            {
                while (otri3.triangle != Mesh.dummytri && !otri3.Equal(otri1))
                {
                    otri3.Copy(ref otri);
                    otri3.OprevSelf();
                }
                otri.Copy(ref otri1);
                otri.Onext(ref otri2);
            }
            if (otri3.triangle == Mesh.dummytri)
            {
                point = new Point(vertex.x, vertex.y)
                {
                    id = count + this.segIndex
                };
                this.points[count + this.segIndex] = point;
                this.segIndex = this.segIndex + 1;
                points.Add(point);
            }
            Vertex vertex2 = otri.Org();
            Vertex vertex3 = otri.Dest();

            point = new Point((vertex2.X + vertex3.X) / 2, (vertex2.Y + vertex3.Y) / 2)
            {
                id = count + this.segIndex
            };
            this.points[count + this.segIndex] = point;
            this.segIndex = this.segIndex + 1;
            points.Add(point);
            do
            {
                Point point1 = this.points[otri.triangle.id];
                if (otri2.triangle != Mesh.dummytri)
                {
                    Point point2 = this.points[otri2.triangle.id];
                    if (otri.triangle.infected)
                    {
                        item.seg = this.subsegMap[otri.triangle.hash];
                        Vertex vertex4 = item.SegOrg();
                        Vertex vertex5 = item.SegDest();
                        if (otri2.triangle.infected)
                        {
                            osub.seg = this.subsegMap[otri2.triangle.hash];
                            if (!item.Equal(osub))
                            {
                                if (this.SegmentsIntersect(vertex4, vertex5, point1, point2, out point, true))
                                {
                                    point.id = count + this.segIndex;
                                    this.points[count + this.segIndex] = point;
                                    this.segIndex = this.segIndex + 1;
                                    points.Add(point);
                                }
                                if (this.SegmentsIntersect(osub.SegOrg(), osub.SegDest(), point1, point2, out point, true))
                                {
                                    point.id = count + this.segIndex;
                                    this.points[count + this.segIndex] = point;
                                    this.segIndex = this.segIndex + 1;
                                    points.Add(point);
                                }
                            }
                            else if (this.SegmentsIntersect(vertex4, vertex5, new Point((vertex2.X + vertex3.X) / 2, (vertex2.Y + vertex3.Y) / 2), point2, out point, false))
                            {
                                point.id = count + this.segIndex;
                                this.points[count + this.segIndex] = point;
                                this.segIndex = this.segIndex + 1;
                                points.Add(point);
                            }
                        }
                        else
                        {
                            vertex3 = otri.Dest();
                            vertex1 = otri.Apex();
                            if (this.SegmentsIntersect(vertex4, vertex5, new Point((vertex3.X + vertex1.X) / 2, (vertex3.Y + vertex1.Y) / 2), point1, out point, false))
                            {
                                point.id = count + this.segIndex;
                                this.points[count + this.segIndex] = point;
                                this.segIndex = this.segIndex + 1;
                                points.Add(point);
                            }
                            if (this.SegmentsIntersect(vertex4, vertex5, point1, point2, out point, true))
                            {
                                point.id = count + this.segIndex;
                                this.points[count + this.segIndex] = point;
                                this.segIndex = this.segIndex + 1;
                                points.Add(point);
                            }
                        }
                    }
                    else
                    {
                        points.Add(point1);
                        if (otri2.triangle.infected)
                        {
                            osub.seg = this.subsegMap[otri2.triangle.hash];
                            if (this.SegmentsIntersect(osub.SegOrg(), osub.SegDest(), point1, point2, out point, true))
                            {
                                point.id = count + this.segIndex;
                                this.points[count + this.segIndex] = point;
                                this.segIndex = this.segIndex + 1;
                                points.Add(point);
                            }
                        }
                    }
                    otri2.Copy(ref otri);
                    otri2.OnextSelf();
                }
                else
                {
                    if (!otri.triangle.infected)
                    {
                        points.Add(point1);
                    }
                    vertex2 = otri.Org();
                    vertex1 = otri.Apex();
                    point   = new Point((vertex2.X + vertex1.X) / 2, (vertex2.Y + vertex1.Y) / 2)
                    {
                        id = count + this.segIndex
                    };
                    this.points[count + this.segIndex] = point;
                    this.segIndex = this.segIndex + 1;
                    points.Add(point);
                    break;
                }
            }while (!otri.Equal(otri1));
            voronoiRegion.Add(points);
        }
예제 #15
0
        private void ConstructBvdCell(Vertex vertex)
        {
            Point         point;
            VoronoiRegion voronoiRegion = new VoronoiRegion(vertex);

            this.regions.Add(voronoiRegion);
            Otri         otri   = new Otri();
            Otri         otri1  = new Otri();
            Otri         otri2  = new Otri();
            Osub         item   = new Osub();
            Osub         osub   = new Osub();
            int          count  = this.mesh.triangles.Count;
            List <Point> points = new List <Point>();

            vertex.tri.Copy(ref otri1);
            if (otri1.Org() != vertex)
            {
                throw new Exception("ConstructBvdCell: inconsistent topology.");
            }
            otri1.Copy(ref otri);
            otri1.Onext(ref otri2);
            do
            {
                Point point1 = this.points[otri.triangle.id];
                Point point2 = this.points[otri2.triangle.id];
                if (otri.triangle.infected)
                {
                    item.seg = this.subsegMap[otri.triangle.hash];
                    if (otri2.triangle.infected)
                    {
                        osub.seg = this.subsegMap[otri2.triangle.hash];
                        if (!item.Equal(osub))
                        {
                            if (this.SegmentsIntersect(item.SegOrg(), item.SegDest(), point1, point2, out point, true))
                            {
                                point.id = count + this.segIndex;
                                this.points[count + this.segIndex] = point;
                                this.segIndex = this.segIndex + 1;
                                points.Add(point);
                            }
                            if (this.SegmentsIntersect(osub.SegOrg(), osub.SegDest(), point1, point2, out point, true))
                            {
                                point.id = count + this.segIndex;
                                this.points[count + this.segIndex] = point;
                                this.segIndex = this.segIndex + 1;
                                points.Add(point);
                            }
                        }
                    }
                    else if (this.SegmentsIntersect(item.SegOrg(), item.SegDest(), point1, point2, out point, true))
                    {
                        point.id = count + this.segIndex;
                        this.points[count + this.segIndex] = point;
                        this.segIndex = this.segIndex + 1;
                        points.Add(point);
                    }
                }
                else
                {
                    points.Add(point1);
                    if (otri2.triangle.infected)
                    {
                        osub.seg = this.subsegMap[otri2.triangle.hash];
                        if (this.SegmentsIntersect(osub.SegOrg(), osub.SegDest(), point1, point2, out point, true))
                        {
                            point.id = count + this.segIndex;
                            this.points[count + this.segIndex] = point;
                            this.segIndex = this.segIndex + 1;
                            points.Add(point);
                        }
                    }
                }
                otri2.Copy(ref otri);
                otri2.OnextSelf();
            }while (!otri.Equal(otri1));
            voronoiRegion.Add(points);
        }
예제 #16
0
        private void Plague()
        {
            Otri item = new Otri();
            Otri otri = new Otri();
            Osub osub = new Osub();

            for (int i = 0; i < this.viri.Count; i++)
            {
                item.triangle = this.viri[i];
                item.Uninfect();
                item.orient = 0;
                while (item.orient < 3)
                {
                    item.Sym(ref otri);
                    item.SegPivot(ref osub);
                    if (otri.triangle != Mesh.dummytri && !otri.IsInfected())
                    {
                        if (osub.seg != Mesh.dummysub)
                        {
                            osub.TriDissolve();
                            if (osub.seg.boundary == 0)
                            {
                                osub.seg.boundary = 1;
                            }
                            Vertex vertex  = otri.Org();
                            Vertex vertex1 = otri.Dest();
                            if (vertex.mark == 0)
                            {
                                vertex.mark = 1;
                            }
                            if (vertex1.mark == 0)
                            {
                                vertex1.mark = 1;
                            }
                        }
                        else
                        {
                            otri.Infect();
                            this.viri.Add(otri.triangle);
                        }
                    }
                    else if (osub.seg != Mesh.dummysub)
                    {
                        this.mesh.SubsegDealloc(osub.seg);
                        if (otri.triangle != Mesh.dummytri)
                        {
                            otri.Uninfect();
                            otri.SegDissolve();
                            otri.Infect();
                        }
                    }
                    item.orient = item.orient + 1;
                }
                item.Infect();
            }
            foreach (Triangle virus in this.viri)
            {
                item.triangle = virus;
                item.orient   = 0;
                while (item.orient < 3)
                {
                    Vertex vertex2 = item.Org();
                    if (vertex2 != null)
                    {
                        bool flag = true;
                        item.SetOrg(null);
                        item.Onext(ref otri);
                        while (otri.triangle != Mesh.dummytri && !otri.Equal(item))
                        {
                            if (!otri.IsInfected())
                            {
                                flag = false;
                            }
                            else
                            {
                                otri.SetOrg(null);
                            }
                            otri.OnextSelf();
                        }
                        if (otri.triangle == Mesh.dummytri)
                        {
                            item.Oprev(ref otri);
                            while (otri.triangle != Mesh.dummytri)
                            {
                                if (!otri.IsInfected())
                                {
                                    flag = false;
                                }
                                else
                                {
                                    otri.SetOrg(null);
                                }
                                otri.OprevSelf();
                            }
                        }
                        if (flag)
                        {
                            vertex2.type = VertexType.UndeadVertex;
                            Mesh mesh = this.mesh;
                            mesh.undeads = mesh.undeads + 1;
                        }
                    }
                    item.orient = item.orient + 1;
                }
                item.orient = 0;
                while (item.orient < 3)
                {
                    item.Sym(ref otri);
                    if (otri.triangle != Mesh.dummytri)
                    {
                        otri.Dissolve();
                        Mesh mesh1 = this.mesh;
                        mesh1.hullsize = mesh1.hullsize + 1;
                    }
                    else
                    {
                        Mesh mesh2 = this.mesh;
                        mesh2.hullsize = mesh2.hullsize - 1;
                    }
                    item.orient = item.orient + 1;
                }
                this.mesh.TriangleDealloc(item.triangle);
            }
            this.viri.Clear();
        }