Beispiel #1
0
 internal static bool Execute(com.epl.geometry.EditShape shape, int geometry, com.epl.geometry.IndexMultiDCList sorted_vertices, bool fixSelfTangency)
 {
     com.epl.geometry.RingOrientationFixer fixer = new com.epl.geometry.RingOrientationFixer();
     fixer.m_shape           = shape;
     fixer.m_geometry        = geometry;
     fixer.m_sorted_vertices = sorted_vertices;
     fixer.m_fixSelfTangency = fixSelfTangency;
     return(fixer.FixRingOrientation_());
 }
Beispiel #2
0
        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 SweepBlue_()
        {
            int y_end_point_handle_blue = m_sorted_end_indices_blue.Get(--m_sweep_index_blue);
            int envelope_handle_blue    = y_end_point_handle_blue >> 1;

            if (IsBottom_(y_end_point_handle_blue))
            {
                if (m_queued_list_blue != -1 && m_queued_indices_blue.Get(envelope_handle_blue) != -1)
                {
                    m_queued_envelopes.DeleteElement(m_queued_list_blue, m_queued_indices_blue.Get(envelope_handle_blue));
                    m_queued_indices_blue.Set(envelope_handle_blue, -1);
                }
                else
                {
                    m_interval_tree_blue.Remove(envelope_handle_blue);
                }
                if (m_sweep_index_blue == 0)
                {
                    m_envelope_handle_a = -1;
                    m_envelope_handle_b = -1;
                    m_b_done            = true;
                    return(false);
                }
                return(true);
            }
            if (m_queued_list_red != -1 && m_queued_envelopes.GetListSize(m_queued_list_red) > 0)
            {
                int node = m_queued_envelopes.GetFirst(m_queued_list_red);
                while (node != -1)
                {
                    int e = m_queued_envelopes.GetData(node);
                    m_interval_tree_red.Insert(e);
                    m_queued_indices_red.Set(e, -1);
                    int next_node = m_queued_envelopes.GetNext(node);
                    m_queued_envelopes.DeleteElement(m_queued_list_red, node);
                    node = next_node;
                }
            }
            if (m_interval_tree_red.Size() > 0)
            {
                m_iterator_red.ResetIterator(m_envelopes_blue[envelope_handle_blue].xmin, m_envelopes_blue[envelope_handle_blue].xmax, m_tolerance);
                m_envelope_handle_b = envelope_handle_blue;
                m_function          = com.epl.geometry.Envelope2DIntersectorImpl.State.iterateRed;
            }
            else
            {
                if (m_queued_list_blue == -1)
                {
                    if (m_queued_envelopes == null)
                    {
                        m_queued_envelopes = new com.epl.geometry.IndexMultiDCList();
                    }
                    m_queued_indices_blue = new com.epl.geometry.AttributeStreamOfInt32(0);
                    m_queued_indices_blue.Resize(m_envelopes_blue.Count, -1);
                    m_queued_indices_blue.SetRange(-1, 0, m_envelopes_blue.Count);
                    m_queued_list_blue = m_queued_envelopes.CreateList(0);
                }
                m_queued_indices_blue.Set(envelope_handle_blue, m_queued_envelopes.AddElement(m_queued_list_blue, envelope_handle_blue));
                m_function = com.epl.geometry.Envelope2DIntersectorImpl.State.sweepRedBlue;
            }
            return(true);
        }