コード例 #1
0
        private void Create()
        {
            if (_subdiv != null)
            {
                return;
            }

            Envelope        siteEnv  = DelaunayTriangulationBuilder.Envelope(_siteCoords);
            IList <Segment> segments = new List <Segment>();

            if (_constraintLines != null)
            {
                siteEnv.ExpandToInclude(_constraintLines.EnvelopeInternal);
                CreateVertices(_constraintLines);
                segments = CreateConstraintSegments(_constraintLines);
            }

            IEnumerable <Vertex> sites = CreateSiteVertices(_siteCoords);

            ConformingDelaunayTriangulator cdt = new ConformingDelaunayTriangulator(sites, _tolerance);

            cdt.SetConstraints(segments, new List <Vertex>(_constraintVertexMap.Values));
            cdt.FormInitialDelaunay();
            cdt.EnforceConstraints();
            _subdiv = cdt.Subdivision;
        }
コード例 #2
0
        private void Create()
        {
            if (_subdiv != null)
            {
                return;
            }

            Envelope siteEnv = DelaunayTriangulationBuilder.Envelope(_siteCoords);

            _diagramEnv = siteEnv;
            // add a buffer around the final envelope
            double expandBy = Math.Max(_diagramEnv.Width, _diagramEnv.Height);

            _diagramEnv.ExpandBy(expandBy);
            if (_clipEnv != null)
            {
                _diagramEnv.ExpandToInclude(_clipEnv);
            }

            var vertices = DelaunayTriangulationBuilder.ToVertices(_siteCoords);

            _subdiv = new QuadEdgeSubdivision(siteEnv, _tolerance);
            IncrementalDelaunayTriangulator triangulator = new IncrementalDelaunayTriangulator(_subdiv);

            triangulator.InsertSites(vertices);
        }
コード例 #3
0
        // ==================================================================

        /// <summary>
        /// Computes the Delaunay triangulation of the initial sites.
        /// </summary>
        public void FormInitialDelaunay()
        {
            ComputeBoundingBox();
            _subdiv = new QuadEdgeSubdivision(_computeAreaEnv, _tolerance);
            _subdiv.SetLocator(new LastFoundQuadEdgeLocator(_subdiv));
            _incDel = new IncrementalDelaunayTriangulator(_subdiv);
            InsertSites(_initialVertices);
        }
コード例 #4
0
        private void Create()
        {
            if (_subdiv != null)
            {
                return;
            }

            var siteEnv  = Envelope(_siteCoords);
            var vertices = ToVertices(_siteCoords);

            _subdiv = new QuadEdgeSubdivision(siteEnv, _tolerance);
            IncrementalDelaunayTriangulator triangulator = new IncrementalDelaunayTriangulator(_subdiv);

            triangulator.InsertSites(vertices);
        }
コード例 #5
0
        public void TestVoronoiDiagramBuilder()
        {
            const string wkt =
                @"POLYGON ((561758.3399999999 4815264.26, 561758.2199999997 4815264.24, 561758.0899999999 4815264.25, 561757.9699999997 4815264.279999999, 561757.8499999996 4815264.34, 561757.7599999999 4815264.42, 561757.6799999997 4815264.52, 561757.6299999999 4815264.640000001, 561757.5999999996 4815264.76, 561757.5999999996 4815264.890000001, 561757.6299999999 4815265.02, 561757.6799999997 4815265.130000001, 561757.7599999999 4815265.230000001, 561757.8600000005 4815265.310000001, 561758.6100000005 4815265.724000001, 561759.3600000005 4815266.138000001, 561760.1100000005 4815266.552000001, 561760.8600000005 4815266.966000001, 561761.6100000005 4815267.380000001, 561761.75 4815267.41, 561761.9000000004 4815267.4, 561762.04 4815267.359999999, 561762.1699999999 4815267.289999999, 561762.2699999996 4815267.1899999995, 561762.3600000005 4815267.07, 561762.4100000003 4815266.930000001, 561762.4299999997 4815266.789999999, 561762.4199999999 4815266.65, 561762.3799999999 4815266.51, 561762.2999999998 4815266.380000001, 561761.5319999999 4815265.966000001, 561760.764 4815265.552000001, 561759.9959999999 4815265.138000001, 561759.228 4815264.724000001, 561758.4600000001 4815264.310000001, 561758.3399999999 4815264.26))";

            var reader = new WKTReader();
            var geom   = reader.Read(wkt);

            Assert.IsTrue(geom.IsValid);
            Assert.IsTrue(geom.IsSimple);

            //var dtb = new DelaunayTriangulationBuilder();
            //dtb.SetSites(geom);
            QuadEdgeSubdivision qes = null;
            //Assert.DoesNotThrow( () => qes = dtb.GetSubdivision());
            //Assert.IsNotNull(qes);

            //foreach (var t in qes.GetVoronoiCellPolygons(GeometryFactory.Default))
            //    Console.WriteLine(t.AsText());

            //Console.WriteLine();

            GeometryCollection diag = null;
            //Assert.DoesNotThrow(() => diag = qes.GetVoronoiDiagram(GeometryFactory.Default));
            //Assert.IsNotNull(diag);

            var vdb = new VoronoiDiagramBuilder();

            vdb.SetSites(geom);
            qes = null;
            Assert.DoesNotThrow(() => qes = vdb.GetSubdivision());
            Assert.IsNotNull(qes);

            foreach (var t in qes.GetVoronoiCellPolygons(GeometryFactory.Default))
            {
                Console.WriteLine(t.AsText());
            }

            Console.WriteLine();

            diag = null;
            Assert.DoesNotThrow(() => diag = vdb.GetDiagram(GeometryFactory.Default));
            Assert.IsNotNull(diag);
        }
コード例 #6
0
        private static void RunVoronoi(string sitesWKT, string expectedWKT)
        {
            WKTReader reader = new WKTReader();
            IGeometry sites  = reader.Read(sitesWKT);

            DelaunayTriangulationBuilder builder = new DelaunayTriangulationBuilder();

            builder.SetSites(sites);

            QuadEdgeSubdivision subdiv = builder.GetSubdivision();
            IGeometry           result = subdiv.GetVoronoiDiagram(GeometryFactory.Default);

            Assert.IsNotNull(result);

            IGeometry expectedEdges = reader.Read(expectedWKT);

            result.Normalize();
            expectedEdges.Normalize();
            Assert.IsTrue(expectedEdges.EqualsExact(result, ComparisonTolerance));
        }
コード例 #7
0
 /// <summary>
 /// Creates a new triangulator using the given <see cref="QuadEdgeSubdivision"/>.
 /// The triangulator uses the tolerance of the supplied subdivision.
 /// </summary>
 /// <param name="subdiv">a subdivision in which to build the TIN</param>
 public IncrementalDelaunayTriangulator(QuadEdgeSubdivision subdiv)
 {
     _subdiv           = subdiv;
     _isUsingTolerance = subdiv.Tolerance > 0.0;
 }
コード例 #8
0
        private static IList <QuadEdgeTriangle> ExtractTriangles(QuadEdgeSubdivision subdiv)
        {
            var qeTris = QuadEdgeTriangle.CreateOn(subdiv);

            return(qeTris);
        }
コード例 #9
0
 public LastFoundQuadEdgeLocator(QuadEdgeSubdivision subdiv)
 {
     _subdiv = subdiv;
     Init();
 }
コード例 #10
0
 public LastFoundQuadEdgeLocator(QuadEdgeSubdivision subdiv)
 {
     _subdiv = subdiv;
     Init();
 }
コード例 #11
0
        } // End Function GetConcaveHull


        public Geometry ComputeConcaveHull()
        {
            ConformingDelaunayTriangulationBuilder cdtb = new ConformingDelaunayTriangulationBuilder();

            cdtb.SetSites(this.geometries);

            QuadEdgeSubdivision qes = cdtb.GetSubdivision();

            IList <QuadEdge>         quadEdges   = qes.GetEdges();
            IList <QuadEdgeTriangle> qeTriangles = QuadEdgeTriangle.CreateOn(qes);
            IEnumerable <Vertex>     qeVertices  = qes.GetVertices(false);

            int iV = 0;

            foreach (Vertex v in qeVertices)
            {
                this.coordinates[v.Coordinate] = iV;
                this.vertices[iV] = new Vertex(iV, v.Coordinate);
                iV++;
            }

            List <QuadEdge> qeFrameBorder = new List <QuadEdge>();
            List <QuadEdge> qeFrame       = new List <QuadEdge>();
            List <QuadEdge> qeBorder      = new List <QuadEdge>();

            // here each one more
            foreach (QuadEdge qe in quadEdges)
            {
                if (qes.IsFrameBorderEdge(qe))
                {
                    qeFrameBorder.Add(qe);
                }

                if (qes.IsFrameEdge(qe))
                {
                    qeFrame.Add(qe);
                }
            } // Next qe

            // border
            for (int j = 0; j < qeFrameBorder.Count; j++)
            {
                QuadEdge q = qeFrameBorder[j];
                if (!qeFrame.Contains(q))
                {
                    qeBorder.Add(q);
                }
            } // Next j

            // deletion of exterior edges
            foreach (QuadEdge qe in qeFrame)
            {
                qes.Delete(qe);
            }



            Dictionary <QuadEdge, double> qeDistances = new Dictionary <QuadEdge, double>();

            foreach (QuadEdge qe in quadEdges)
            {
                qeDistances.Add(qe, qe.ToLineSegment().Length);
            }


            DoubleComparator dc = new DoubleComparator(qeDistances);
            // This doesn't work with dictionary - missing duplicates ...
            List <KeyValuePair <QuadEdge, double> > qeSorted = new List <KeyValuePair <QuadEdge, double> >();

            foreach (KeyValuePair <QuadEdge, double> thisDistance in qeDistances)
            {
                qeSorted.Add(thisDistance);
            }
            qeSorted.Sort(dc);


            // edges creation
            int i = 0;

            foreach (KeyValuePair <QuadEdge, double> kvp in qeSorted)
            {
                LineSegment s = kvp.Key.ToLineSegment();
                s.Normalize();

                int    idS = this.coordinates[s.P0];
                int    idD = this.coordinates[s.P1];
                Vertex oV  = this.vertices[idS];
                Vertex eV  = this.vertices[idD];

                Edge edge;
                if (qeBorder.Contains(kvp.Key))
                {
                    oV.IsBorder = true;
                    eV.IsBorder = true;

                    edge = new Edge(i, s, oV, eV, true);

                    if (s.Length < this.threshold)
                    {
                        this.shortLengths[i] = edge;
                    }
                    else
                    {
                        this.lengths[i] = edge;
                    }
                }
                else
                {
                    edge = new Edge(i, s, oV, eV, false);
                }

                this.edges[i]    = edge;
                this.segments[s] = i;
                i++;
            } // Next qe

            // hm of linesegment and hm of edges // with id as key
            // hm of triangles using hm of ls and connection with hm of edges

            i = 0;
            foreach (QuadEdgeTriangle qet in qeTriangles)
            {
                LineSegment sA = qet.GetEdge(0).ToLineSegment();
                LineSegment sB = qet.GetEdge(1).ToLineSegment();
                LineSegment sC = qet.GetEdge(2).ToLineSegment();

                sA.Normalize();
                sB.Normalize();
                sC.Normalize();

                Edge edgeA = this.edges[this.segments[sA]];
                Edge edgeB = this.edges[this.segments[sB]];
                Edge edgeC = this.edges[this.segments[sC]];

                Triangle triangle = new Triangle(i, qet.IsBorder() ? true : false);
                triangle.AddEdge(edgeA);
                triangle.AddEdge(edgeB);
                triangle.AddEdge(edgeC);

                edgeA.AddTriangle(triangle);
                edgeB.AddTriangle(triangle);
                edgeC.AddTriangle(triangle);

                this.triangles[i] = triangle;
                i++;
            } // Next qet


            // add triangle neighbourood
            foreach (Edge edge in this.edges.Values)
            {
                if (edge.Triangles.Count != 1)
                {
                    Triangle tA = edge.Triangles[0];
                    Triangle tB = edge.Triangles[1];
                    tA.AddNeighbour(tB);
                    tB.AddNeighbour(tA);
                }
            }

            // concave hull algorithm
            int index = 0;

            while (index != -1)
            {
                index = -1;

                Edge e = null;

                // find the max length (smallest id so first entry)
                int si = this.lengths.Count;

                if (si != 0)
                {
                    KeyValuePair <int, Edge> entry = this.lengths.First();

                    int ind = entry.Key;
                    if (entry.Value.Geometry.Length > this.threshold)
                    {
                        index = ind;
                        e     = entry.Value;
                    }
                } // End if (si != 0)

                if (index != -1)
                {
                    Triangle        triangle   = e.Triangles[0];
                    List <Triangle> neighbours = triangle.Neighbours;

                    // irregular triangle test
                    if (neighbours.Count == 1)
                    {
                        this.shortLengths[e.Id] = e;
                        this.lengths.Remove(e.Id);
                    }
                    else
                    {
                        Edge e0 = triangle.Edges[0];
                        Edge e1 = triangle.Edges[1];

                        // test if all the vertices are on the border
                        if (e0.OV.IsBorder && e0.EV.IsBorder &&
                            e1.OV.IsBorder && e1.EV.IsBorder)
                        {
                            this.shortLengths[e.Id] = e;
                            this.lengths.Remove(e.Id);
                        }
                        else
                        {
                            // management of triangles
                            Triangle tA = neighbours[0];
                            Triangle tB = neighbours[1];
                            tA.Border = true; // FIXME not necessarily useful
                            tB.Border = true; // FIXME not necessarily useful
                            this.triangles.Remove(triangle.Id);
                            tA.RemoveNeighbour(triangle);
                            tB.RemoveNeighbour(triangle);

                            // new edges
                            List <Edge> ee = triangle.Edges;
                            Edge        eA = ee[0];
                            Edge        eB = ee[1];
                            Edge        eC = ee[2];

                            if (eA.Border)
                            {
                                this.edges.Remove(eA.Id);
                                eB.Border = true;

                                eB.OV.IsBorder = true;
                                eB.EV.IsBorder = true;

                                eC.Border = true;

                                eC.OV.IsBorder = true;
                                eC.EV.IsBorder = true;

                                // clean the relationships with the triangle
                                eB.RemoveTriangle(triangle);
                                eC.RemoveTriangle(triangle);

                                if (eB.Geometry.Length < this.threshold)
                                {
                                    this.shortLengths[eB.Id] = eB;
                                }
                                else
                                {
                                    this.lengths[eB.Id] = eB;
                                }

                                if (eC.Geometry.Length < this.threshold)
                                {
                                    this.shortLengths[eC.Id] = eC;
                                }
                                else
                                {
                                    this.lengths[eC.Id] = eC;
                                }

                                this.lengths.Remove(eA.Id);
                            } // End if (eA.Border)
                            else if (eB.Border)
                            {
                                this.edges.Remove(eB.Id);
                                eA.Border      = true;
                                eA.OV.IsBorder = true;
                                eA.EV.IsBorder = true;
                                eC.Border      = true;
                                eC.OV.IsBorder = true;
                                eC.EV.IsBorder = true;

                                // clean the relationships with the triangle
                                eA.RemoveTriangle(triangle);
                                eC.RemoveTriangle(triangle);

                                if (eA.Geometry.Length < this.threshold)
                                {
                                    this.shortLengths[eA.Id] = eA;
                                }
                                else
                                {
                                    this.lengths[eA.Id] = eA;
                                }
                                if (eC.Geometry.Length < this.threshold)
                                {
                                    this.shortLengths[eC.Id] = eC;
                                }
                                else
                                {
                                    this.lengths[eC.Id] = eC;
                                }

                                this.lengths.Remove(eB.Id);
                            } // End else if (eB.Border)
                            else
                            {
                                this.edges.Remove(eC.Id);
                                eA.Border = true;

                                eA.OV.IsBorder = true;
                                eA.EV.IsBorder = true;
                                eB.Border      = true;
                                eB.OV.IsBorder = true;
                                eB.EV.IsBorder = true;

                                // clean the relationships with the triangle
                                eA.RemoveTriangle(triangle);
                                eB.RemoveTriangle(triangle);

                                if (eA.Geometry.Length < this.threshold)
                                {
                                    this.shortLengths[eA.Id] = eA;
                                }
                                else
                                {
                                    this.lengths[eA.Id] = eA;
                                }

                                if (eB.Geometry.Length < this.threshold)
                                {
                                    this.shortLengths[eB.Id] = eB;
                                }
                                else
                                {
                                    this.lengths[eB.Id] = eB;
                                }

                                this.lengths.Remove(eC.Id);
                            } // End Else of if (e0.OV.Border && e0.EV.Border && e1.OV.Border && e1.EV.Border)
                        }     // End Else of if
                    }         // End Else of if (neighbours.Count == 1)
                }             // End if (index != -1)
            }                 // Whend

            // concave hull creation
            List <LineString> edges = new List <LineString>();

            foreach (Edge e in this.lengths.Values)
            {
                LineString l = e.Geometry.ToGeometry(this.geomFactory);
                edges.Add(l);
            }

            foreach (Edge e in this.shortLengths.Values)
            {
                LineString l = e.Geometry.ToGeometry(this.geomFactory);
                edges.Add(l);
            }

            // merge
            Operation.Linemerge.LineMerger lineMerger = new Operation.Linemerge.LineMerger();
            lineMerger.Add(edges);

            LineString merge = null;

            using (IEnumerator <Geometry> en = lineMerger.GetMergedLineStrings().GetEnumerator())
            {
                en.MoveNext();
                merge = (LineString)en.Current;
            }

            if (merge.IsRing)
            {
                LinearRing lr          = new LinearRing(merge.CoordinateSequence, this.geomFactory);
                Polygon    concaveHull = new Polygon(lr, null, this.geomFactory);
                return(concaveHull);
            }

            return(merge);
        } // End Function ComputeConcaveHull