示例#1
0
 /// <summary>
 /// Verifies that all methods of the two S2Shapes return identical results,
 /// except for id() and type_tag().
 /// </summary>
 public static void ExpectEqual(S2Shape a, S2Shape b)
 {
     Assert.True(a.NumEdges() == b.NumEdges());
     for (int i = 0; i < a.NumEdges(); ++i)
     {
         Assert.Equal(a.GetEdge(i), b.GetEdge(i));
         Assert.True(a.GetChainPosition(i) == b.GetChainPosition(i));
     }
     Assert.True(a.Dimension() == b.Dimension());
     Assert.True(a.GetReferencePoint() == b.GetReferencePoint());
     Assert.True(a.NumChains() == b.NumChains());
     for (int i = 0; i < a.NumChains(); ++i)
     {
         Assert.True(a.GetChain(i) == b.GetChain(i));
         int chain_length = a.GetChain(i).Length;
         for (int j = 0; j < chain_length; ++j)
         {
             Assert.True(a.ChainEdge(i, j) == b.ChainEdge(i, j));
         }
     }
 }
示例#2
0
    // Overwrites "vertices" with the vertices of the given edge chain of "shape".
    // If dimension == 1, the chain will have (chain.length + 1) vertices, and
    // otherwise it will have (chain.length) vertices.
    //
    // This is a low-level helper method used in the implementations of some of
    // the methods above.
    public static void GetChainVertices(S2Shape shape, int chain_id, out S2Point[] vertices)
    {
        S2Shape.Chain chain        = shape.GetChain(chain_id);
        int           num_vertices = chain.Length + (shape.Dimension() == 1 ? 1 : 0);
        int           e            = 0;
        var           verts        = new List <S2Point>();

        if ((num_vertices & 1) != 0)
        {
            verts.Add(shape.ChainEdge(chain_id, e++).V0);
        }
        for (; e < num_vertices; e += 2)
        {
            var edge = shape.ChainEdge(chain_id, e);
            verts.Add(edge.V0);
            verts.Add(edge.V1);
        }

        vertices = verts.ToArray();
    }
示例#3
0
    // This is a helper function for implementing S2Shape.GetReferencePoint().
    //
    // Given a shape consisting of closed polygonal loops, the interior of the
    // shape is defined as the region to the left of all edges (which must be
    // oriented consistently).  This function then chooses an arbitrary point and
    // returns true if that point is contained by the shape.
    //
    // Unlike S2Loop and S2Polygon, this method allows duplicate vertices and
    // edges, which requires some extra care with definitions.  The rule that we
    // apply is that an edge and its reverse edge "cancel" each other: the result
    // is the same as if that edge pair were not present.  Therefore shapes that
    // consist only of degenerate loop(s) are either empty or full; by convention,
    // the shape is considered full if and only if it contains an empty loop (see
    // S2LaxPolygonShape for details).
    //
    // Determining whether a loop on the sphere contains a point is harder than
    // the corresponding problem in 2D plane geometry.  It cannot be implemented
    // just by counting edge crossings because there is no such thing as a "point
    // at infinity" that is guaranteed to be outside the loop.
    public static S2Shape.ReferencePoint GetReferencePoint(this S2Shape shape)
    {
        System.Diagnostics.Debug.Assert(shape.Dimension() == 2);
        if (shape.NumEdges() == 0)
        {
            // A shape with no edges is defined to be full if and only if it
            // contains at least one chain.
            return(S2Shape.ReferencePoint.FromContained(shape.NumChains() > 0));
        }
        // Define a "matched" edge as one that can be paired with a corresponding
        // reversed edge.  Define a vertex as "balanced" if all of its edges are
        // matched. In order to determine containment, we must find an unbalanced
        // vertex.  Often every vertex is unbalanced, so we start by trying an
        // arbitrary vertex.
        var edge = shape.GetEdge(0);

        if (GetReferencePointAtVertex(shape, edge.V0, out var result))
        {
            return(result);
        }
        // That didn't work, so now we do some extra work to find an unbalanced
        // vertex (if any).  Essentially we gather a list of edges and a list of
        // reversed edges, and then sort them.  The first edge that appears in one
        // list but not the other is guaranteed to be unmatched.
        int n         = shape.NumEdges();
        var edges     = new S2Shape.Edge[n];
        var rev_edges = new S2Shape.Edge[n];

        for (int i = 0; i < n; ++i)
        {
            var edge2 = shape.GetEdge(i);
            edges[i]     = edge2;
            rev_edges[i] = new S2Shape.Edge(edge2.V1, edge2.V0);
        }
        Array.Sort(edges);
        Array.Sort(rev_edges);
        for (int i = 0; i < n; ++i)
        {
            if (edges[i] < rev_edges[i])
            {  // edges[i] is unmatched
                System.Diagnostics.Debug.Assert(GetReferencePointAtVertex(shape, edges[i].V0, out result));
                return(result);
            }
            if (rev_edges[i] < edges[i])
            {  // rev_edges[i] is unmatched
                System.Diagnostics.Debug.Assert(GetReferencePointAtVertex(shape, rev_edges[i].V0, out result));
                return(result);
            }
        }
        // All vertices are balanced, so this polygon is either empty or full except
        // for degeneracies.  By convention it is defined to be full if it contains
        // any chain with no edges.
        for (int i = 0; i < shape.NumChains(); ++i)
        {
            if (shape.GetChain(i).Length == 0)
            {
                return(S2Shape.ReferencePoint.FromContained(true));
            }
        }
        return(S2Shape.ReferencePoint.FromContained(false));
    }