/// <summary>Static method to construct the convex hull of a Multi_vertex_geometry.</summary>
        /// <remarks>
        /// Static method to construct the convex hull of a Multi_vertex_geometry.
        /// Returns a Geometry.
        /// \param mvg The geometry used to create the convex hull.
        /// </remarks>
        internal static com.epl.geometry.Geometry Construct(com.epl.geometry.MultiVertexGeometry mvg)
        {
            if (mvg.IsEmpty())
            {
                return(new com.epl.geometry.Polygon(mvg.GetDescription()));
            }
            com.epl.geometry.MultiVertexGeometryImpl mvg_impl = (com.epl.geometry.MultiVertexGeometryImpl)mvg._getImpl();
            int N = mvg_impl.GetPointCount();

            if (N <= 2)
            {
                if (N == 1 || mvg_impl.GetXY(0).Equals(mvg_impl.GetXY(1)))
                {
                    com.epl.geometry.Point point = new com.epl.geometry.Point(mvg_impl.GetDescription());
                    mvg_impl.GetPointByVal(0, point);
                    return(point);
                }
                else
                {
                    com.epl.geometry.Point    pt       = new com.epl.geometry.Point();
                    com.epl.geometry.Polyline polyline = new com.epl.geometry.Polyline(mvg_impl.GetDescription());
                    mvg_impl.GetPointByVal(0, pt);
                    polyline.StartPath(pt);
                    mvg_impl.GetPointByVal(1, pt);
                    polyline.LineTo(pt);
                    return(polyline);
                }
            }
            com.epl.geometry.AttributeStreamOfDbl stream      = (com.epl.geometry.AttributeStreamOfDbl)mvg_impl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION);
            com.epl.geometry.ConvexHull           convex_hull = new com.epl.geometry.ConvexHull(stream, N);
            int t0 = 0;
            int tm = 1;

            com.epl.geometry.Point2D pt_0 = new com.epl.geometry.Point2D();
            com.epl.geometry.Point2D pt_m = new com.epl.geometry.Point2D();
            com.epl.geometry.Point2D pt_p = new com.epl.geometry.Point2D();
            stream.Read(t0 << 1, pt_0);
            while (true)
            {
                if (tm >= N)
                {
                    break;
                }
                stream.Read(tm << 1, pt_m);
                if (!pt_m.IsEqual(pt_0, com.epl.geometry.NumberUtils.DoubleEps()))
                {
                    break;
                }
                tm++;
            }
            // We don't want to close the gap between t0 and tm.
            convex_hull.m_tree_hull.AddElement(t0, -1);
            if (tm < N)
            {
                convex_hull.m_tree_hull.AddBiggestElement(tm, -1);
                for (int tp = tm + 1; tp < mvg_impl.GetPointCount(); tp++)
                {
                    // Dynamically insert into the current convex hull
                    stream.Read(tp << 1, pt_p);
                    int p = convex_hull.TreeHull_(pt_p);
                    if (p != -1)
                    {
                        convex_hull.m_tree_hull.SetElement(p, tp);
                    }
                }
            }
            // reset the place holder to the point index.
            // Extracts the convex hull from the tree. Reading the tree in order from first to last is the resulting convex hull.
            com.epl.geometry.VertexDescription description = mvg_impl.GetDescription();
            bool b_has_attributes = (description.GetAttributeCount() > 1);
            int  point_count      = convex_hull.m_tree_hull.Size(-1);

            com.epl.geometry.Geometry hull;
            if (point_count >= 2)
            {
                if (point_count >= 3)
                {
                    hull = new com.epl.geometry.Polygon(description);
                }
                else
                {
                    hull = new com.epl.geometry.Polyline(description);
                }
                com.epl.geometry.MultiPathImpl hull_impl = (com.epl.geometry.MultiPathImpl)hull._getImpl();
                hull_impl.AddPath((com.epl.geometry.Point2D[])null, 0, true);
                com.epl.geometry.Point point = null;
                if (b_has_attributes)
                {
                    point = new com.epl.geometry.Point();
                }
                for (int i = convex_hull.m_tree_hull.GetFirst(-1); i != -1; i = convex_hull.m_tree_hull.GetNext(i))
                {
                    if (b_has_attributes)
                    {
                        mvg_impl.GetPointByVal(convex_hull.m_tree_hull.GetElement(i), point);
                        hull_impl.InsertPoint(0, -1, point);
                    }
                    else
                    {
                        stream.Read(convex_hull.m_tree_hull.GetElement(i) << 1, pt_p);
                        hull_impl.InsertPoint(0, -1, pt_p);
                    }
                }
            }
            else
            {
                System.Diagnostics.Debug.Assert((point_count == 1));
                if (b_has_attributes)
                {
                    com.epl.geometry.Point point = new com.epl.geometry.Point(description);
                    mvg_impl.GetPointByVal(convex_hull.m_tree_hull.GetElement(convex_hull.m_tree_hull.GetFirst(-1)), point);
                    hull = point;
                }
                else
                {
                    stream.Read(convex_hull.m_tree_hull.GetElement(convex_hull.m_tree_hull.GetFirst(-1)) << 1, pt_p);
                    hull = new com.epl.geometry.Point(pt_p);
                }
            }
            return(hull);
        }
Example #2
0
 /// <summary>Copies a path from another multipath.</summary>
 /// <param name="src">The multipath to copy from.</param>
 /// <param name="srcPathIndex">The index of the path in the the source MultiPath.</param>
 /// <param name="bForward">When FALSE, the points are inserted in reverse order.</param>
 public virtual void AddPath(com.epl.geometry.MultiPath src, int srcPathIndex, bool bForward)
 {
     m_impl.AddPath((com.epl.geometry.MultiPathImpl)src._getImpl(), srcPathIndex, bForward);
 }
        private void GeneralizePath(com.epl.geometry.MultiPathImpl mpsrc, int ipath, com.epl.geometry.MultiPathImpl mpdst, com.epl.geometry.Line lineHelper)
        {
            if (mpsrc.GetPathSize(ipath) < 2)
            {
                return;
            }
            int start = mpsrc.GetPathStart(ipath);
            int end   = mpsrc.GetPathEnd(ipath) - 1;

            com.epl.geometry.AttributeStreamOfDbl xy = (com.epl.geometry.AttributeStreamOfDbl)mpsrc.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION);
            bool bClosed = mpsrc.IsClosedPath(ipath);

            com.epl.geometry.AttributeStreamOfInt32 stack = new com.epl.geometry.AttributeStreamOfInt32(0);
            stack.Reserve(mpsrc.GetPathSize(ipath) + 1);
            com.epl.geometry.AttributeStreamOfInt32 resultStack = new com.epl.geometry.AttributeStreamOfInt32(0);
            resultStack.Reserve(mpsrc.GetPathSize(ipath) + 1);
            stack.Add(bClosed ? start : end);
            stack.Add(start);
            com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D();
            while (stack.Size() > 1)
            {
                int i1 = stack.GetLast();
                stack.RemoveLast();
                int i2 = stack.GetLast();
                mpsrc.GetXY(i1, pt);
                lineHelper.SetStartXY(pt);
                mpsrc.GetXY(i2, pt);
                lineHelper.SetEndXY(pt);
                int mid = FindGreatestDistance(lineHelper, pt, xy, i1, i2, end);
                if (mid >= 0)
                {
                    stack.Add(mid);
                    stack.Add(i1);
                }
                else
                {
                    resultStack.Add(i1);
                }
            }
            if (!bClosed)
            {
                resultStack.Add(stack.Get(0));
            }
            int rs_size   = resultStack.Size();
            int path_size = mpsrc.GetPathSize(ipath);

            if (rs_size == path_size && rs_size == stack.Size())
            {
                mpdst.AddPath(mpsrc, ipath, true);
            }
            else
            {
                if (resultStack.Size() > 0)
                {
                    if (m_bRemoveDegenerateParts && resultStack.Size() <= 2)
                    {
                        if (bClosed || resultStack.Size() == 1)
                        {
                            return;
                        }
                        double d = com.epl.geometry.Point2D.Distance(mpsrc.GetXY(resultStack.Get(0)), mpsrc.GetXY(resultStack.Get(1)));
                        if (d <= m_maxDeviation)
                        {
                            return;
                        }
                    }
                    com.epl.geometry.Point point = new com.epl.geometry.Point();
                    for (int i = 0, n = resultStack.Size(); i < n; i++)
                    {
                        mpsrc.GetPointByVal(resultStack.Get(i), point);
                        if (i == 0)
                        {
                            mpdst.StartPath(point);
                        }
                        else
                        {
                            mpdst.LineTo(point);
                        }
                    }
                    if (bClosed)
                    {
                        for (int i_1 = resultStack.Size(); i_1 < 3; i_1++)
                        {
                            mpdst.LineTo(point);
                        }
                        mpdst.ClosePathWithLine();
                    }
                }
            }
        }