Ejemplo n.º 1
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;
        }
Ejemplo n.º 2
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();
        }
Ejemplo n.º 3
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);
            }
        }
Ejemplo n.º 4
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();
        }
Ejemplo n.º 6
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);
                    }
                }
            }
        }
Ejemplo n.º 7
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]);
                    }
                }
            }
        }
Ejemplo n.º 8
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);
                }
            }
        }
Ejemplo n.º 9
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();
            }
        }
Ejemplo n.º 10
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);
            }
        }