private static int MinDistToMapEdge(PlanarGraph graph, Node n, int limit)
        {
            if (n.Coordinate.X == 0 || n.Coordinate.X == Size ||
                n.Coordinate.Y == 0 || n.Coordinate.Y == Size)
                return 0;

            int ret = int.MaxValue;
            Stack<Tuple<int, Node>> stack = new Stack<Tuple<int, Node>>();
            HashSet<Node> visited = new HashSet<Node>();
            stack.Push(new Tuple<int, Node>(0, n));
            do
            {
                Tuple<int, Node> state = stack.Pop();
                if (state.Item2.Coordinate.X == 0 || state.Item2.Coordinate.X == Size ||
                    state.Item2.Coordinate.Y == 0 || state.Item2.Coordinate.Y == Size)
                {
                    if (state.Item1 < ret)
                        ret = state.Item1;
                    if (ret == 0) return 0;

                    continue;
                }
                visited.Add(state.Item2);

                if (state.Item1 > limit) continue;
                foreach (EdgeEnd i in state.Item2.Edges)
                {
                    Node node = graph.Find(i.DirectedCoordinate);
                    if (!visited.Contains(node))
                        stack.Push(new Tuple<int, Node>(state.Item1 + 1, node));
                }
            } while (stack.Count > 0);
            return ret;
        }
Пример #2
0
        /// <summary>
        /// Constructs an instance to compute a single overlay operation
        /// for the given geometries.
        /// </summary>
        /// <param name="g0">The first geometry argument</param>
        /// <param name="g1">The second geometry argument</param>
        public OverlayOp(IGeometry g0, IGeometry g1)
            : base(g0, g1)
        {
            _graph = new PlanarGraph(new OverlayNodeFactory());

            /*
            * Use factory of primary point.
            * Note that this does NOT handle mixed-precision arguments
            * where the second arg has greater precision than the first.
            */
            _geomFact = g0.Factory;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool IsInteriorsConnected()
        {
            // node the edges, in case holes touch the shell
            IList<Edge> splitEdges = new List<Edge>();
            _geomGraph.ComputeSplitEdges(splitEdges);

            // form the edges into rings
            PlanarGraph graph = new PlanarGraph(new OverlayNodeFactory());
            graph.AddEdges(splitEdges);
            SetInteriorEdgesInResult(graph);
            graph.LinkResultDirectedEdges();
            IList<EdgeRing> edgeRings = BuildEdgeRings(graph.EdgeEnds);
            /*
             * Mark all the edges for the edgeRings corresponding to the shells
             * of the input polygons.  Note only ONE ring gets marked for each shell.
             */
            VisitShellInteriors(this._geomGraph.Geometry, graph);

            /*
             * If there are any unvisited shell edges
             * (i.e. a ring which is not a hole and which has the interior
             * of the parent area on the RHS)
             * this means that one or more holes must have split the interior of the
             * polygon into at least two pieces.  The polygon is thus invalid.
             */
            return !HasUnvisitedShellEdge(edgeRings);
        }
 /// <summary>
 /// Mark all the edges for the edgeRings corresponding to the shells of the input polygons.  
 /// Only ONE ring gets marked for each shell - if there are others which remain unmarked
 /// this indicates a disconnected interior.
 /// </summary>
 /// <param name="g"></param>
 /// <param name="graph"></param>
 private void VisitShellInteriors(IGeometry g, PlanarGraph graph)
 {
     if (g is IPolygon)
     {
         IPolygon p = (IPolygon) g;
         VisitInteriorRing(p.Shell, graph);
     }
     if (g is IMultiPolygon)
     {
         IMultiPolygon mp = (IMultiPolygon) g;
         foreach (IPolygon p in mp.Geometries)
             VisitInteriorRing(p.Shell, graph);
     }
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ring"></param>
 /// <param name="graph"></param>
 private void VisitInteriorRing(ILineString ring, PlanarGraph graph)
 {
     Coordinate[] pts = ring.Coordinates;
     Coordinate pt0 = pts[0];
     /*
      * Find first point in coord list different to initial point.
      * Need special check since the first point may be repeated.
      */
     Coordinate pt1 = FindDifferentPoint(pts, pt0);
     Edge e = graph.FindEdgeInSameDirection(pt0, pt1);
     DirectedEdge de = (DirectedEdge) graph.FindEdgeEnd(e);
     DirectedEdge intDe = null;
     if (de.Label.GetLocation(0, Positions.Right) == Location.Interior)
         intDe = de;
     else if (de.Sym.Label.GetLocation(0, Positions.Right) == Location.Interior)
         intDe = de.Sym;
     Assert.IsTrue(intDe != null, "unable to find dirEdge with Interior on RHS");
     VisitLinkedDirectedEdges(intDe);
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 private static void SetInteriorEdgesInResult(PlanarGraph graph)
 {
     foreach (DirectedEdge de in graph.EdgeEnds)
         if (de.Label.GetLocation(0, Positions.Right) == Location.Interior)
             de.InResult = true;
 }
Пример #7
0
 public void Generate(int pointCount)
 {
     //Generate random points
     var hashSet = new HashSet<Coordinate>();
     {
         var rand = new Random(seed);
         while (hashSet.Count < pointCount)
         {
             var x = rand.NextDouble()*2 - 1;
             var y = rand.NextDouble()*2 - 1;
             if (x < -0.99 || y < -0.99 || x > 0.99 || y > 0.99) continue;
             hashSet.Add(new Coordinate(x, y));
         }
     }
     //Optimize points
     {
         var points = hashSet.ToArray();
         for (var i = 0; i < 2; i++)
         {
             var builder = new VoronoiDiagramBuilder();
             builder.SetSites(points);
             VoronoiDiagram = builder.GetDiagram(new GeometryFactory());
             for (var j = 0; j < points.Length; j++)
             {
                 var poly = VoronoiDiagram[j] as Polygon;
                 points[j] = new Coordinate(poly.Centroid.X, poly.Centroid.Y);
             }
         }
     }
     //Build graph
     PlanarGraph graph;
     {
         VoronoiDiagram = ClipGeometryCollection(VoronoiDiagram, new Envelope(-1, 1, -1, 1));
         graph = new PlanarGraph(new OverlayNodeFactory());
         var edges = new List<Edge>();
         for (var i = 0; i < VoronoiDiagram.Count; i++)
         {
             var poly = VoronoiDiagram[i] as Polygon;
             var coords = poly.Coordinates;
             for (var j = 1; j < coords.Length; j++)
             {
                 edges.Add(new Edge(new[] {coords[j - 1], coords[j]}, new Label(Location.Boundary)));
             }
         }
         graph.AddEdges(edges);
     }
     //Convert graph
     Dictionary<Node, MapNode> nodeDict;
     {
         var polys = new Dictionary<MapPolygon, HashSet<MapPolygon>>();
         nodeDict = new Dictionary<Node, MapNode>();
         var dats = new Dictionary<MapNode, Tuple<HashSet<MapPolygon>, HashSet<MapEdge>>>();
         for (var i = 0; i < VoronoiDiagram.Count; i++)
         {
             var nodes = new List<MapNode>();
             var poly = new MapPolygon
             {
                 CentroidX = VoronoiDiagram[i].Centroid.X,
                 CentroidY = VoronoiDiagram[i].Centroid.Y,
                 Polygon = VoronoiDiagram[i] as Polygon
             };
             foreach (var j in VoronoiDiagram[i].Coordinates.Skip(1))
             {
                 var n = graph.Find(j);
                 MapNode mapNode;
                 if (!nodeDict.TryGetValue(n, out mapNode))
                 {
                     mapNode = new MapNode {X = j.X, Y = j.Y};
                     dats[mapNode] =
                         new Tuple<HashSet<MapPolygon>, HashSet<MapEdge>>(new HashSet<MapPolygon> {poly},
                             new HashSet<MapEdge>());
                 }
                 else
                     dats[mapNode].Item1.Add(poly);
                 nodes.Add(nodeDict[n] = mapNode);
             }
             poly.Nodes = nodes.ToArray();
             polys.Add(poly, new HashSet<MapPolygon>());
         }
         foreach (var i in nodeDict)
         {
             foreach (var j in dats[i.Value].Item1)
                 foreach (var k in dats[i.Value].Item1)
                     if (j != k)
                     {
                         polys[j].Add(k);
                         polys[k].Add(j);
                     }
             foreach (var j in i.Key.Edges)
             {
                 var from = nodeDict[graph.Find(j.Coordinate)];
                 var to = nodeDict[graph.Find(j.DirectedCoordinate)];
                 dats[from].Item2.Add(new MapEdge {From = from, To = to});
             }
         }
         var ftrh = dats.Count(_ => _.Value.Item2.Count == 0);
         foreach (var i in dats)
             i.Key.Edges = i.Value.Item2.ToArray();
         var x = polys.ToArray();
         for (var i = 0; i < x.Length; i++)
         {
             x[i].Key.Neighbour = x[i].Value.ToArray();
             x[i].Key.Id = i;
         }
         Polygons = x.Select(_ => _.Key).ToArray();
     }
     //Generate map
     DetermineLandmass();
     FindOceans();
     ComputeDistances();
     RedistributeElevation(nodeDict.Values);
     FindLakesAndCoasts();
 }
Пример #8
0
 /// <summary>
 /// Add a complete graph.
 /// The graph is assumed to contain one or more polygons,
 /// possibly with holes.
 /// </summary>
 /// <param name="graph"></param>
 public void Add(PlanarGraph graph)
 {
     Add(graph.EdgeEnds, graph.Nodes);
 }
Пример #9
0
        public IGeometry Buffer(IGeometry g, double distance)
        {
            IPrecisionModel precisionModel = _workingPrecisionModel;
            if (precisionModel == null)
                precisionModel = g.PrecisionModel;

            // factory must be the same as the one used by the input
            _geomFact = g.Factory;

            OffsetCurveBuilder curveBuilder = new OffsetCurveBuilder(precisionModel, _bufParams);

            OffsetCurveSetBuilder curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder);

            var bufferSegStrList = curveSetBuilder.GetCurves();

            // short-circuit test
            if (bufferSegStrList.Count <= 0)
            {
                return CreateEmptyResultGeometry();
            }

            ComputeNodedEdges(bufferSegStrList, precisionModel);
            _graph = new PlanarGraph(new OverlayNodeFactory());
            _graph.AddEdges(_edgeList.Edges);

            IEnumerable<BufferSubgraph> subgraphList = CreateSubgraphs(_graph);
            PolygonBuilder polyBuilder = new PolygonBuilder(_geomFact);
            BuildSubgraphs(subgraphList, polyBuilder);
            var resultPolyList = polyBuilder.Polygons;

            // just in case...
            if (resultPolyList.Count <= 0)
            {
                return CreateEmptyResultGeometry();
            }

            IGeometry resultGeom = _geomFact.BuildGeometry(resultPolyList);
            return resultGeom;
        }
Пример #10
0
 private static IEnumerable<BufferSubgraph> CreateSubgraphs(PlanarGraph graph)
 {
     var subgraphList = new List<BufferSubgraph>();
     foreach (Node node in graph.Nodes)
     {
         if (!node.IsVisited)
         {
             var subgraph = new BufferSubgraph();
             subgraph.Create(node);
             subgraphList.Add(subgraph);
         }
     }
     /*
      * Sort the subgraphs in descending order of their rightmost coordinate.
      * This ensures that when the Polygons for the subgraphs are built,
      * subgraphs for shells will have been built before the subgraphs for
      * any holes they contain.
      */
     subgraphList.Sort();
     subgraphList.Reverse();
     return subgraphList;
 }
Пример #11
0
        public IGeometry Buffer(IGeometry g, double distance)
        {
            IPrecisionModel precisionModel = _workingPrecisionModel;
            if (precisionModel == null)
                precisionModel = g.PrecisionModel;

            // factory must be the same as the one used by the input
            _geomFact = g.Factory;

            OffsetCurveBuilder curveBuilder = new OffsetCurveBuilder(precisionModel, _bufParams);

            OffsetCurveSetBuilder curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder);

            var bufferSegStrList = curveSetBuilder.GetCurves();

            // short-circuit test
            if (bufferSegStrList.Count <= 0)
            {
                return CreateEmptyResultGeometry();
            }

            //BufferDebug.runCount++;
            //String filename = "run" + BufferDebug.runCount + "_curves";
            //System.out.println("saving " + filename);
            //BufferDebug.saveEdges(bufferEdgeList, filename);
            // DEBUGGING ONLY
            //WKTWriter wktWriter = new WKTWriter();
            //Debug.println("Rings: " + wktWriter.write(convertSegStrings(bufferSegStrList.iterator())));
            //wktWriter.setMaxCoordinatesPerLine(10);
            //System.out.println(wktWriter.writeFormatted(convertSegStrings(bufferSegStrList.iterator())));

            ComputeNodedEdges(bufferSegStrList, precisionModel);
            _graph = new PlanarGraph(new OverlayNodeFactory());
            _graph.AddEdges(_edgeList.Edges);

            IEnumerable<BufferSubgraph> subgraphList = CreateSubgraphs(_graph);
            PolygonBuilder polyBuilder = new PolygonBuilder(_geomFact);
            BuildSubgraphs(subgraphList, polyBuilder);
            var resultPolyList = polyBuilder.Polygons;

            // just in case...
            if (resultPolyList.Count <= 0)
            {
                return CreateEmptyResultGeometry();
            }

            IGeometry resultGeom = _geomFact.BuildGeometry(resultPolyList);
            return resultGeom;
        }