Example #1
0
        public void TestInvertedItalicNTSConforming()
        {
            var atb = new AffineTransformationBuilder(
                new Coordinate(0, 0), new Coordinate(50, 0), new Coordinate(0, 100),
                new Coordinate(0, 0), new Coordinate(50, 0), new Coordinate(20, 100));

            var geom = _wktReader.Read(NTS);

            //Apply italic effect
            geom = atb.GetTransformation().Transform(geom);
            Console.WriteLine(geom.AsText());

            IGeometry constraint = ((IPolygon)geom).GetInteriorRingN(0);

            constraint = geom.Factory.CreatePolygon((ILinearRing)constraint, null);
            constraint = ((IPolygon)constraint.Buffer(-1)).Shell;
            var coordinates = constraint.Coordinates;

            coordinates[coordinates.Length - 1].X -= 1e-7;
            coordinates[coordinates.Length - 1].Y -= 1e-7;

            constraint = geom.Factory.CreateLineString(coordinates);
            Console.WriteLine(constraint.AsText());

            //Setup
            var dtb = new ConformingDelaunayTriangulationBuilder {
                Constraints = constraint
            };

            dtb.SetSites(geom);
            var result = dtb.GetEdges(geom.Factory);

            Console.WriteLine(result.AsText());
        }
        public void TestInvertedNTSConforming()
        {
            IGeometry geom = _wktReader.Read(NTS);

            Console.WriteLine(geom.AsText());

            IGeometry constraint = ((IPolygon)geom).GetInteriorRingN(0);

            constraint = geom.Factory.CreatePolygon((ILinearRing)constraint, null);
            constraint = ((IPolygon)constraint.Buffer(-1)).Shell;
            Coordinate[] coordinates = constraint.Coordinates;
            coordinates[coordinates.Length - 1].X -= 1e-7;
            coordinates[coordinates.Length - 1].Y -= 1e-7;

            constraint = geom.Factory.CreateLineString(coordinates);
            Console.WriteLine(constraint.AsText());

            //Setup
            ConformingDelaunayTriangulationBuilder dtb = new ConformingDelaunayTriangulationBuilder {
                Constraints = constraint
            };

            dtb.SetSites(geom);
            IMultiLineString result = dtb.GetEdges(geom.Factory);

            Console.WriteLine(result.AsText());
        }
Example #3
0
        /// <summary>
        /// Calculte concave hull for grid cells
        /// </summary>
        /// <param name="gridCells"></param>
        /// <param name="alphaValue"></param>
        /// <param name="useCenterPoint">Used when concave hull is calculated. Grid corner coordinates used when false</param>
        /// <returns></returns>
        public static IGeometry ConcaveHull(this List <WebGridCellSpeciesObservationCount> gridCells, double alphaValue, bool useCenterPoint)
        {
            if (gridCells == null || gridCells.Count < 3)
            {
                return(null);
            }

            IPoint[] points;
            if (useCenterPoint)
            {
                //Create a geometry with all grid cell points, this is much faster than using the gridcells because it's less coordinates, the generated geometry will also look better
                points = (from c in gridCells select c.OrginalCentreCoordinate.ToPoint()).ToArray();
            }
            else
            {
                points = new IPoint[gridCells.Count * 4];

                for (var i = 0; i < gridCells.Count; i++)
                {
                    var gridCell    = gridCells[i];
                    var boundingBox = gridCell.OrginalBoundingBox;

                    if (boundingBox == null)
                    {
                        continue;
                    }

                    var startIndex = i * 4;
                    points[startIndex]     = new Point(new Coordinate(boundingBox.Min.X, boundingBox.Min.Y));
                    points[startIndex + 1] = new Point(new Coordinate(boundingBox.Min.X, boundingBox.Max.Y));
                    points[startIndex + 2] = new Point(new Coordinate(boundingBox.Max.X, boundingBox.Max.Y));
                    points[startIndex + 3] = new Point(new Coordinate(boundingBox.Max.X, boundingBox.Min.Y));
                }
            }

            //Triangulate all points
            var triangulationBuilder = new ConformingDelaunayTriangulationBuilder();

            triangulationBuilder.SetSites(new MultiPoint(points));

            var geometryFactory = new GeometryFactory();
            var triangles       = triangulationBuilder.GetTriangles(geometryFactory);

            IGeometry alphaGeometry = null;

            for (var i = 0; i < triangles.Count; i++)
            {
                var triangle = triangles[i];
                var radius   = triangle.Radius() / 1000; //Div radius by 1000 to (commonly) keep alpha values in a range of 1 - 1000

                if (radius < alphaValue)
                {
                    alphaGeometry = alphaGeometry == null ? triangle : alphaGeometry.Union(triangle);
                }
            }

            return(alphaGeometry);
        }
Example #4
0
        public static Geometry conformingDelaunayTriangles(Geometry sites, Geometry constraints)
        {
            ConformingDelaunayTriangulationBuilder builder = new ConformingDelaunayTriangulationBuilder();

            builder.SetSites(sites);
            builder.Constraints = constraints;
            builder.Tolerance   = TRIANGULATION_TOLERANCE;

            var      geomFact = sites != null ? sites.Factory : constraints.Factory;
            Geometry tris     = builder.GetTriangles(geomFact);

            return(tris);
        }
Example #5
0
        private static Geometry ConformingDelaunayTrianglesWithTolerance(Geometry sites, Geometry constraints, double tol)
        {
            var builder = new ConformingDelaunayTriangulationBuilder();

            builder.SetSites(sites);
            builder.Constraints = constraints;
            builder.Tolerance   = tol;

            var      geomFact = sites != null ? sites.Factory : constraints.Factory;
            Geometry tris     = builder.GetTriangles(geomFact);

            return(tris);
        }
Example #6
0
        public void Test2()
        {
            var geom = _wktReader.Read("POLYGON ((0 0, 0 10, 4 10, 4 8, 6 8, 6 10, 10 10, 10 0, 0 0))");
            var dtb  = new ConformingDelaunayTriangulationBuilder();

            dtb.SetSites(geom);
            var resultEdges = dtb.GetEdges(geom.Factory);

            Console.WriteLine(resultEdges.AsText());
            var resultTriangles = dtb.GetTriangles(geom.Factory);

            Console.WriteLine(resultTriangles.AsText());
        }
        public static IGeometry ConformingDelaunayEdgesWithTolerance(IGeometry sites, IGeometry constraints, double tol)
        {
            ConformingDelaunayTriangulationBuilder builder = new ConformingDelaunayTriangulationBuilder();

            builder.SetSites(sites);
            builder.Constraints = constraints;
            builder.Tolerance   = tol;

            IGeometryFactory geomFact = sites != null ? sites.Factory : constraints.Factory;
            IGeometry        tris     = builder.GetEdges(geomFact);

            return(tris);
        }
        private static void RunDelaunay(string sitesWKT, string constraintsWKT, bool computeTriangles, string expectedWKT)
        {
            var reader      = new WKTReader();
            var sites       = reader.Read(sitesWKT);
            var constraints = reader.Read(constraintsWKT);

            var builder = new ConformingDelaunayTriangulationBuilder();

            builder.SetSites(sites);
            builder.Constraints = constraints;

            var      geomFact = GeometryFactory.Default;
            Geometry result   = computeTriangles ? builder.GetTriangles(geomFact) : builder.GetEdges(geomFact);

            Assert.IsNotNull(result);

            var expectedEdges = reader.Read(expectedWKT);

            result.Normalize();
            expectedEdges.Normalize();
            Assert.IsTrue(expectedEdges.EqualsExact(result, ComparisonTolerance));
        }
Example #9
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