Esempio n. 1
0
 /// <summary>
 /// Appends all edges in the given S2ShapeIndexCell to the given vector.
 /// </summary>
 private static void AppendShapeEdges(S2ShapeIndex index, S2ShapeIndexCell cell, ShapeEdgeVector shape_edges)
 {
     for (int s = 0; s < cell.NumClipped(); ++s)
     {
         var clipped   = cell.Clipped(s);
         var shape     = index.Shape(clipped.ShapeId);
         var num_edges = clipped.NumEdges;
         for (int i = 0; i < num_edges; i++)
         {
             shape_edges.Add(new ShapeEdge(shape, clipped.Edge(i)));
         }
     }
 }
Esempio n. 2
0
    // Returns the total area of all polygons in the index.  Returns zero if no
    // polygons are present.  This method has good relative accuracy for both very
    // large and very small regions.  Note that the result may exceed 4*Pi if the
    // index contains overlapping polygons.
    //
    // All edges are modeled as spherical geodesics.  The result can be converted
    // to an area on the Earth's surface (with a worst-case error of 0.900% near
    // the poles) using the functions in s2earth.h.
    public static double GetArea(S2ShapeIndex index)
    {
        double area = 0;

        for (int i = 0; i < index.NumShapeIds(); ++i)
        {
            var shape = index.Shape(i);
            if (shape != null)
            {
                area += S2.GetArea(shape);
            }
        }
        return(area);
    }
Esempio n. 3
0
    // Returns the total perimeter of all polygons in the index (including both
    // "shells" and "holes").  Returns zero if no polygons are present.
    //
    // All edges are modeled as spherical geodesics.  The result can be converted
    // to a distance on the Earth's surface (with a worst-case error of 0.562%
    // near the equator) using the functions in s2earth.h.
    public static S1Angle GetPerimeter(S2ShapeIndex index)
    {
        var perimeter = S1Angle.Zero;

        for (int i = 0; i < index.NumShapeIds(); ++i)
        {
            var shape = index.Shape(i);
            if (shape != null)
            {
                perimeter += S2.GetPerimeter(shape);
            }
        }
        return(perimeter);
    }
Esempio n. 4
0
    // Returns the total length of all polylines in the index.  Returns zero if no
    // polylines are present.
    //
    // All edges are modeled as spherical geodesics.  The result can be converted
    // to a distance on the Earth's surface (with a worst-case error of 0.562%
    // near the equator) using the functions in s2earth.h.
    public static S1Angle GetLength(S2ShapeIndex index)
    {
        var length = S1Angle.Zero;

        for (int i = 0; i < index.NumShapeIds(); ++i)
        {
            var shape = index.Shape(i);
            if (shape != null)
            {
                length += S2.GetLength(shape);
            }
        }
        return(length);
    }
Esempio n. 5
0
    // Returns the number of points (objects of dimension zero) in the index.
    // Note that polyline and polygon vertices are *not* included in this count.
    public static int GetNumPoints(S2ShapeIndex index)
    {
        int count = 0;

        for (int i = 0; i < index.NumShapeIds(); ++i)
        {
            var shape = index.Shape(i);
            if (shape != null && shape.Dimension() == 0)
            {
                count += shape.NumEdges();
            }
        }
        return(count);
    }
Esempio n. 6
0
    // Returns the maximum dimension of any shape in the index.  Returns -1 if the
    // index does not contain any shapes.
    //
    // Note that the dimension does *not* depend on whether the shapes in the
    // index contain any points; for example, the dimension of an empty point set
    // is 0, and the dimension of an empty polygon is 2.
    public static int GetDimension(S2ShapeIndex index)
    {
        int dim = -1;

        for (int i = 0; i < index.NumShapeIds(); ++i)
        {
            var shape = index.Shape(i);
            if (shape != null)
            {
                dim = Math.Max(dim, shape.Dimension());
            }
        }
        return(dim);
    }
Esempio n. 7
0
 public bool MoveNext()
 {
     while (++edge_id_ >= num_edges_)
     {
         if (++shape_id_ >= index_.NumShapeIds())
         {
             break;
         }
         var shape = index_.Shape(shape_id_);
         num_edges_ = (shape == null) ? 0 : shape.NumEdges();
         edge_id_   = -1;
     }
     return(!Done());
 }
Esempio n. 8
0
 public VisitIntersectingShapesTest(S2ShapeIndex index)
 {
     index_  = index;
     iter_   = new(index);
     region_ = new(index);
     // Create an S2ShapeIndex for each shape in the original index, so that we
     // can use MayIntersect() and Contains() to determine the status of
     // individual shapes.
     for (int s = 0; s < index_.NumShapeIds(); ++s)
     {
         var shape_index = new MutableS2ShapeIndex();
         shape_index.Add(new S2WrappedShape(index_.Shape(s)));
         shape_indexes_.Add(shape_index);
     }
 }
Esempio n. 9
0
    // Returns the centroid of all shapes whose dimension is maximal within the
    // index, multiplied by the measure of those shapes.  For example, if the
    // index contains points and polylines, then the result is defined as the
    // centroid of the polylines multiplied by the total length of those
    // polylines.  The points would be ignored when computing the centroid.
    //
    // The measure of a given shape is defined as follows:
    //
    //  - For dimension 0 shapes, the measure is shape.num_edges().
    //  - For dimension 1 shapes, the measure is GetLength(shape).
    //  - For dimension 2 shapes, the measure is GetArea(shape).
    //
    // Note that the centroid is not unit length, so you may need to call
    // Normalize() before passing it to other S2 functions.  Note that this
    // function returns (0, 0, 0) if the index contains no geometry.
    //
    // The centroid is scaled by the total measure of the shapes for two reasons:
    // (1) it is cheaper to compute this way, and (2) this makes it easier to
    // compute the centroid of a collection of shapes (since the individual
    // centroids can simply be summed).
    public static S2Point GetCentroid(S2ShapeIndex index)
    {
        int dim      = GetDimension(index);
        var centroid = S2Point.Empty;

        for (int i = 0; i < index.NumShapeIds(); ++i)
        {
            var shape = index.Shape(i);
            if (shape != null && shape.Dimension() == dim)
            {
                centroid += S2.GetCentroid(shape);
            }
        }
        return(centroid);
    }
Esempio n. 10
0
    /// <summary>
    /// Verifies that two S2ShapeIndexes have identical contents (including all the
    /// S2Shapes in both indexes).
    /// </summary>
    public static void ExpectEqual(S2ShapeIndex a, S2ShapeIndex b)
    {
        // Check that both indexes have identical shapes.
        Assert.True(a.NumShapeIds() == b.NumShapeIds());
        for (int shape_id = 0; shape_id < a.NumShapeIds(); ++shape_id)
        {
            var a_shape = a.Shape(shape_id);
            var b_shape = b.Shape(shape_id);
            if (a_shape == null || b_shape == null)
            {
                Assert.True(a_shape == b_shape);
            }
            else
            {
                Assert.True(a_shape.Id == b_shape.Id);
                Assert.True(a_shape == b_shape);
            }
        }

        // Check that both indexes have identical cell contents.
        var a_it     = a.GetNewEnumerator();
        var b_it     = b.GetNewEnumerator();
        var aHasNext = a_it.MoveNext();
        var bHasNext = b_it.MoveNext();

        while (aHasNext && bHasNext)
        {
            Assert.True(a_it.Current.Item1 == b_it.Current.Item1);
            var a_cell = a_it.Current.Item2;
            var b_cell = b_it.Current.Item2;
            Assert.True(a_cell.NumClipped() == b_cell.NumClipped());
            for (var i = 0; i < a_cell.NumClipped(); ++i)
            {
                var a_clipped = a_cell.Clipped(i);
                var b_clipped = b_cell.Clipped(i);
                Assert.True(a_clipped.ShapeId == b_clipped.ShapeId);
                Assert.True(a_clipped.ContainsCenter == b_clipped.ContainsCenter);
                Assert.True(a_clipped.NumEdges == b_clipped.NumEdges);
                for (int j = 0; j < a_clipped.NumEdges; ++j)
                {
                    Assert.True(a_clipped.Edge(j) == b_clipped.Edge(j));
                }
            }
            aHasNext = a_it.MoveNext();
            bHasNext = b_it.MoveNext();
        }
        Assert.True(!bHasNext);

        // Spot-check the other iterator methods.  (We know that both indexes have
        // the same contents, so any differences are due to implementation bugs.)
        a_it.Reset();
        b_it.Reset();
        a_it.MoveNext();
        b_it.MoveNext();
        Assert.True(a_it.Current.Item1 == b_it.Current.Item1);
        aHasNext = a_it.MoveNext();
        bHasNext = b_it.MoveNext();
        if (aHasNext)
        {
            Assert.True(a_it.Current.Item1 == b_it.Current.Item1);
            Assert.True(aHasNext == bHasNext);
            // Assert.True(a_it.MovePrevious());
            // Assert.True(b_it.MovePrevious());
            Assert.True(a_it.Current.Item1 == b_it.Current.Item1);
        }
        // Assert.False(a_it.MovePrevious());
        // Assert.False(b_it.MovePrevious());
        // a_it.Finish();
        // b_it.Finish();
        // Assert.True(a_it.id() == b_it.id());
        // a_it.Seek(a_it.id().Next);
        // b_it.Seek(b_it.id().Next);
        // Assert.True(a_it.id() == b_it.id());
    }