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 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);
        }
        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);
        }
        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);
        }