Ejemplo n.º 1
0
        internal bool ClusterNonReciprocal_()
        {
            int point_count = m_shape.GetTotalPointCount();

            com.epl.geometry.Envelope2D env = m_shape.GetEnvelope2D();
            m_origin = env.GetLowerLeft();
            double dim     = System.Math.Max(env.GetHeight(), env.GetWidth());
            double mincell = dim / (com.epl.geometry.NumberUtils.IntMax() - 1);

            if (m_cell_size < mincell)
            {
                m_cell_size     = mincell;
                m_inv_cell_size = 1.0 / m_cell_size;
            }
            // This holds clusters.
            m_clusters = new com.epl.geometry.IndexMultiList();
            m_clusters.ReserveLists(m_shape.GetTotalPointCount() / 3 + 1);
            m_clusters.ReserveNodes(m_shape.GetTotalPointCount() / 3 + 1);
            m_hash_values  = m_shape.CreateUserIndex();
            m_new_clusters = m_shape.CreateUserIndex();
            // Make the hash table. It serves a purpose of fine grain grid.
            // Make it 25% larger than the 4 times point count to reduce the chance
            // of collision.
            // The 4 times comes from the fact that we check four neighbouring cells
            // in the grid for each point.
            m_hash_function = new com.epl.geometry.Clusterer.ClusterHashFunction(this, m_shape, m_origin, m_sqr_tolerance, m_inv_cell_size, m_hash_values);
            m_hash_table    = new com.epl.geometry.IndexHashTable(4 * point_count / 3, m_hash_function);
            m_hash_table.ReserveElements(m_shape.GetTotalPointCount());
            bool b_clustered = false;

            // Go through all vertices stored in the m_shape and put the handles of
            // the vertices into the clusters and the hash table.
            for (int geometry = m_shape.GetFirstGeometry(); geometry != -1; geometry = m_shape.GetNextGeometry(geometry))
            {
                for (int path = m_shape.GetFirstPath(geometry); path != -1; path = m_shape.GetNextPath(path))
                {
                    int vertex = m_shape.GetFirstVertex(path);
                    for (int index = 0, nindex = m_shape.GetPathSize(path); index < nindex; index++)
                    {
                        System.Diagnostics.Debug.Assert((vertex != -1));
                        int hash = m_hash_function.Calculate_hash_from_vertex(vertex);
                        m_shape.SetUserIndex(vertex, m_hash_values, hash);
                        m_hash_table.AddElement(vertex, hash);
                        // add cluster to the
                        // hash table
                        System.Diagnostics.Debug.Assert((m_shape.GetUserIndex(vertex, m_new_clusters) == -1));
                        vertex = m_shape.GetNextVertex(vertex);
                    }
                }
            }
            {
                // m_hash_table->dbg_print_bucket_histogram_();
                // scope for candidates array
                com.epl.geometry.AttributeStreamOfInt32 candidates = new com.epl.geometry.AttributeStreamOfInt32(0);
                candidates.Reserve(10);
                for (int geometry_1 = m_shape.GetFirstGeometry(); geometry_1 != -1; geometry_1 = m_shape.GetNextGeometry(geometry_1))
                {
                    for (int path = m_shape.GetFirstPath(geometry_1); path != -1; path = m_shape.GetNextPath(path))
                    {
                        int vertex = m_shape.GetFirstVertex(path);
                        for (int index = 0, nindex = m_shape.GetPathSize(path); index < nindex; index++)
                        {
                            if (m_shape.GetUserIndex(vertex, m_new_clusters) == com.epl.geometry.StridedIndexTypeCollection.ImpossibleIndex2())
                            {
                                vertex = m_shape.GetNextVertex(vertex);
                                continue;
                            }
                            // this vertex was merged with another
                            // cluster. It also was removed from the
                            // hash table.
                            int hash = m_shape.GetUserIndex(vertex, m_hash_values);
                            m_hash_table.DeleteElement(vertex, hash);
                            while (true)
                            {
                                CollectClusterCandidates_(vertex, candidates);
                                if (candidates.Size() == 0)
                                {
                                    // no candidate for
                                    // clustering has
                                    // been found for
                                    // the cluster_1.
                                    break;
                                }
                                bool clustered = false;
                                for (int candidate_index = 0, ncandidates = candidates.Size(); candidate_index < ncandidates; candidate_index++)
                                {
                                    int cluster_node = candidates.Get(candidate_index);
                                    int other_vertex = m_hash_table.GetElement(cluster_node);
                                    m_hash_table.DeleteNode(cluster_node);
                                    clustered |= MergeClusters_(vertex, other_vertex, candidate_index + 1 == ncandidates);
                                }
                                b_clustered |= clustered;
                                candidates.Clear(false);
                                // repeat search for the cluster candidates for
                                // cluster_1
                                if (!clustered)
                                {
                                    break;
                                }
                            }
                            // positions did not change
                            // m_shape->set_user_index(vertex, m_new_clusters,
                            // Strided_index_type_collection::impossible_index_2());
                            vertex = m_shape.GetNextVertex(vertex);
                        }
                    }
                }
            }
            if (b_clustered)
            {
                ApplyClusterPositions_();
            }
            m_hash_table    = null;
            m_hash_function = null;
            m_shape.RemoveUserIndex(m_hash_values);
            m_shape.RemoveUserIndex(m_new_clusters);
            // output_debug_printf("total: %d\n",m_shape->get_total_point_count());
            // output_debug_printf("clustered: %d\n",m_dbg_candidate_check_count);
            return(b_clustered);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        internal bool NeedsCrackingImpl_()
        {
            bool b_needs_cracking = false;

            if (m_sweep_structure == null)
            {
                m_sweep_structure = new com.epl.geometry.Treap();
            }
            com.epl.geometry.AttributeStreamOfInt32 event_q = new com.epl.geometry.AttributeStreamOfInt32(0);
            event_q.Reserve(m_shape.GetTotalPointCount() + 1);
            com.epl.geometry.EditShape.VertexIterator iter = m_shape.QueryVertexIterator();
            for (int vert = iter.Next(); vert != -1; vert = iter.Next())
            {
                event_q.Add(vert);
            }
            System.Diagnostics.Debug.Assert((m_shape.GetTotalPointCount() == event_q.Size()));
            m_shape.SortVerticesSimpleByY_(event_q, 0, event_q.Size());
            event_q.Add(-1);
            // for termination;
            // create user indices to store edges that end at vertices.
            int edge_index_1 = m_shape.CreateUserIndex();
            int edge_index_2 = m_shape.CreateUserIndex();

            m_sweep_comparator = new com.epl.geometry.SweepComparator(m_shape, m_tolerance, !m_bAllowCoincident);
            m_sweep_structure.SetComparator(m_sweep_comparator);
            com.epl.geometry.AttributeStreamOfInt32 swept_edges_to_delete = new com.epl.geometry.AttributeStreamOfInt32(0);
            com.epl.geometry.AttributeStreamOfInt32 edges_to_insert       = new com.epl.geometry.AttributeStreamOfInt32(0);
            // Go throught the sorted vertices
            int event_q_index = 0;

            com.epl.geometry.Point2D cluster_pt = new com.epl.geometry.Point2D();
            // sweep-line algorithm:
            for (int vertex = event_q.Get(event_q_index++); vertex != -1;)
            {
                m_shape.GetXY(vertex, cluster_pt);
                do
                {
                    int next_vertex = m_shape.GetNextVertex(vertex);
                    int prev_vertex = m_shape.GetPrevVertex(vertex);
                    if (next_vertex != -1 && m_shape.CompareVerticesSimpleY_(vertex, next_vertex) < 0)
                    {
                        edges_to_insert.Add(vertex);
                        edges_to_insert.Add(next_vertex);
                    }
                    if (prev_vertex != -1 && m_shape.CompareVerticesSimpleY_(vertex, prev_vertex) < 0)
                    {
                        edges_to_insert.Add(prev_vertex);
                        edges_to_insert.Add(prev_vertex);
                    }
                    // Continue accumulating current cluster
                    int attached_edge_1 = m_shape.GetUserIndex(vertex, edge_index_1);
                    if (attached_edge_1 != -1)
                    {
                        swept_edges_to_delete.Add(attached_edge_1);
                        m_shape.SetUserIndex(vertex, edge_index_1, -1);
                    }
                    int attached_edge_2 = m_shape.GetUserIndex(vertex, edge_index_2);
                    if (attached_edge_2 != -1)
                    {
                        swept_edges_to_delete.Add(attached_edge_2);
                        m_shape.SetUserIndex(vertex, edge_index_2, -1);
                    }
                    vertex = event_q.Get(event_q_index++);
                }while (vertex != -1 && m_shape.IsEqualXY(vertex, cluster_pt));
                bool b_continuing_segment_chain_optimization = swept_edges_to_delete.Size() == 1 && edges_to_insert.Size() == 2;
                int  new_left  = -1;
                int  new_right = -1;
                // Process the cluster
                for (int i = 0, n = swept_edges_to_delete.Size(); i < n; i++)
                {
                    // Find left and right neighbour of the edges that terminate at
                    // the cluster (there will be atmost only one left and one
                    // right).
                    int edge = swept_edges_to_delete.Get(i);
                    int left = m_sweep_structure.GetPrev(edge);
                    if (left != -1 && !swept_edges_to_delete.HasElement(left))
                    {
                        // Note:
                        // for
                        // some
                        // heavy
                        // cases,
                        // it
                        // could
                        // be
                        // better
                        // to
                        // use
                        // binary
                        // search.
                        System.Diagnostics.Debug.Assert((new_left == -1));
                        new_left = left;
                    }
                    int right = m_sweep_structure.GetNext(edge);
                    if (right != -1 && !swept_edges_to_delete.HasElement(right))
                    {
                        System.Diagnostics.Debug.Assert((new_right == -1));
                        new_right = right;
                    }
                    //#ifdef NDEBUG
                    if (new_left != -1 && new_right != -1)
                    {
                        break;
                    }
                }
                //#endif
                System.Diagnostics.Debug.Assert((new_left == -1 || new_left != new_right));
                m_sweep_comparator.SetSweepY(cluster_pt.y, cluster_pt.x);
                // Delete the edges that terminate at the cluster.
                for (int i_1 = 0, n = swept_edges_to_delete.Size(); i_1 < n; i_1++)
                {
                    int edge = swept_edges_to_delete.Get(i_1);
                    m_sweep_structure.DeleteNode(edge, -1);
                }
                swept_edges_to_delete.Clear(false);
                if (!b_continuing_segment_chain_optimization && new_left != -1 && new_right != -1)
                {
                    if (CheckForIntersections_(new_left, new_right))
                    {
                        b_needs_cracking    = true;
                        m_non_simple_result = m_sweep_comparator.GetResult();
                        break;
                    }
                }
                for (int i_2 = 0, n = edges_to_insert.Size(); i_2 < n; i_2 += 2)
                {
                    int v          = edges_to_insert.Get(i_2);
                    int otherv     = edges_to_insert.Get(i_2 + 1);
                    int new_edge_1 = -1;
                    if (b_continuing_segment_chain_optimization)
                    {
                        new_edge_1 = m_sweep_structure.AddElementAtPosition(new_left, new_right, v, true, true, -1);
                        b_continuing_segment_chain_optimization = false;
                    }
                    else
                    {
                        new_edge_1 = m_sweep_structure.AddElement(v, -1);
                    }
                    // the
                    // sweep
                    // structure
                    // consist
                    // of
                    // the
                    // origin
                    // vertices
                    // for
                    // edges.
                    // One
                    // can
                    // always
                    // get
                    // the
                    // other
                    // endpoint
                    // as
                    // the
                    // next
                    // vertex.
                    if (m_sweep_comparator.IntersectionDetected())
                    {
                        m_non_simple_result = m_sweep_comparator.GetResult();
                        b_needs_cracking    = true;
                        break;
                    }
                    int e_1 = m_shape.GetUserIndex(otherv, edge_index_1);
                    if (e_1 == -1)
                    {
                        m_shape.SetUserIndex(otherv, edge_index_1, new_edge_1);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert((m_shape.GetUserIndex(otherv, edge_index_2) == -1));
                        m_shape.SetUserIndex(otherv, edge_index_2, new_edge_1);
                    }
                }
                if (b_needs_cracking)
                {
                    break;
                }
                // Start accumulating new cluster
                edges_to_insert.ResizePreserveCapacity(0);
            }
            m_shape.RemoveUserIndex(edge_index_1);
            m_shape.RemoveUserIndex(edge_index_2);
            return(b_needs_cracking);
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        internal virtual bool ProcessBunchForRingOrientationTestOddEven_(com.epl.geometry.AttributeStreamOfInt32 bunch)
        {
            bool bModified = false;

            if (m_edges == null)
            {
                m_edges = new com.epl.geometry.RingOrientationFixer.Edges(m_shape);
            }
            if (m_unknown_nodes == null)
            {
                m_unknown_nodes = new com.epl.geometry.AttributeStreamOfInt32(0);
                m_unknown_nodes.Reserve(16);
            }
            else
            {
                m_unknown_nodes.Clear(false);
            }
            ProcessBunchForRingOrientationRemoveEdges_(bunch);
            // add edges that come into scope
            for (int i = 0, n = bunch.Size(); i < n; i++)
            {
                int vertex = bunch.Get(i);
                if (vertex == -1)
                {
                    continue;
                }
                InsertEdge_(vertex, -1);
            }
            for (int i_1 = 0; i_1 < m_unknown_nodes.Size() && m_unknown_ring_orientation_count > 0; i_1++)
            {
                int aetNode     = m_unknown_nodes.Get(i_1);
                int edge        = m_AET.GetElement(aetNode);
                int path        = m_edges.GetPath(edge);
                int orientation = m_shape.GetPathUserIndex(path, m_path_orientation_index);
                int prevPath    = -1;
                if (orientation == 0)
                {
                    int  node     = m_AET.GetPrev(aetNode);
                    int  prevNode = aetNode;
                    bool odd_even = false;
                    // find the leftmost edge for which the ring orientation is
                    // known
                    while (node != com.epl.geometry.Treap.NullNode())
                    {
                        int edge1        = m_AET.GetElement(node);
                        int path1        = m_edges.GetPath(edge1);
                        int orientation1 = m_shape.GetPathUserIndex(path1, m_path_orientation_index);
                        if (orientation1 != 0)
                        {
                            prevPath = path1;
                            break;
                        }
                        prevNode = node;
                        node     = m_AET.GetPrev(node);
                    }
                    if (node == com.epl.geometry.Treap.NullNode())
                    {
                        // if no edges have ring
                        // orientation known, then start
                        // from the left most and it has
                        // to be exterior ring.
                        odd_even = true;
                        node     = prevNode;
                    }
                    else
                    {
                        int edge1 = m_AET.GetElement(node);
                        odd_even = m_edges.IsBottomUp(edge1);
                        node     = m_AET.GetNext(node);
                        odd_even = !odd_even;
                    }
                    do
                    {
                        int edge1        = m_AET.GetElement(node);
                        int path1        = m_edges.GetPath(edge1);
                        int orientation1 = m_shape.GetPathUserIndex(path1, m_path_orientation_index);
                        if (orientation1 == 0)
                        {
                            if (odd_even != m_edges.IsBottomUp(edge1))
                            {
                                int first = m_shape.GetFirstVertex(path1);
                                m_shape.ReverseRingInternal_(first);
                                m_shape.SetLastVertex_(path1, m_shape.GetPrevVertex(first));
                                bModified = true;
                            }
                            m_shape.SetPathUserIndex(path1, m_path_orientation_index, odd_even ? 3 : 2);
                            if (!odd_even)
                            {
                                // link the holes into the linked list
                                // to mantain the OGC order.
                                int lastHole = m_shape.GetPathUserIndex(prevPath, m_path_parentage_index);
                                m_shape.SetPathUserIndex(prevPath, m_path_parentage_index, path1);
                                m_shape.SetPathUserIndex(path1, m_path_parentage_index, lastHole);
                            }
                            m_unknown_ring_orientation_count--;
                            if (m_unknown_ring_orientation_count == 0)
                            {
                                return(bModified);
                            }
                        }
                        prevPath = path1;
                        prevNode = node;
                        node     = m_AET.GetNext(node);
                        odd_even = !odd_even;
                    }while (prevNode != aetNode);
                }
            }
            return(bModified);
        }
Ejemplo n.º 6
0
        internal virtual bool FixRingOrientation_()
        {
            bool bFound = false;

            if (m_fixSelfTangency)
            {
                bFound = FixRingSelfTangency_();
            }
            if (m_shape.GetPathCount(m_geometry) == 1)
            {
                int    path = m_shape.GetFirstPath(m_geometry);
                double area = m_shape.GetRingArea(path);
                m_shape.SetExterior(path, true);
                if (area < 0)
                {
                    int first = m_shape.GetFirstVertex(path);
                    m_shape.ReverseRingInternal_(first);
                    m_shape.SetLastVertex_(path, m_shape.GetPrevVertex(first));
                    // fix
                    // last
                    // after
                    // the
                    // reverse
                    return(true);
                }
                return(false);
            }
            m_path_orientation_index = m_shape.CreatePathUserIndex();
            // used to
            // store
            // discovered
            // orientation
            // (3 -
            // extrior,
            // 2 -
            // interior)
            m_path_parentage_index = m_shape.CreatePathUserIndex();
            // used to
            // resolve OGC
            // order
            for (int path_1 = m_shape.GetFirstPath(m_geometry); path_1 != -1; path_1 = m_shape.GetNextPath(path_1))
            {
                m_shape.SetPathUserIndex(path_1, m_path_orientation_index, 0);
                m_shape.SetPathUserIndex(path_1, m_path_parentage_index, -1);
            }
            com.epl.geometry.AttributeStreamOfInt32 bunch = new com.epl.geometry.AttributeStreamOfInt32(0);
            m_y_scanline = com.epl.geometry.NumberUtils.TheNaN;
            com.epl.geometry.Point2D pt = new com.epl.geometry.Point2D();
            m_unknown_ring_orientation_count = m_shape.GetPathCount(m_geometry);
            m_node_1_user_index = m_shape.CreateUserIndex();
            m_node_2_user_index = m_shape.CreateUserIndex();
            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);
                if (pt.y != m_y_scanline && bunch.Size() != 0)
                {
                    bFound |= ProcessBunchForRingOrientationTest_(bunch);
                    m_sweep_comparator.Reset();
                    bunch.Clear(false);
                }
                bunch.Add(vertex);
                // all vertices that have same y are added to the
                // bunch
                m_y_scanline = pt.y;
                if (m_unknown_ring_orientation_count == 0)
                {
                    break;
                }
            }
            if (m_unknown_ring_orientation_count > 0)
            {
                bFound |= ProcessBunchForRingOrientationTest_(bunch);
                bunch.Clear(false);
            }
            m_shape.RemoveUserIndex(m_node_1_user_index);
            m_shape.RemoveUserIndex(m_node_2_user_index);
            // dbg_verify_ring_orientation_();//debug
            for (int path_2 = m_shape.GetFirstPath(m_geometry); path_2 != -1;)
            {
                if (m_shape.GetPathUserIndex(path_2, m_path_orientation_index) == 3)
                {
                    // exterior
                    m_shape.SetExterior(path_2, true);
                    int afterPath = path_2;
                    for (int nextHole = m_shape.GetPathUserIndex(path_2, m_path_parentage_index); nextHole != -1;)
                    {
                        int p = m_shape.GetPathUserIndex(nextHole, m_path_parentage_index);
                        m_shape.MovePath(m_geometry, m_shape.GetNextPath(afterPath), nextHole);
                        afterPath = nextHole;
                        nextHole  = p;
                    }
                    path_2 = m_shape.GetNextPath(afterPath);
                }
                else
                {
                    m_shape.SetExterior(path_2, false);
                    path_2 = m_shape.GetNextPath(path_2);
                }
            }
            m_shape.RemovePathUserIndex(m_path_orientation_index);
            m_shape.RemovePathUserIndex(m_path_parentage_index);
            return(bFound);
        }