/// <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); }
/// <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(); } } } }