private bool _simplify() { if (m_shape.GetGeometryType(m_geometry) == com.epl.geometry.Geometry.Type.Polygon.Value() && m_shape.GetFillRule(m_geometry) == com.epl.geometry.Polygon.FillRule.enumFillRuleWinding) { com.epl.geometry.TopologicalOperations ops = new com.epl.geometry.TopologicalOperations(); ops.PlanarSimplifyNoCrackingAndCluster(m_fixSelfTangency, m_shape, m_geometry, m_progressTracker); System.Diagnostics.Debug.Assert((m_shape.GetFillRule(m_geometry) == com.epl.geometry.Polygon.FillRule.enumFillRuleOddEven)); } bool bChanged = false; bool bNeedWindingRepeat = true; bool bWinding = false; m_userIndexSortedIndexToVertex = -1; m_userIndexSortedAngleIndexToVertex = -1; int pointCount = m_shape.GetPointCount(m_geometry); // Sort vertices lexicographically // Firstly copy allvertices to an array. com.epl.geometry.AttributeStreamOfInt32 verticesSorter = new com.epl.geometry.AttributeStreamOfInt32(0); verticesSorter.Reserve(pointCount); for (int path = m_shape.GetFirstPath(m_geometry); path != -1; path = m_shape.GetNextPath(path)) { int vertex = m_shape.GetFirstVertex(path); for (int index = 0, n = m_shape.GetPathSize(path); index < n; index++) { verticesSorter.Add(vertex); vertex = m_shape.GetNextVertex(vertex); } } // Sort verticesSorter.Sort(0, pointCount, new com.epl.geometry.Simplificator.SimplificatorVertexComparer(this)); // SORTDYNAMICARRAYEX(verticesSorter, int, 0, pointCount, // SimplificatorVertexComparer, this); // Copy sorted vertices to the m_sortedVertices list. Make a mapping // from the edit shape vertices to the sorted vertices. m_userIndexSortedIndexToVertex = m_shape.CreateUserIndex(); // this index // is used // to map // from edit // shape // vertex to // the // m_sortedVertices // list m_sortedVertices = new com.epl.geometry.IndexMultiDCList(); m_sortedVerticesListIndex = m_sortedVertices.CreateList(0); for (int i = 0; i < pointCount; i++) { int vertex = verticesSorter.Get(i); { // debug com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); m_shape.GetXY(vertex, pt); // for debugging double y = pt.x; } int vertexlistIndex = m_sortedVertices.AddElement(m_sortedVerticesListIndex, vertex); m_shape.SetUserIndex(vertex, m_userIndexSortedIndexToVertex, vertexlistIndex); } // remember the sorted list element on the // vertex. // When we remove a vertex, we also remove associated sorted list // element. m_userIndexSortedAngleIndexToVertex = m_shape.CreateUserIndex(); // create // additional // list // to // store // angular // sort // mapping. m_nextVertexToProcess = -1; if (_cleanupSpikes()) { // cleanup any spikes on the polygon. bChanged = true; } // External iteration loop for the simplificator. // ST. I am not sure if it actually needs this loop. TODO: figure this // out. while (bNeedWindingRepeat) { bNeedWindingRepeat = false; int max_iter = m_shape.GetPointCount(m_geometry) + 10 > 30 ? 1000 : (m_shape.GetPointCount(m_geometry) + 10) * (m_shape.GetPointCount(m_geometry) + 10); // Simplify polygon int iRepeatNum = 0; bool bNeedRepeat = false; do { // Internal iteration loop for the simplificator. // ST. I am not sure if it actually needs this loop. TODO: figure // this out. // while (bNeedRepeat); bNeedRepeat = false; bool bVertexRecheck = false; m_firstCoincidentVertex = -1; int coincidentCount = 0; com.epl.geometry.Point2D ptFirst = new com.epl.geometry.Point2D(); com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); // Main loop of the simplificator. Go through the vertices and // for those that have same coordinates, for (int vlistindex = m_sortedVertices.GetFirst(m_sortedVerticesListIndex); vlistindex != com.epl.geometry.IndexMultiDCList.NullNode();) { int vertex = m_sortedVertices.GetData(vlistindex); { // debug // Point2D pt = new Point2D(); m_shape.GetXY(vertex, pt); double d = pt.x; } if (m_firstCoincidentVertex != -1) { // Point2D pt = new Point2D(); m_shape.GetXY(vertex, pt); if (ptFirst.IsEqual(pt)) { coincidentCount++; } else { ptFirst.SetCoords(pt); m_nextVertexToProcess = vlistindex; // we remeber the // next index in // the member // variable to // allow it to // be updated if // a vertex is // removed // inside of the // _ProcessBunch. if (coincidentCount > 0) { bool result = _processBunch(); // process a // bunch of // coinciding // vertices if (result) { // something has changed. // Note that ProcessBunch may // change m_nextVertexToProcess // and m_firstCoincidentVertex. bNeedRepeat = true; if (m_nextVertexToProcess != com.epl.geometry.IndexMultiDCList.NullNode()) { int v = m_sortedVertices.GetData(m_nextVertexToProcess); m_shape.GetXY(v, ptFirst); } } } vlistindex = m_nextVertexToProcess; m_firstCoincidentVertex = vlistindex; coincidentCount = 0; } } else { m_firstCoincidentVertex = vlistindex; m_shape.GetXY(m_sortedVertices.GetData(vlistindex), ptFirst); coincidentCount = 0; } if (vlistindex != -1) { //vlistindex can be set to -1 after ProcessBunch call above vlistindex = m_sortedVertices.GetNext(vlistindex); } } m_nextVertexToProcess = -1; if (coincidentCount > 0) { bool result = _processBunch(); if (result) { bNeedRepeat = true; } } if (iRepeatNum++ > 10) { throw com.epl.geometry.GeometryException.GeometryInternalError(); } if (bNeedRepeat) { _fixOrphanVertices(); } // fix broken structure of the shape if (_cleanupSpikes()) { bNeedRepeat = true; } bNeedWindingRepeat |= bNeedRepeat && bWinding; bChanged |= bNeedRepeat; }while (bNeedRepeat); } // while (bNeedWindingRepeat) // Now process rings. Fix ring orientation and determine rings that need // to be deleted. m_shape.RemoveUserIndex(m_userIndexSortedIndexToVertex); m_shape.RemoveUserIndex(m_userIndexSortedAngleIndexToVertex); bChanged |= com.epl.geometry.RingOrientationFixer.Execute(m_shape, m_geometry, m_sortedVertices, m_fixSelfTangency); return(bChanged); }
private bool _processBunch() { bool bModified = false; int iter = 0; com.epl.geometry.Point2D ptCenter = new com.epl.geometry.Point2D(); while (true) { m_dbgCounter++; // only for debugging iter++; // _ASSERT(iter < 10); if (m_bunchEdgeEndPoints == null) { m_bunchEdgeEndPoints = new com.epl.geometry.AttributeStreamOfInt32(0); m_bunchEdgeCenterPoints = new com.epl.geometry.AttributeStreamOfInt32(0); m_bunchEdgeIndices = new com.epl.geometry.AttributeStreamOfInt32(0); } else { m_bunchEdgeEndPoints.Clear(false); m_bunchEdgeCenterPoints.Clear(false); m_bunchEdgeIndices.Clear(false); } int currentVertex = m_firstCoincidentVertex; int index = 0; bool bFirst = true; while (currentVertex != m_nextVertexToProcess) { int v = m_sortedVertices.GetData(currentVertex); { // debug com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); m_shape.GetXY(v, pt); double y = pt.x; } if (bFirst) { m_shape.GetXY(v, ptCenter); bFirst = false; } int vertP = m_shape.GetPrevVertex(v); int vertN = m_shape.GetNextVertex(v); // _ASSERT(vertP != vertN || m_shape.getPrevVertex(vertN) == v // && m_shape.getNextVertex(vertP) == v); int id = m_shape.GetUserIndex(vertP, m_userIndexSortedAngleIndexToVertex); if (id != unchecked ((int)(0xdeadbeef))) { // avoid adding a point twice // _ASSERT(id == -1); m_bunchEdgeEndPoints.Add(vertP); m_shape.SetUserIndex(vertP, m_userIndexSortedAngleIndexToVertex, unchecked ((int)(0xdeadbeef))); // mark // that // it // has // been // already // added m_bunchEdgeCenterPoints.Add(v); m_bunchEdgeIndices.Add(index++); } int id2 = m_shape.GetUserIndex(vertN, m_userIndexSortedAngleIndexToVertex); if (id2 != unchecked ((int)(0xdeadbeef))) { // avoid adding a point twice // _ASSERT(id2 == -1); m_bunchEdgeEndPoints.Add(vertN); m_shape.SetUserIndex(vertN, m_userIndexSortedAngleIndexToVertex, unchecked ((int)(0xdeadbeef))); // mark // that // it // has // been // already // added m_bunchEdgeCenterPoints.Add(v); m_bunchEdgeIndices.Add(index++); } currentVertex = m_sortedVertices.GetNext(currentVertex); } if (m_bunchEdgeEndPoints.Size() < 2) { break; } // Sort the bunch edpoints by angle (angle between the axis x and // the edge, connecting the endpoint with the bunch center) m_bunchEdgeIndices.Sort(0, m_bunchEdgeIndices.Size(), new com.epl.geometry.Simplificator.SimplificatorAngleComparer(this)); // SORTDYNAMICARRAYEX(m_bunchEdgeIndices, int, 0, // m_bunchEdgeIndices.size(), SimplificatorAngleComparer, this); for (int i = 0, n = m_bunchEdgeIndices.Size(); i < n; i++) { int indexL = m_bunchEdgeIndices.Get(i); int vertex = m_bunchEdgeEndPoints.Get(indexL); m_shape.SetUserIndex(vertex, m_userIndexSortedAngleIndexToVertex, i); { // rember the // sort by angle // order // debug com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); m_shape.GetXY(vertex, pt); double y = pt.x; } } bool bCrossOverResolved = _processCrossOvers(ptCenter); // see of // there // are // crossing // over // edges. for (int i_1 = 0, n = m_bunchEdgeIndices.Size(); i_1 < n; i_1++) { int indexL = m_bunchEdgeIndices.Get(i_1); if (indexL == -1) { continue; } int vertex = m_bunchEdgeEndPoints.Get(indexL); m_shape.SetUserIndex(vertex, m_userIndexSortedAngleIndexToVertex, -1); } // remove // mapping if (bCrossOverResolved) { bModified = true; continue; } break; } return(bModified); }
public override void UserSort(int begin, int end, com.epl.geometry.AttributeStreamOfInt32 indices) { indices.Sort(begin, end, new com.epl.geometry.Boundary.MultiPathImplBoundarySorter.CompareIndices(m_xy)); }
internal static com.epl.geometry.MultiPoint CalculatePolylineBoundary_(object impl, com.epl.geometry.ProgressTracker progress_tracker, bool only_check_non_empty_boundary, bool[] not_empty) { if (not_empty != null) { not_empty[0] = false; } com.epl.geometry.MultiPathImpl mpImpl = (com.epl.geometry.MultiPathImpl)impl; com.epl.geometry.MultiPoint dst = null; if (!only_check_non_empty_boundary) { dst = new com.epl.geometry.MultiPoint(mpImpl.GetDescription()); } if (!mpImpl.IsEmpty()) { com.epl.geometry.AttributeStreamOfInt32 indices = new com.epl.geometry.AttributeStreamOfInt32(0); indices.Reserve(mpImpl.GetPathCount() * 2); for (int ipath = 0, nPathCount = mpImpl.GetPathCount(); ipath < nPathCount; ipath++) { int path_size = mpImpl.GetPathSize(ipath); if (path_size > 0 && !mpImpl.IsClosedPathInXYPlane(ipath)) { // closed // paths // of // polyline // do // not // contribute // to // the // boundary. int start = mpImpl.GetPathStart(ipath); indices.Add(start); int end = mpImpl.GetPathEnd(ipath) - 1; indices.Add(end); } } if (indices.Size() > 0) { com.epl.geometry.BucketSort sorter = new com.epl.geometry.BucketSort(); com.epl.geometry.AttributeStreamOfDbl xy = (com.epl.geometry.AttributeStreamOfDbl)(mpImpl.GetAttributeStreamRef(com.epl.geometry.VertexDescription.Semantics.POSITION)); sorter.Sort(indices, 0, indices.Size(), new com.epl.geometry.Boundary.MultiPathImplBoundarySorter(xy)); com.epl.geometry.Point2D ptPrev = new com.epl.geometry.Point2D(); xy.Read(2 * indices.Get(0), ptPrev); int ind = 0; int counter = 1; com.epl.geometry.Point point = new com.epl.geometry.Point(); com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); for (int i = 1, n = indices.Size(); i < n; i++) { xy.Read(2 * indices.Get(i), pt); if (pt.IsEqual(ptPrev)) { if (indices.Get(ind) > indices.Get(i)) { // remove duplicate point indices.Set(ind, com.epl.geometry.NumberUtils.IntMax()); ind = i; } else { // just for the heck of it, have the first // point in the order to be added to the // boundary. indices.Set(i, com.epl.geometry.NumberUtils.IntMax()); } counter++; } else { if ((counter & 1) == 0) { // remove boundary point indices.Set(ind, com.epl.geometry.NumberUtils.IntMax()); } else { if (only_check_non_empty_boundary) { if (not_empty != null) { not_empty[0] = true; } return(null); } } ptPrev.SetCoords(pt); ind = i; counter = 1; } } if ((counter & 1) == 0) { // remove the point indices.Set(ind, com.epl.geometry.NumberUtils.IntMax()); } else { if (only_check_non_empty_boundary) { if (not_empty != null) { not_empty[0] = true; } return(null); } } if (!only_check_non_empty_boundary) { indices.Sort(0, indices.Size()); for (int i_1 = 0, n = indices.Size(); i_1 < n; i_1++) { if (indices.Get(i_1) == com.epl.geometry.NumberUtils.IntMax()) { break; } mpImpl.GetPointByVal(indices.Get(i_1), point); dst.Add(point); } } } } if (only_check_non_empty_boundary) { return(null); } return(dst); }
private void SortYEndIndicesHelper_(com.epl.geometry.AttributeStreamOfInt32 end_indices, int begin_, int end_, bool b_red) { end_indices.Sort(begin_, end_, new com.epl.geometry.Envelope2DIntersectorImpl.EndPointsComparer(this, b_red)); }