Пример #1
0
        /// <summary>
        /// Adds a spatial object into the index
        /// </summary>
        /// <param name="o">The object to add to the index</param>
        public void Add(ISpatialObject o)
        {
            // Points are handled using their own index. Unfortunately, they
            // must implement IPoint in order for it to work (something
            // that should really be reflected in the parameter list).

            // Could cover this by using the fact that an ISpatialObject that is
            // a point must be able to return an IWindow (from which we can
            // pull out the point position). Just a bit more convoluted.

            if (o is IPoint)
            {
                m_Points.Add(o as IPoint);
                return;
            }

            Item        item = new Item(o);
            SpatialType t    = o.SpatialType;

            if (t == SpatialType.Line)
            {
                m_Lines.AddItem(item);
            }
            else if (t == SpatialType.Text)
            {
                m_Text.AddItem(item);
            }
            else if (t == SpatialType.Polygon)
            {
                m_Polygons.AddItem(item);
            }
            else
            {
                throw new NotSupportedException("Unexpected object type: " + o.SpatialType);
            }
        }
        /**
         * Look for groups of vertices that are separated by at most merge_distance()
         * and merge them into a single vertex.
         */

        private void MergeVertices()
        {
            // The overall strategy is to start from each vertex and grow a maximal
            // cluster of mergable vertices. In graph theoretic terms, we find the
            // connected components of the undirected graph whose edges connect pairs of
            // vertices that are separated by at most merge_distance.
            //
            // We then choose a single representative vertex for each cluster, and
            // update all the edges appropriately. We choose an arbitrary existing
            // vertex rather than computing the centroid of all the vertices to avoid
            // creating new vertex pairs that need to be merged. (We guarantee that all
            // vertex pairs are separated by at least merge_distance in the output.)

            var index = new PointIndex(_options.MergeDistance.Radians);

            foreach (var edge in _edges)
            {
                index.Add(edge.Key);
                var vset = edge.Value;
                foreach (var v in vset)
                {
                    index.Add(v);
                }
            }

            // Next, we loop through all the vertices and attempt to grow a maximial
            // mergeable group starting from each vertex.

            var mergeMap  = new Dictionary <S2Point, S2Point>();
            var frontier  = new Stack <S2Point>();
            var mergeable = new List <S2Point>();

            foreach (var entry in index)
            {
                var point = entry.Value;
                if (point.IsMarked)
                {
                    continue; // Already processed.
                }

                point.Mark();

                // Grow a maximal mergeable component starting from "vstart", the
                // canonical representative of the mergeable group.
                var vstart = point.Point;
                frontier.Push(vstart);
                while (frontier.Any())
                {
                    var v0 = frontier.Pop();

                    index.Query(v0, mergeable);
                    foreach (var v1 in mergeable)
                    {
                        frontier.Push(v1);
                        mergeMap.Add(v1, vstart);
                    }
                }
            }

            // Finally, we need to replace vertices according to the merge_map.
            MoveVertices(mergeMap);
        }