internal static bool CanBeCracked(com.epl.geometry.EditShape shape) { for (int geometry = shape.GetFirstGeometry(); geometry != -1; geometry = shape.GetNextGeometry(geometry)) { if (!com.epl.geometry.Geometry.IsMultiPath(shape.GetGeometryType(geometry))) { continue; } return(true); } return(false); }
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 CrackBruteForce_() { com.epl.geometry.EditShape.VertexIterator iter_1 = m_shape.QueryVertexIterator(false); bool b_cracked = false; com.epl.geometry.Line line_1 = new com.epl.geometry.Line(); com.epl.geometry.Line line_2 = new com.epl.geometry.Line(); com.epl.geometry.Envelope2D seg_1_env = new com.epl.geometry.Envelope2D(); seg_1_env.SetEmpty(); com.epl.geometry.Envelope2D seg_2_env = new com.epl.geometry.Envelope2D(); seg_2_env.SetEmpty(); bool assume_intersecting = false; com.epl.geometry.Point helper_point = new com.epl.geometry.Point(); com.epl.geometry.SegmentIntersector segment_intersector = new com.epl.geometry.SegmentIntersector(); for (int vertex_1 = iter_1.Next(); vertex_1 != -1; vertex_1 = iter_1.Next()) { com.epl.geometry.ProgressTracker.CheckAndThrow(m_progress_tracker); int GT_1 = m_shape.GetGeometryType(iter_1.CurrentGeometry()); com.epl.geometry.Segment seg_1 = null; bool seg_1_zero = false; if (!com.epl.geometry.Geometry.IsPoint(GT_1)) { seg_1 = GetSegment_(vertex_1, line_1); if (seg_1 == null) { continue; } seg_1.QueryEnvelope2D(seg_1_env); seg_1_env.Inflate(m_tolerance, m_tolerance); if (seg_1.IsDegenerate(m_tolerance)) { // do not crack with // degenerate segments if (seg_1.IsDegenerate(0)) { seg_1_zero = true; seg_1 = null; } else { continue; } } } com.epl.geometry.EditShape.VertexIterator iter_2 = m_shape.QueryVertexIterator(iter_1); int vertex_2 = iter_2.Next(); if (vertex_2 != -1) { vertex_2 = iter_2.Next(); } for (; vertex_2 != -1; vertex_2 = iter_2.Next()) { int GT_2 = m_shape.GetGeometryType(iter_2.CurrentGeometry()); com.epl.geometry.Segment seg_2 = null; bool seg_2_zero = false; if (!com.epl.geometry.Geometry.IsPoint(GT_2)) { seg_2 = GetSegment_(vertex_2, line_2); if (seg_2 == null) { continue; } seg_2.QueryEnvelope2D(seg_2_env); if (seg_2.IsDegenerate(m_tolerance)) { // do not crack with // degenerate segments if (seg_2.IsDegenerate(0)) { seg_2_zero = true; seg_2 = null; } else { continue; } } } int split_count_1 = 0; int split_count_2 = 0; if (seg_1 != null && seg_2 != null) { if (seg_1_env.IsIntersectingNE(seg_2_env)) { segment_intersector.PushSegment(seg_1); segment_intersector.PushSegment(seg_2); segment_intersector.Intersect(m_tolerance, assume_intersecting); split_count_1 = segment_intersector.GetResultSegmentCount(0); split_count_2 = segment_intersector.GetResultSegmentCount(1); if (split_count_1 + split_count_2 > 0) { m_shape.SplitSegment_(vertex_1, segment_intersector, 0, true); m_shape.SplitSegment_(vertex_2, segment_intersector, 1, true); } segment_intersector.Clear(); } } else { if (seg_1 != null) { com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); m_shape.GetXY(vertex_2, pt); if (seg_1_env.Contains(pt)) { segment_intersector.PushSegment(seg_1); m_shape.QueryPoint(vertex_2, helper_point); segment_intersector.Intersect(m_tolerance, helper_point, 0, 1.0, assume_intersecting); split_count_1 = segment_intersector.GetResultSegmentCount(0); if (split_count_1 > 0) { m_shape.SplitSegment_(vertex_1, segment_intersector, 0, true); if (seg_2_zero) { //seg_2 was zero length. Need to change all coincident points //segment at vertex_2 is dzero length, change all attached zero length segments int v_to = -1; for (int v = m_shape.GetNextVertex(vertex_2); v != -1 && v != vertex_2; v = m_shape.GetNextVertex(v)) { seg_2 = GetSegment_(v, line_2); v_to = v; if (seg_2 == null || !seg_2.IsDegenerate(0)) { break; } } //change from vertex_2 to v_to (inclusive). for (int v_1 = vertex_2; v_1 != -1; v_1 = m_shape.GetNextVertex(v_1)) { m_shape.SetPoint(v_1, segment_intersector.GetResultPoint()); if (v_1 == v_to) { break; } } } else { m_shape.SetPoint(vertex_2, segment_intersector.GetResultPoint()); } } segment_intersector.Clear(); } } else { if (seg_2 != null) { com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); m_shape.GetXY(vertex_1, pt); seg_2_env.Inflate(m_tolerance, m_tolerance); if (seg_2_env.Contains(pt)) { segment_intersector.PushSegment(seg_2); m_shape.QueryPoint(vertex_1, helper_point); segment_intersector.Intersect(m_tolerance, helper_point, 0, 1.0, assume_intersecting); split_count_2 = segment_intersector.GetResultSegmentCount(0); if (split_count_2 > 0) { m_shape.SplitSegment_(vertex_2, segment_intersector, 0, true); if (seg_1_zero) { //seg_1 was zero length. Need to change all coincident points //segment at vertex_2 is dzero length, change all attached zero length segments int v_to = -1; for (int v = m_shape.GetNextVertex(vertex_1); v != -1 && v != vertex_1; v = m_shape.GetNextVertex(v)) { seg_2 = GetSegment_(v, line_2); //using here seg_2 for seg_1 v_to = v; if (seg_2 == null || !seg_2.IsDegenerate(0)) { break; } } //change from vertex_2 to v_to (inclusive). for (int v_1 = vertex_1; v_1 != -1; v_1 = m_shape.GetNextVertex(v_1)) { m_shape.SetPoint(v_1, segment_intersector.GetResultPoint()); if (v_1 == v_to) { break; } } } else { m_shape.SetPoint(vertex_1, segment_intersector.GetResultPoint()); } } segment_intersector.Clear(); } } else { continue; } } } // points on points if (split_count_1 + split_count_2 != 0) { if (split_count_1 != 0) { seg_1 = m_shape.GetSegment(vertex_1); // reload segment // after split if (seg_1 == null) { if (!m_shape.QueryLineConnector(vertex_1, line_1)) { continue; } seg_1 = line_1; line_1.QueryEnvelope2D(seg_1_env); } else { seg_1.QueryEnvelope2D(seg_1_env); } if (seg_1.IsDegenerate(m_tolerance)) { // do not crack with // degenerate // segments break; } } b_cracked = true; } } } return(b_cracked); }