예제 #1
0
        private void ConstructBvdCell(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 = mesh.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("ConstructBvdCell: 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      = this.points[f.triangle.id];
                cc_f_next = this.points[f_next.triangle.id];

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

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

                        // Insert point Lf,f_next /\ Sf_next into P
                        if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex;
                            points[n + segIndex] = p;
                            segIndex++;

                            vpoints.Add(p);
                        }
                    }
                }
                else
                {
                    // Call Sf the constrained edge blinding f
                    sf.seg = subsegMap[f.triangle.hash];

                    // if f_next is tagged non-blind then
                    if (!f_next.triangle.infected)
                    {
                        // Insert point Lf,f_next /\ Sf into P
                        if (SegmentsIntersect(sf.SegOrg(), sf.SegDest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex;
                            points[n + segIndex] = p;
                            segIndex++;

                            vpoints.Add(p);
                        }
                    }
                    else
                    {
                        // Call Sf_next the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.triangle.hash];

                        // if Sf != Sf_next then
                        if (!sf.Equal(sfn))
                        {
                            // Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
                            if (SegmentsIntersect(sf.SegOrg(), sf.SegDest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex;
                                points[n + segIndex] = p;
                                segIndex++;

                                vpoints.Add(p);
                            }

                            if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex;
                                points[n + segIndex] = p;
                                segIndex++;

                                vpoints.Add(p);
                            }
                        }
                    }
                }

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

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

            // Output: Bounded Voronoi cell of x in counterclockwise order.
            region.Add(vpoints);
        }
예제 #2
0
        private void ConstructBoundaryBvdCell(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 = mesh.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("ConstructBoundaryBvdCell: 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.triangle != Mesh.dummytri)
            {
                // Go clockwise until we reach the border (or the initial triangle)
                while (f_prev.triangle != Mesh.dummytri && !f_prev.Equal(f_init))
                {
                    f_prev.Copy(ref f);
                    f_prev.OprevSelf();
                }

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

            if (f_prev.triangle == Mesh.dummytri)
            {
                // 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;
                points[n + segIndex] = p;
                segIndex++;

                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;
            points[n + segIndex] = p;
            segIndex++;

            vpoints.Add(p);

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

                if (f_next.triangle == Mesh.dummytri)
                {
                    if (!f.triangle.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;
                    points[n + segIndex] = p;
                    segIndex++;

                    vpoints.Add(p);

                    break;
                }

                cc_f_next = this.points[f_next.triangle.id];

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

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

                        // Insert point Lf,f_next /\ Sf_next into P
                        if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex;
                            points[n + segIndex] = p;
                            segIndex++;

                            vpoints.Add(p);
                        }
                    }
                }
                else
                {
                    // Call Sf the constrained edge blinding f
                    sf.seg = subsegMap[f.triangle.hash];

                    sorg  = sf.SegOrg();
                    sdest = sf.SegDest();

                    // if f_next is tagged non-blind then
                    if (!f_next.triangle.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;
                            points[n + segIndex] = p;
                            segIndex++;

                            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;
                            points[n + segIndex] = p;
                            segIndex++;

                            vpoints.Add(p);
                        }
                    }
                    else
                    {
                        // Call Sf_next the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.triangle.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;
                                points[n + segIndex] = p;
                                segIndex++;

                                vpoints.Add(p);
                            }

                            if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex;
                                points[n + segIndex] = p;
                                segIndex++;

                                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;
                                points[n + segIndex] = p;
                                segIndex++;

                                vpoints.Add(p);
                            }
                        }
                    }
                }

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

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

            // Output: Bounded Voronoi cell of x in counterclockwise order.
            region.Add(vpoints);
        }
예제 #3
0
파일: Voronoi.cs 프로젝트: oldmannus/PitGit
        /// <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);
        }