private void Next_(int action) { switch (m_functionStack.GetLast()) { case com.epl.geometry.JsonWriter.State.accept: { Accept_(action); break; } case com.epl.geometry.JsonWriter.State.start: { Start_(action); break; } case com.epl.geometry.JsonWriter.State.objectStart: { ObjectStart_(action); break; } case com.epl.geometry.JsonWriter.State.arrayStart: { ArrayStart_(action); break; } case com.epl.geometry.JsonWriter.State.pairEnd: { PairEnd_(action); break; } case com.epl.geometry.JsonWriter.State.elementEnd: { ElementEnd_(action); break; } case com.epl.geometry.JsonWriter.State.fieldNameEnd: { FieldNameEnd_(action); break; } default: { throw new com.epl.geometry.GeometryException("internal error"); } } }
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(); } } } }
internal virtual bool FixRingSelfTangency_() { com.epl.geometry.AttributeStreamOfInt32 self_tangent_paths = new com.epl.geometry.AttributeStreamOfInt32(0); com.epl.geometry.AttributeStreamOfInt32 self_tangency_clusters = new com.epl.geometry.AttributeStreamOfInt32(0); int tangent_path_first_vertex_index = -1; int tangent_vertex_cluster_index = -1; com.epl.geometry.Point2D pt_prev = new com.epl.geometry.Point2D(); pt_prev.SetNaN(); int prev_vertex = -1; int old_path = -1; int current_cluster = -1; com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D(); for (int ivertex = m_sorted_vertices.GetFirst(m_sorted_vertices.GetFirstList()); ivertex != -1; ivertex = m_sorted_vertices.GetNext(ivertex)) { int vertex = m_sorted_vertices.GetData(ivertex); m_shape.GetXY(vertex, pt); int path = m_shape.GetPathFromVertex(vertex); if (pt_prev.IsEqual(pt) && old_path == path) { if (tangent_vertex_cluster_index == -1) { tangent_path_first_vertex_index = m_shape.CreatePathUserIndex(); tangent_vertex_cluster_index = m_shape.CreateUserIndex(); } if (current_cluster == -1) { current_cluster = self_tangency_clusters.Size(); m_shape.SetUserIndex(prev_vertex, tangent_vertex_cluster_index, current_cluster); self_tangency_clusters.Add(1); int p = m_shape.GetPathUserIndex(path, tangent_path_first_vertex_index); if (p == -1) { m_shape.SetPathUserIndex(path, tangent_path_first_vertex_index, prev_vertex); self_tangent_paths.Add(path); } } m_shape.SetUserIndex(vertex, tangent_vertex_cluster_index, current_cluster); self_tangency_clusters.SetLast(self_tangency_clusters.GetLast() + 1); } else { current_cluster = -1; pt_prev.SetCoords(pt); } prev_vertex = vertex; old_path = path; } if (self_tangent_paths.Size() == 0) { return(false); } // Now self_tangent_paths contains list of clusters of tangency for each // path. // The clusters contains list of clusters and for each cluster it // contains a list of vertices. com.epl.geometry.AttributeStreamOfInt32 vertex_stack = new com.epl.geometry.AttributeStreamOfInt32(0); com.epl.geometry.AttributeStreamOfInt32 cluster_stack = new com.epl.geometry.AttributeStreamOfInt32(0); for (int ipath = 0, npath = self_tangent_paths.Size(); ipath < npath; ipath++) { int path = self_tangent_paths.Get(ipath); int first_vertex = m_shape.GetPathUserIndex(path, tangent_path_first_vertex_index); int cluster = m_shape.GetUserIndex(first_vertex, tangent_vertex_cluster_index); vertex_stack.Clear(false); cluster_stack.Clear(false); vertex_stack.Add(first_vertex); cluster_stack.Add(cluster); for (int vertex = m_shape.GetNextVertex(first_vertex); vertex != first_vertex; vertex = m_shape.GetNextVertex(vertex)) { int vertex_to = vertex; int cluster_to = m_shape.GetUserIndex(vertex_to, tangent_vertex_cluster_index); if (cluster_to != -1) { if (cluster_stack.Size() == 0) { cluster_stack.Add(cluster_to); vertex_stack.Add(vertex_to); continue; } if (cluster_stack.GetLast() == cluster_to) { int vertex_from = vertex_stack.GetLast(); // peel the loop from path int from_next = m_shape.GetNextVertex(vertex_from); int from_prev = m_shape.GetPrevVertex(vertex_from); int to_next = m_shape.GetNextVertex(vertex_to); int to_prev = m_shape.GetPrevVertex(vertex_to); m_shape.SetNextVertex_(vertex_from, to_next); m_shape.SetPrevVertex_(to_next, vertex_from); m_shape.SetNextVertex_(vertex_to, from_next); m_shape.SetPrevVertex_(from_next, vertex_to); // vertex_from is left in the path we are processing, // while the vertex_to is in the loop being teared off. bool[] first_vertex_correction_requied = new bool[] { false }; int new_path = m_shape.InsertClosedPath_(m_geometry, -1, from_next, m_shape.GetFirstVertex(path), first_vertex_correction_requied); m_shape.SetUserIndex(vertex, tangent_vertex_cluster_index, -1); // Fix the path after peeling if the peeled loop had the // first path vertex in it if (first_vertex_correction_requied[0]) { m_shape.SetFirstVertex_(path, to_next); } int path_size = m_shape.GetPathSize(path); int new_path_size = m_shape.GetPathSize(new_path); path_size -= new_path_size; System.Diagnostics.Debug.Assert((path_size >= 3)); m_shape.SetPathSize_(path, path_size); self_tangency_clusters.Set(cluster_to, self_tangency_clusters.Get(cluster_to) - 1); if (self_tangency_clusters.Get(cluster_to) == 1) { self_tangency_clusters.Set(cluster_to, 0); cluster_stack.RemoveLast(); vertex_stack.RemoveLast(); } // this cluster has more than two vertices in it. first_vertex = vertex_from; // reset the counter to // ensure we find all loops. vertex = vertex_from; } else { vertex_stack.Add(vertex); cluster_stack.Add(cluster_to); } } } } m_shape.RemovePathUserIndex(tangent_path_first_vertex_index); m_shape.RemoveUserIndex(tangent_vertex_cluster_index); return(true); }