示例#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;
        }
示例#2
0
        public void TestCellsCount()
        {
            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));
            input.Add(new Segment(0, 0, 5, 5));
            input.Add(new Segment(5, 5, 10, 10));

            //Build the CLR voronoi
            VoronoiWrapper vw = new VoronoiWrapper();
            foreach (var s in input)
                vw.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);

            vw.ConstructVoronoi();
            List<Tuple<int, int, bool, bool, List<int>, bool, short>> clrCells = vw.GetCells();

            //Build the C# Voronoi
            BoostVoronoi bv = new BoostVoronoi();
            foreach (var s in input)
                bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
            bv.Construct();
            List<Cell> sharpCells = bv.Cells;

            //Test that the outputs have the same length
            Assert.AreEqual(clrCells.Count, sharpCells.Count);
        }
示例#3
0
        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
            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
            List<Cell> cells = bv.Cells;
            List<Edge> edges = bv.Edges;
            List<Vertex> vertices = bv.Vertices;

            foreach (var cell in cells)
            {
                Console.Out.WriteLine(String.Format("Cell Identifier {0}. Is open = {1}", cell.Index, cell.IsOpen));
                foreach (var edgeIndex in cell.EdgesIndex)
                {
                    Edge edge = edges[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 = vertices[edge.Start];
                        Vertex end = vertices[edge.End];

                        Console.Out.WriteLine(
                            String.Format("     From:{0}, To: {1}",
                            start.ToString(),
                            end.ToString()));
                    }
                }
            }
            Console.In.ReadLine();
        }
示例#4
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();
            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("Time elapsed: {0:hh\\:mm\\:ss\\:ff}", stopwatch.Elapsed);
        }
示例#5
0
        public void TestVerticesSequence()
        {
            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));
            input.Add(new Segment(0, 0, 5, 5));
            input.Add(new Segment(5, 5, 10, 10));

            //Build the CLR voronoi
            VoronoiWrapper vw = new VoronoiWrapper();
            foreach (var s in input)
                vw.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);

            vw.ConstructVoronoi();
            List<Tuple<double, double>> clrVertices = vw.GetVertices();

            //Build the C# Voronoi
            BoostVoronoi bv = new BoostVoronoi();
            foreach (var s in input)
                bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
            bv.Construct();
            List<Vertex> sharpVertices = bv.Vertices;

            //Test that the outputs have the same length
            Assert.AreEqual(clrVertices.Count, sharpVertices.Count);

            for (int i = 0; i < sharpVertices.Count; i++)
            {
                Assert.AreEqual(clrVertices[i].Item1, sharpVertices[i].X);
                Assert.AreEqual(clrVertices[i].Item2, sharpVertices[i].Y);
            }
        }
示例#6
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 CLR voronoi
            VoronoiWrapper vw = new VoronoiWrapper();

            foreach (var p in inputPoint)
                vw.AddPoint(p.X, p.Y);

            foreach (var s in inputSegment)
                vw.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);

            vw.ConstructVoronoi();
            List<Tuple<int, int, bool, bool, List<int>, bool, short>> clrCells = vw.GetCells();

            //Build the C# Voronoi
            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();
            List<Edge> sharpEdges = bv.Edges;

            //Test twin reciprocity
            for (int i = 0; i < sharpEdges.Count; i++)
            {
                Assert.AreEqual(i, sharpEdges[sharpEdges[i].Twin].Twin);
            }
        }
示例#7
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 CLR voronoi
            VoronoiWrapper vw = new VoronoiWrapper();

            foreach (var p in inputPoint)
                vw.AddPoint(p.X, p.Y);

            foreach (var s in inputSegment)
                vw.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);

            vw.ConstructVoronoi();
            List<Tuple<int, int, bool, bool, List<int>, bool, short>> clrCells = vw.GetCells();

            //Build the C# Voronoi
            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();
            List<Vertex> vertices = bv.Vertices;
            List<Edge> sharpEdges = bv.Edges;
            List<Cell> sharpCells = bv.Cells;

            int testEdgeIndex = 2;

            for (int i = 0; i < sharpEdges.Count; i++)
            {
                if (sharpCells[sharpEdges[sharpEdges[i].Twin].Cell].SourceCategory == CellSourceCatory.SinglePoint
                    &&
                    sharpCells[sharpEdges[i].Cell].Site == 1)
                    testEdgeIndex = i;

            }

            Edge testEdge = sharpEdges[testEdgeIndex];
            Vertex startVertex = vertices[testEdge.Start];
            Vertex endVertex = vertices[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);
        }
示例#8
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 CLR voronoi
            VoronoiWrapper vw = new VoronoiWrapper();

            foreach (var p in inputPoint)
                vw.AddPoint(p.X, p.Y);

            foreach (var s in inputSegment)
                vw.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);

            vw.ConstructVoronoi();
            List<Tuple<int, int, bool, bool, List<int>, bool, short>> clrCells = vw.GetCells();

            //Build the C# Voronoi
            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();
            List<Vertex> vertices = bv.Vertices;
            List<Edge> sharpEdges = bv.Edges;

            int countPrimary = 0;
            int countSecondary = 0;
            int countFinite = 0;
            for (int i = 0; i < sharpEdges.Count; i++)
            {
                if (sharpEdges[i].IsPrimary)
                    countPrimary++;

                if (sharpEdges[i].IsFinite)
                    countFinite++;

                if (!sharpEdges[i].IsPrimary && sharpEdges[i].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);
        }
示例#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
            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();
            List<Vertex> vertices = bv.Vertices;
            List<Edge> sharpEdges = bv.Edges;
            List<Cell> cells = bv.Cells;

            for (int i = 0; i < cells.Count; i++)
            {
                if(!cells[i].IsOpen)
                {
                    List<int> vertexIndexes = cells[i].GetVertices(ref sharpEdges);
                    Assert.AreEqual(vertexIndexes.Count, 5);
                    Assert.AreEqual(vertexIndexes[0], vertexIndexes[vertexIndexes.Count - 1]);
                }

            }
        }
示例#10
0
        public void TestFindInputSegmentSiteException()
        {
            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
            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();
            List<Vertex> vertices = bv.Vertices;
            List<Edge> sharpEdges = bv.Edges;
            List<Cell> cells = bv.Cells;

            for (int i = 0; i < cells.Count; i++)
            {
                if (cells[i].SourceCategory != CellSourceCatory.InitialSegment
                    && cells[i].SourceCategory != CellSourceCatory.ReverseSegment)
                {
                    bv.RetrieveInputSegment(cells[i]);
                }
            }
        }
示例#11
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;
        }
示例#12
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();
            }
        }