Exemplo n.º 1
0
        private static void AddVerticalBorder(BoostVoronoi voronoi, RTree <Edge> wallsTree, IReadOnlyList <int> border, int x, int maxY)
        {
            var index = 0;

            if (!border.Any())
            {
                voronoi.AddSegment(x, 0, x, maxY);
                wallsTree.Insert(new Edge {
                    Start = new Point2D(x, 0), End = new Point2D(x, maxY)
                }, new RTree <Edge> .Envelope(x, 0, x, maxY));
                return;
            }

            var firstY = border[index++];

            if (firstY != 0)
            {
                var y2 = index >= border.Count ? maxY : border[index++];
                voronoi.AddSegment(x, firstY, x, y2);
                wallsTree.Insert(new Edge {
                    Start = new Point2D(x, firstY), End = new Point2D(x, y2)
                }, new RTree <Edge> .Envelope(x, firstY, x, y2));
            }

            while (index < border.Count)
            {
                var y1 = border[index++];
                var y2 = index >= border.Count ? maxY : border[index++];
                voronoi.AddSegment(x, y1, x, y2);
                wallsTree.Insert(new Edge {
                    Start = new Point2D(x, y1), End = new Point2D(x, y2)
                }, new RTree <Edge> .Envelope(x, y1, x, y2));
            }
        }
Exemplo n.º 2
0
        private static void AddHorizontalBorder(BoostVoronoi voronoi, RTree <Edge> wallsTree, IReadOnlyList <int> border, int y, int maxX)
        {
            var index = 0;

            if (!border.Any())
            {
                voronoi.AddSegment(0, y, maxX, y);
                wallsTree.Insert(new Edge {
                    Start = new Point2D(0, y), End = new Point2D(maxX, y)
                }, new RTree <Edge> .Envelope(0, y, maxX, y));
                return;
            }

            var firstX = border[index++];

            if (firstX != 0)
            {
                var x2 = index >= border.Count ? maxX : border[index++];
                voronoi.AddSegment(firstX, y, x2, y);
                wallsTree.Insert(new Edge {
                    Start = new Point2D(firstX, y), End = new Point2D(x2, y)
                }, new RTree <Edge> .Envelope(firstX, y, x2, y));
            }

            while (index < border.Count)
            {
                var x1 = border[index++];
                var x2 = index >= border.Count ? maxX : border[index++];
                voronoi.AddSegment(x1, y, x2, y);
                wallsTree.Insert(new Edge {
                    Start = new Point2D(x1, y), End = new Point2D(x2, y)
                }, new RTree <Edge> .Envelope(x1, y, x2, y));
            }
        }
Exemplo n.º 3
0
        static void ConstructAndMeasure(ref List <Point> inputPoints, ref List <Segment> inputSegments)
        {
            Console.WriteLine(String.Format("Testing with {0} points and {1} segments", inputPoints.Count, inputSegments.Count));
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var point in inputPoints)
                {
                    bv.AddPoint(point.X, point.Y);
                }

                foreach (var segment in inputSegments)
                {
                    bv.AddSegment(segment.Start.X, segment.Start.Y, segment.End.X, segment.End.Y);
                }



                bv.Construct();

                // Stop timing.
                stopwatch.Stop();
                Console.WriteLine(String.Format("Vertices: {0}, Edges: {1}, Cells: {2}", bv.CountVertices, bv.CountEdges, bv.CountCells));
                Console.WriteLine("Time elapsed: {0:hh\\:mm\\:ss\\:ff}.", stopwatch.Elapsed);

                //bv.Clear();
            }
            inputPoints.Clear();
            inputSegments.Clear();
        }
Exemplo n.º 4
0
        public GraphData(string name, List <Point> inputPoints, List <Segment> segments)
        {
            if (String.IsNullOrEmpty(name) || inputPoints == null || segments == null)
            {
                throw new ArgumentNullException();
            }

            Name = name;
            //InputPoints = new List<Point>();
            //InputSegments = new List<Segment>();
            VoronoiSolution = new BoostVoronoi();

            //Populate the input
            foreach (var point in inputPoints)
            {
                //InputPoints.Add(point);
                VoronoiSolution.AddPoint(point.X, point.Y);
            }

            foreach (var segment in segments)
            {
                //InputSegments.Add(segment);
                VoronoiSolution.AddSegment(segment.Start.X, segment.Start.Y, segment.End.X, segment.End.Y);
            }

            //Construct
            VoronoiSolution.Construct();

            //Populate the output
            //OutputVertices = VoronoiSolution.Vertices;
            //OutputEdges = VoronoiSolution.Edges;
            //OutputCells = VoronoiSolution.Cells;
        }
Exemplo n.º 5
0
        public void TestInvalidCellIndexException()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 0, 10, 0));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 0, 10, 10));

            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();
                bv.GetCell(bv.CountCells);
            }
        }
Exemplo n.º 6
0
        public void TestPrimaryEdges()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 0, 10, 0));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 0, 10, 10));

            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();

                int countPrimary   = 0;
                int countSecondary = 0;
                int countFinite    = 0;
                for (long i = 0; i < bv.CountEdges; i++)
                {
                    Edge edge = bv.GetEdge(i);
                    if (edge.IsPrimary)
                    {
                        countPrimary++;
                    }

                    if (edge.IsFinite)
                    {
                        countFinite++;
                    }

                    if (!edge.IsPrimary && edge.IsFinite)
                    {
                        countSecondary++;
                    }
                }

                //8 finites from the center of the square corner + 8 edges arount the center point.
                Assert.AreEqual(countFinite, 16);

                //Check the number of secondary edge. Because this input is a square with a point in the center, the expected count is 0.
                Assert.AreEqual(countSecondary, 0);

                Assert.AreEqual(countPrimary, countFinite - countSecondary);
            }
        }
        static void Main(string[] args)
        {
            //Define a set of segments and pass them to the voronoi wrapper
            List <Segment> input = new List <Segment>();

            input.Add(new Segment(0, 0, 0, 10));
            input.Add(new Segment(0, 10, 10, 10));
            input.Add(new Segment(10, 10, 10, 0));
            input.Add(new Segment(10, 0, 0, 0));

            //Instanciate the voronoi wrapper
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                //Add a point
                bv.AddPoint(5, 5);

                //Add the segments
                foreach (var s in input)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                //Build the C# Voronoi
                bv.Construct();

                //Get the voronoi output
                for (long i = 0; i < bv.CountCells; i++)
                {
                    Cell cell = bv.GetCell(i);
                    Console.Out.WriteLine(String.Format("Cell Identifier {0}. Is open = {1}", cell.Index, cell.IsOpen));
                    foreach (var edgeIndex in cell.EdgesIndex)
                    {
                        Edge edge = bv.GetEdge(edgeIndex);
                        Console.Out.WriteLine(
                            String.Format("  Edge Index: {0}. Start vertex index: {1}, End vertex index: {2}",
                                          edgeIndex,
                                          edge.Start,
                                          edge.End));

                        //If the vertex index equals -1, it means the edge is infinite. It is impossible to print the coordinates.
                        if (edge.IsLinear)
                        {
                            Vertex start = bv.GetVertex(edge.Start);
                            Vertex end   = bv.GetVertex(edge.End);

                            Console.Out.WriteLine(
                                String.Format("     From:{0}, To: {1}",
                                              start.ToString(),
                                              end.ToString()));
                        }
                    }
                }
            }
            Console.In.ReadLine();
        }
Exemplo n.º 8
0
        public void TestFindInputPointSiteException()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 0, 10, 0));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 0, 10, 10));

            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();

                for (long i = 0; i < bv.CountCells; i++)
                {
                    Cell cell = bv.GetCell(i);
                    if (cell.SourceCategory != CellSourceCatory.SegmentStartPoint &&
                        cell.SourceCategory != CellSourceCatory.SegmentEndPoint &&
                        cell.SourceCategory != CellSourceCatory.SinglePoint)
                    {
                        bv.RetrieveInputPoint(cell);
                    }
                }
            }
        }
Exemplo n.º 9
0
        public void TestGetCellVertices()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 0, 10, 0));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 0, 10, 10));

            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();

                for (long i = 0; i < bv.CountCells; i++)
                {
                    Cell cell = bv.GetCell(i);
                    if (!cell.IsOpen)
                    {
                        List <long> vertexIndexes = cell.VerticesIndex;
                        Assert.AreEqual(vertexIndexes.Count, 5);
                        Assert.AreEqual(vertexIndexes[0], vertexIndexes[vertexIndexes.Count - 1]);
                    }
                }
            }
        }
Exemplo n.º 10
0
        public void TestSegmentTwin()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 10, 10, 0));
            inputSegment.Add(new Segment(10, 0, 0, 0));


            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();

                //Test twin reciprocity
                for (long i = 0; i < bv.CountEdges; i++)
                {
                    Edge edge = bv.GetEdge(i);
                    Edge twin = bv.GetEdge(edge.Twin);
                    Assert.AreEqual(i, twin.Twin);
                }
            }
        }
Exemplo n.º 11
0
        public static IReadOnlyList <TerrainNode> Analyze <TNode>(Map2D <TNode> map, Func <TNode, bool> isBlocking, int pruneDistanceToObstacleSquared, int maxDistanceToMergeSquared)
        {
            var tracingResult = ComponentLabeling.Trace(map, node => isBlocking(node) ? 1 : 0);

            var contours = new List <List <Point2D> >();

            foreach (var blob in tracingResult.Blobs)
            {
                contours.AddRange(
                    new[] { blob.ExternalContour }.Concat(blob.InternalContours).Select(
                        points => DouglasPeucker.Simplify(points.ToList(), 2 * 2, DistanceSquared)));
            }

            var edges        = new List <Edge>();
            var leftBorder   = new List <int>();
            var rightBorder  = new List <int>();
            var topBorder    = new List <int>();
            var bottomBorder = new List <int>();
            var wallsTree    = new RTree <Edge>(5, 9);

            using (var voronoi = new BoostVoronoi())
            {
                foreach (var contour in contours)
                {
                    var startPoint = contour.First();
                    foreach (var point in contour.Skip(1))
                    {
                        voronoi.AddSegment((int)startPoint.X, (int)startPoint.Y, (int)point.X, (int)point.Y);
                        wallsTree.Insert(new Edge {
                            Start = startPoint, End = point
                        }, new RTree <Edge> .Envelope(startPoint, point));

                        if ((int)startPoint.X == 0 && (int)point.X == 0)
                        {
                            leftBorder.Add((int)startPoint.Y);
                            leftBorder.Add((int)point.Y);
                        }

                        if ((int)startPoint.X == map.Width - 1 && (int)point.X == map.Width - 1)
                        {
                            rightBorder.Add((int)startPoint.Y);
                            rightBorder.Add((int)point.Y);
                        }

                        if ((int)startPoint.Y == 0 && (int)point.Y == 0)
                        {
                            topBorder.Add((int)startPoint.X);
                            topBorder.Add((int)point.X);
                        }

                        if ((int)startPoint.Y == map.Height - 1 && (int)point.Y == map.Height - 1)
                        {
                            bottomBorder.Add((int)startPoint.X);
                            bottomBorder.Add((int)point.X);
                        }

                        startPoint = point;
                    }
                }

                AddVerticalBorder(voronoi, wallsTree, leftBorder.OrderBy(x => x).ToList(), 0, map.Height - 1);
                AddVerticalBorder(voronoi, wallsTree, rightBorder.OrderBy(x => x).ToList(), map.Width - 1, map.Height - 1);
                AddHorizontalBorder(voronoi, wallsTree, topBorder.OrderBy(x => x).ToList(), 0, map.Width - 1);
                AddHorizontalBorder(voronoi, wallsTree, bottomBorder.OrderBy(x => x).ToList(), map.Height - 1, map.Width - 1);

                var visitedTwins = new List <long>();
                voronoi.Construct();
                for (long i = 0; i < voronoi.CountEdges; i++)
                {
                    var edge = voronoi.GetEdge(i);

                    if (!edge.IsPrimary || !edge.IsFinite || visitedTwins.Contains(edge.Twin))
                    {
                        continue;
                    }

                    visitedTwins.Add(edge.Twin);

                    var start = voronoi.GetVertex(edge.Start);
                    var end   = voronoi.GetVertex(edge.End);

                    if (double.IsNaN(start.X) || double.IsNaN(start.Y) || double.IsNaN(end.X) || double.IsNaN(end.Y))
                    {
                        continue;
                    }

                    if (edges.Any(
                            e => (int)e.Start.X == (int)start.X && (int)e.Start.Y == (int)start.Y &&
                            (int)e.End.X == (int)end.X && (int)e.End.Y == (int)end.Y ||
                            (int)e.Start.X == (int)end.X && (int)e.Start.Y == (int)end.Y &&
                            (int)e.End.X == (int)start.X && (int)e.End.Y == (int)start.Y))
                    {
                        continue;
                    }

                    edges.Add(new Edge
                    {
                        Start = new Point2D((int)start.X, (int)start.Y),
                        End   = new Point2D((int)end.X, (int)end.Y)
                    });
                }
            }

            var walkableEdges = edges.Where(edge => IsOnNonBlocking(edge, map, isBlocking)).ToList();

            var nodes = new List <InternalNode>();

            foreach (var node in walkableEdges)
            {
                if (node.Start == node.End)
                {
                    continue;
                }

                var startNode = nodes.Find(x => x.Point == node.Start);
                if (startNode == null)
                {
                    startNode = CreateNode(wallsTree, node.Start);
                    nodes.Add(startNode);
                }

                var endNode = nodes.Find(x => x.Point == node.End);
                if (endNode == null)
                {
                    endNode = CreateNode(wallsTree, node.End);
                    nodes.Add(endNode);
                }

                startNode.Neighbors.Add(endNode);
                endNode.Neighbors.Add(startNode);
            }

            PruneNodes(nodes, pruneDistanceToObstacleSquared);

            GetPointsOfInterest(nodes, pruneDistanceToObstacleSquared, maxDistanceToMergeSquared);

            var mergedNodes = MergeNodes(nodes, maxDistanceToMergeSquared);

            return(MapToTerrainNodes(mergedNodes, wallsTree));
        }
Exemplo n.º 12
0
        private ISegmentCollection createSegments(Cell cell, BoostVoronoi bv, ArcConstructionMethods method, ISpatialReference spatialReference)
        {
            List <Cell>   cells    = bv.Cells;
            List <Edge>   edges    = bv.Edges;
            List <Vertex> vertices = bv.Vertices;

            IPoint previousEndPoint = null;

            ISegmentCollection segmentCollection = new PolygonClass()
            {
                SpatialReference = spatialReference
            };

            // As per boost documentation, edges are returned in counter clockwise (CCW) rotation.
            //  voronoi_edge_type* next()	Returns the pointer to the CCW next edge within the corresponding Voronoi cell.  Edges not necessarily share a common vertex (e.g. infinite edges).
            for (int i = cell.EdgesIndex.Count - 1; i >= 0; i--)
            {
                Edge edge = edges[cell.EdgesIndex[i]];


                //If the vertex index equals -1, it means the edge is infinite. It is impossible to print the coordinates.
                if (!edge.IsFinite && edge.End < 0)
                {
                    // this is the ending portion of a pair of infinite edges, file the previous edge with Start >= 0
                    Edge previous = null;
                    for (int k = i + 1; k < cell.EdgesIndex.Count; k++)
                    {
                        previous = edges[cell.EdgesIndex[k]];
                        if (previous.End >= 0)
                        {
                            break;
                        }
                        previous = null;
                    }
                    if (previous == null)
                    {
                        for (int k = 0; k < i; k++)
                        {
                            previous = edges[cell.EdgesIndex[k]];
                            if (previous.End >= 0)
                            {
                                break;
                            }
                            previous = null;
                        }
                    }
                    if (previous == null)
                    {
                        throw new Exception("No outbound infinite edge could be found");
                    }

                    //Add a straight line segment
                    Vertex start     = vertices[previous.End];
                    IPoint FromPoint = new PointClass()
                    {
                        X = start.X, Y = start.Y, SpatialReference = spatialReference
                    };
                    Vertex end     = vertices[edge.Start];
                    IPoint ToPoint = new PointClass()
                    {
                        X = end.X, Y = end.Y, SpatialReference = spatialReference
                    };

                    segmentCollection.AddSegment(new LineClass()
                    {
                        FromPoint = FromPoint, ToPoint = ToPoint, SpatialReference = spatialReference
                    });
                    previousEndPoint = ToPoint;
                }
                else if (edge.IsFinite)
                {
                    Vertex start     = vertices[edge.End];
                    IPoint FromPoint = new PointClass()
                    {
                        X = start.X, Y = start.Y, SpatialReference = spatialReference
                    };
                    if (previousEndPoint != null)
                    {
                        if ((Math.Abs(previousEndPoint.X - FromPoint.X) > 0.05 || Math.Abs(previousEndPoint.X - FromPoint.X) > 0.05))
                        {
                            throw new Exception("Significant change between last end point and current start point");
                        }
                        else
                        {
                            FromPoint = previousEndPoint;
                        }
                    }
                    Vertex end     = vertices[edge.Start];
                    IPoint ToPoint = new PointClass()
                    {
                        X = end.X, Y = end.Y, SpatialReference = spatialReference
                    };

                    if (method == ArcConstructionMethods.Straight || edge.IsLinear)
                    {
                        segmentCollection.AddSegment(new LineClass()
                        {
                            FromPoint = FromPoint, ToPoint = ToPoint, SpatialReference = spatialReference
                        });
                        previousEndPoint = ToPoint;
                    }
                    else
                    {
                        // We need three points, use start, end, mid-point between focus and directrix
                        Cell twinCell = cells[edges[edge.Twin].Cell];


                        VPoint pointSite; VSegment lineSite;
                        if (cell.ContainsPoint && twinCell.ContainsSegment)
                        {
                            pointSite = bv.RetrieveInputPoint(cell);
                            lineSite  = bv.RetrieveInputSegment(twinCell);
                        }
                        else if (cell.ContainsSegment && twinCell.ContainsPoint)
                        {
                            pointSite = bv.RetrieveInputPoint(twinCell);
                            lineSite  = bv.RetrieveInputSegment(cell);
                        }

                        else
                        {
                            throw new Exception("Invalid edge, curves should only be present between a point and a line");
                        }

                        double scaleFactor = Convert.ToDouble(bv.ScaleFactor);
                        IPoint aoPointSite = new Point()
                        {
                            X = Convert.ToDouble(pointSite.X) / scaleFactor,
                            Y = Convert.ToDouble(pointSite.Y) / scaleFactor,
                            SpatialReference = spatialReference
                        };

                        ISegment aoLineSite = new LineClass()
                        {
                            FromPoint = new PointClass()
                            {
                                X = Convert.ToDouble(lineSite.Start.X) / scaleFactor,
                                Y = Convert.ToDouble(lineSite.Start.Y) / scaleFactor,
                                SpatialReference = spatialReference
                            },
                            ToPoint = new PointClass()
                            {
                                X = Convert.ToDouble(lineSite.End.X) / scaleFactor,
                                Y = Convert.ToDouble(lineSite.End.Y) / scaleFactor,
                                SpatialReference = spatialReference
                            },
                            SpatialReference = spatialReference
                        };


                        if (method == ArcConstructionMethods.Approximate)
                        {
                            List <Vertex> sampledVerticed = null;
                            try
                            {
                                sampledVerticed = bv.SampleCurvedEdge(edge, aoLineSite.Length / 10);
                            }
                            catch (FocusOnDirectixException e)
                            {
                                //Log any exception here is required
                                sampledVerticed = new List <Vertex>()
                                {
                                    start, end
                                };
                            }
                            catch (UnsolvableVertexException e)
                            {
                                sampledVerticed = new List <Vertex>()
                                {
                                    start, end
                                };
                            }

                            sampledVerticed.Reverse();
                            List <IPoint> discretizedEdge = sampledVerticed.Select(
                                p => new Point()
                            {
                                X = p.X, Y = p.Y
                            }
                                ).ToList <IPoint>();

                            IPoint prev = discretizedEdge[0];
                            foreach (IPoint v in discretizedEdge.Skip(1))
                            {
                                segmentCollection.AddSegment(new LineClass()
                                {
                                    FromPoint = new Point()
                                    {
                                        X = prev.X, Y = prev.Y, SpatialReference = spatialReference
                                    },
                                    ToPoint = new Point()
                                    {
                                        X = v.X, Y = v.Y, SpatialReference = spatialReference
                                    },
                                    SpatialReference = spatialReference
                                });
                                prev = v;
                            }
                            previousEndPoint = discretizedEdge.Last();
                        }
                        else if (method == ArcConstructionMethods.Circular)
                        {
                            IPoint nearPoint = ((IProximityOperator)aoLineSite).ReturnNearestPoint(aoPointSite, esriSegmentExtension.esriNoExtension);
                            IPoint midpoint  = new PointClass()
                            {
                                X = (nearPoint.X + aoPointSite.X) / 2,
                                Y = (nearPoint.Y + aoPointSite.Y) / 2,
                                SpatialReference = spatialReference
                            };

                            IConstructCircularArc constArc = new CircularArcClass()
                            {
                                SpatialReference = spatialReference
                            };
                            constArc.ConstructThreePoints(FromPoint, midpoint, ToPoint, false);
                            ICircularArc arc = (ICircularArc)constArc;

                            if (!arc.IsMinor)
                            {
                                constArc = new CircularArcClass()
                                {
                                    SpatialReference = spatialReference
                                };
                                constArc.ConstructEndPointsRadius(FromPoint, ToPoint, !arc.IsCounterClockwise, arc.Radius, true);
                                arc = (ICircularArc)constArc;
                            }
                            segmentCollection.AddSegment((ISegment)arc);
                            previousEndPoint = arc.ToPoint;
                        }
                        else if (method == ArcConstructionMethods.Ellipse)
                        {
                            IPoint nearPoint = ((IProximityOperator)aoLineSite).ReturnNearestPoint(aoPointSite, esriSegmentExtension.esriExtendTangents);
                            nearPoint.SpatialReference = spatialReference;

                            ILine lineToFocus = new LineClass()
                            {
                                FromPoint = nearPoint, ToPoint = aoPointSite, SpatialReference = spatialReference
                            };
                            ILine semiMajor = new LineClass()
                            {
                                SpatialReference = spatialReference
                            };
                            lineToFocus.QueryTangent(esriSegmentExtension.esriExtendTangentAtTo, 1, true, 100 * lineToFocus.Length, semiMajor);

                            IPoint center = new PointClass()
                            {
                                X = (semiMajor.FromPoint.X + semiMajor.ToPoint.X) / 2,
                                Y = (semiMajor.FromPoint.Y + semiMajor.ToPoint.Y) / 2,
                                SpatialReference = spatialReference
                            };

                            double minor_length = Math.Sqrt(
                                Math.Pow(distance(semiMajor.FromPoint, ToPoint) + distance(semiMajor.ToPoint, ToPoint), 2)
                                - Math.Pow(semiMajor.Length, 2));

                            IEllipticArc arc = new EllipticArcClass()
                            {
                                SpatialReference = spatialReference
                            };
                            double rotation = lineToFocus.Angle;
                            double from     = GetAngle(center, FromPoint);

                            arc.PutCoords(false, center, FromPoint, ToPoint, rotation, minor_length / semiMajor.Length, esriArcOrientation.esriArcMinor);

                            segmentCollection.AddSegment((ISegment)arc);
                            previousEndPoint = arc.ToPoint;
                        }
                    }
                }
            }
            return(segmentCollection);
        }
Exemplo n.º 13
0
        // Execute: Execute the function given the array of the parameters
        public void Execute(IArray paramvalues, ITrackCancel trackcancel, IGPEnvironmentManager envMgr, IGPMessages message)
        {
            IFeatureClass outputFeatureClass = null;

            try
            {
                // get the input feature class
                IGPMultiValue inputFeatureClasses_Parameter = (IGPMultiValue)m_GPUtilities.UnpackGPValue(paramvalues.get_Element(0));
                layer[]       input_featureClasses          = new layer[inputFeatureClasses_Parameter.Count];
                for (int i = 0; i < inputFeatureClasses_Parameter.Count; i++)
                {
                    IGPValue inputFeatureClass_Parameter = inputFeatureClasses_Parameter.get_Value(i);

                    IFeatureClass inputFeatureClass;
                    IQueryFilter  inputQF;

                    m_GPUtilities.DecodeFeatureLayer(inputFeatureClass_Parameter, out inputFeatureClass, out inputQF);

                    input_featureClasses[i] = new layer()
                    {
                        featureclass = inputFeatureClass, qFilter = inputQF
                    };
                }


                if (input_featureClasses.Length == 0 || input_featureClasses.Any(w => w.featureclass == null))
                {
                    message.AddError(2, "Could not open one or more input dataset.");
                    return;
                }

                //IFields additionalFields = new FieldsClass();
                //additionalFields.AddField(FEATURE_SOURCE_FIELD_NAME, esriFieldType.esriFieldTypeString);
                //additionalFields.AddField(FEATURE_ID_FIELD_NAME, esriFieldType.esriFieldTypeInteger);
                //additionalFields.AddField(
                //    input_featureClasses[0].featureclass.Fields.get_Field(
                //    input_featureClasses[0].featureclass.Fields.FindField(
                //    input_featureClasses[0].featureclass.ShapeFieldName)));

                // create the output feature class
                IGPValue outputFeatureClass_Parameter = m_GPUtilities.UnpackGPValue(paramvalues.get_Element(1));
                outputFeatureClass = GPHelperFunctions.CreateFeatureClass(outputFeatureClass_Parameter, envMgr);

                if (outputFeatureClass == null)
                {
                    message.AddError(2, "Could not create output dataset.");
                    return;
                }



                IGPString curveTypeParameter = (IGPString)m_GPUtilities.UnpackGPValue(paramvalues.get_Element(2));
                ArcConstructionMethods method;
                if (!Enum.TryParse <ArcConstructionMethods>(curveTypeParameter.Value, true, out method))
                {
                    message.AddError(2, string.Format("The value {0} is not expected.  Expected values are: {1}.",
                                                      curveTypeParameter.Value,
                                                      string.Join(",", Enum.GetNames(typeof(ArcConstructionMethods)))));
                    return;
                }

                IStepProgressor stepPro = (IStepProgressor)trackcancel;
                GPHelperFunctions.dropSpatialIndex(outputFeatureClass);

                BoostVoronoi bv = new BoostVoronoi(100);

                double          minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue;
                List <site_key> point_sites   = new List <site_key>();
                List <site_key> segment_sites = new List <site_key>();

                for (short i = 0; i < input_featureClasses.Length; i++)
                {
                    layer l         = input_featureClasses[i];
                    int   featcount = l.featureclass.FeatureCount(l.qFilter);

                    stepPro.MinRange  = 0;
                    stepPro.MaxRange  = featcount;
                    stepPro.StepValue = (1);
                    stepPro.Message   = "Reading features";
                    stepPro.Position  = 0;
                    stepPro.Show();

                    IFeatureCursor cursor = null;
                    IFeature       row    = null;

                    try
                    {
                        cursor = l.featureclass.Search(l.qFilter, false);
                        while ((row = cursor.NextFeature()) != null)
                        {
                            stepPro.Step();
                            IPoint point = row.Shape as IPoint;
                            if (point != null)
                            {
                                double X = point.X;
                                double Y = point.Y;

                                minX = Math.Min(minX, X);
                                maxX = Math.Max(maxX, X);

                                minY = Math.Min(minY, Y);
                                maxY = Math.Max(maxY, Y);

                                bv.AddPoint(point.X, point.Y);
                                point_sites.Add(new site_key(i, row.OID));
                            }

                            IMultipoint multipoint = row.Shape as IMultipoint;
                            if (multipoint != null)
                            {
                                IPointCollection pointCollection = (IPointCollection)multipoint;
                                IEnumVertex      vertices        = pointCollection.EnumVertices;

                                IPoint vertex = null; int part, index;
                                vertices.Next(out vertex, out part, out index);

                                minX = Math.Min(minX, multipoint.Envelope.XMin);
                                maxX = Math.Max(maxX, multipoint.Envelope.XMax);

                                minY = Math.Min(minY, multipoint.Envelope.YMin);
                                maxY = Math.Max(maxY, multipoint.Envelope.YMax);

                                while (vertex != null)
                                {
                                    bv.AddPoint(vertex.X, vertex.Y);
                                    point_sites.Add(new site_key(i, row.OID));

                                    vertices.Next(out vertex, out part, out index);
                                }
                            }

                            IPolyline polyline = row.Shape as IPolyline;
                            if (polyline != null)
                            {
                                double fromX = polyline.FromPoint.X;
                                double fromY = polyline.FromPoint.Y;
                                double toX   = polyline.ToPoint.X;
                                double toY   = polyline.ToPoint.Y;

                                if (toX < fromX)
                                {
                                    minX = Math.Min(minX, toX);
                                    maxX = Math.Max(maxX, fromX);
                                }
                                else
                                {
                                    minX = Math.Min(minX, fromX);
                                    maxX = Math.Max(maxX, toX);
                                }

                                if (toY < fromY)
                                {
                                    minY = Math.Min(minY, toY);
                                    maxY = Math.Max(maxY, fromY);
                                }
                                else
                                {
                                    minY = Math.Min(minY, fromY);
                                    maxY = Math.Max(maxY, toY);
                                }

                                bv.AddSegment(
                                    polyline.FromPoint.X, polyline.FromPoint.Y,
                                    polyline.ToPoint.X, polyline.ToPoint.Y
                                    );


                                segment_sites.Add(new site_key(i, row.OID));
                            }

                            Marshal.ReleaseComObject(row);
                        }
                    }
                    finally
                    {
                        if (row != null)
                        {
                            Marshal.ReleaseComObject(row);
                        }
                        if (cursor != null)
                        {
                            Marshal.ReleaseComObject(cursor);
                        }

                        stepPro.Hide();
                    }
                }

                message.AddMessage(String.Format("{0}, {1} -> {2}, {3}", minX, minY, maxX, maxY));

                int width  = Math.Max((int)((maxX - minX) * 0.1), 1);
                int height = Math.Max((int)((maxY - minY) * 0.1), 1);

                maxX = maxX + width;
                minX = minX - width;
                maxY = maxY + height;
                minY = minY - height;

                message.AddMessage(String.Format("{0}, {1} -> {2}, {3}", minX, minY, maxX, maxY));
                bv.AddSegment(minX, minY, maxX, minY);
                segment_sites.Add(new site_key(-1, -1));
                bv.AddSegment(maxX, minY, maxX, maxY);
                segment_sites.Add(new site_key(-1, -1));
                bv.AddSegment(maxX, maxY, minX, maxY);
                segment_sites.Add(new site_key(-1, -1));
                bv.AddSegment(minX, maxY, minX, minY);
                segment_sites.Add(new site_key(-1, -1));

                stepPro.Message  = "Solve Voronoi";
                stepPro.MaxRange = 0;
                stepPro.MaxRange = 0;
                stepPro.Show();

                bv.Construct();

                stepPro.Hide();

                int featureSourceIndx = outputFeatureClass.Fields.FindField(FEATURE_SOURCE_FIELD_NAME);
                int featureIDIndx     = outputFeatureClass.Fields.FindField(FEATURE_ID_FIELD_NAME);

                IFeatureCursor inserts = null;
                IFeatureBuffer buffer  = null;
                try
                {
                    object            missing          = Type.Missing;
                    ISpatialReference spatialReference = ((IGeoDataset)outputFeatureClass).SpatialReference;
                    inserts = outputFeatureClass.Insert(false);
                    buffer  = outputFeatureClass.CreateFeatureBuffer();

                    List <Cell> cells = bv.Cells;
                    message.AddMessage(string.Format("{0} cells calculated", cells.Count));
                    List <Edge> edges = bv.Edges;
                    message.AddMessage(string.Format("{0} edges calculated", edges.Count));
                    List <Vertex> vertices = bv.Vertices;
                    message.AddMessage(string.Format("{0} vertexes calculated", vertices.Count));

                    stepPro.Message  = "Write cells";
                    stepPro.MaxRange = 0;
                    stepPro.MaxRange = cells.Count;
                    stepPro.Show();


                    for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++)
                    {
                        try
                        {
                            if (cellIndex % 5000 == 0)
                            {
                                message.AddMessage(String.Format("{0}. {1} cells processed.", DateTime.Now, cellIndex));
                            }

                            Cell cell        = cells[cellIndex];
                            int  currentSite = cell.Site;
                            IGeometryCollection geometryCollection = new GeometryBagClass()
                            {
                                SpatialReference = spatialReference
                            };

                            //ignores any sliver cells
                            if (cell.IsOpen || cell.EdgesIndex.Count < 3)
                            {
                                continue;
                            }

                            ISegmentCollection segmentCollection = createSegments(cell, bv, method, spatialReference);

                            if (((IArea)segmentCollection).Area <= 0)
                            {
                                message.AddMessage("A invalid geometry has been detected, try reversing the orientation.");
                                ISegmentCollection reversed_segmentCollection = new PolygonClass()
                                {
                                    SpatialReference = spatialReference
                                };
                                for (int i = segmentCollection.SegmentCount - 1; i >= 0; i--)
                                {
                                    ISegment segment = (ISegment)segmentCollection.get_Segment(i);
                                    segment.ReverseOrientation();
                                    reversed_segmentCollection.AddSegment(segment);
                                }
                                segmentCollection = reversed_segmentCollection;
                            }

                            ((IPolygon)segmentCollection).SpatialReference = spatialReference;
                            if (((IArea)segmentCollection).Area <= 0)
                            {
                                message.AddWarning("An empty shell has been created");

                                for (int i = 0; i < segmentCollection.SegmentCount; i++)
                                {
                                    ISegment segment = (ISegment)segmentCollection.get_Segment(i);
                                    message.AddMessage(String.Format("From {0}, {1} To {2},{3}",
                                                                     segment.FromPoint.X, segment.FromPoint.Y,
                                                                     segment.ToPoint.X, segment.ToPoint.Y));
                                }
                            }


                            //set attributes
                            site_key sk = (currentSite >= point_sites.Count) ? segment_sites[currentSite - point_sites.Count] : point_sites[currentSite];
                            if (!sk.isEmpty)
                            {
                                buffer.set_Value(featureSourceIndx, input_featureClasses[sk.featureClassIndex].featureclass.AliasName);
                                buffer.set_Value(featureIDIndx, sk.objectID);
                            }
                            else
                            {
                                buffer.set_Value(featureSourceIndx, DBNull.Value);
                                buffer.set_Value(featureIDIndx, DBNull.Value);
                            }


                            IPolygon voronoiPolygon = (IPolygon)segmentCollection;
                            buffer.Shape = (IPolygon)voronoiPolygon;
                            inserts.InsertFeature(buffer);
                        }
                        catch (Exception e)
                        {
                            message.AddWarning("Failed to create a cell");
                        }
                    }
                }
                finally
                {
                    if (buffer != null)
                    {
                        Marshal.ReleaseComObject(buffer);
                    }
                    if (inserts != null)
                    {
                        Marshal.ReleaseComObject(inserts);
                    }
                }

                GPHelperFunctions.createSpatialIndex(outputFeatureClass);
            }
            catch (Exception exx)
            {
                message.AddError(2, exx.Message);
                message.AddMessage(exx.ToString());
            }
            finally
            {
                if (outputFeatureClass != null)
                {
                    Marshal.ReleaseComObject(outputFeatureClass);
                }

                ((IProgressor)trackcancel).Hide();
            }
        }
Exemplo n.º 14
0
        public void TestSegmentDicretization()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 0, 10, 0));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 0, 10, 10));

            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();

                long testEdgeIndex = 2;

                for (long i = 0; i < bv.CountEdges; i++)
                {
                    Edge edge = bv.GetEdge(i);
                    Edge twin = bv.GetEdge(edge.Twin);

                    Cell edgeCell = bv.GetCell(edge.Cell);
                    Cell twinCell = bv.GetCell(twin.Cell);

                    if (twinCell.SourceCategory == CellSourceCatory.SinglePoint
                        &&
                        edgeCell.Site == 1)
                    {
                        testEdgeIndex = i;
                    }
                }

                Edge          testEdge    = bv.GetEdge(testEdgeIndex);
                Vertex        startVertex = bv.GetVertex(testEdge.Start);
                Vertex        endVertex   = bv.GetVertex(testEdge.End);
                List <Vertex> dvertices   = bv.SampleCurvedEdge(testEdge, Distance.ComputeDistanceBetweenPoints(startVertex, endVertex) / 2);
                int           lastDicretizedVertexIndex = dvertices.Count - 1;

                //Make sure that the end points are consistents
                Assert.AreEqual(dvertices[0].X, startVertex.X);
                Assert.AreEqual(dvertices[0].Y, startVertex.Y);

                Assert.AreEqual(dvertices[lastDicretizedVertexIndex].X, endVertex.X);
                Assert.AreEqual(dvertices[lastDicretizedVertexIndex].Y, endVertex.Y);

                Assert.AreEqual(dvertices[2].X, 2.5);
                Assert.AreEqual(dvertices[2].Y, 5);
            }
        }