Basic Types

S1Angle

The S1Angle class represents a one-dimensional angle (as opposed to a 2D solid
angle). It has methods for converting angles to or from radians, degrees, and
the E5/E6/E7 representations (i.e. degrees multiplied by 1e5/1e6/1e7 and rounded
to the nearest integer).

classS1Angle{public:// These methods construct S1Angle objects from their measure in radians
// or degrees.
staticconstexprS1AngleRadians(doubleradians);staticconstexprS1AngleDegrees(doubledegrees);staticconstexprS1AngleE5(int32e5);staticconstexprS1AngleE6(int32e6);staticconstexprS1AngleE7(int32e7);// The default constructor yields a zero angle. This is useful for STL
// containers and class methods with output arguments.
constexprS1Angle();// Return an angle larger than any finite angle.
staticconstexprS1AngleInfinity();// A explicit shorthand for the default constructor.
staticconstexprS1AngleZero();// Return the angle between two points, which is also equal to the distance
// between these points on the unit sphere. The points do not need to be
// normalized.
S1Angle(constS2Point&x,constS2Point&y);// Like the constructor above, but return the angle (i.e., distance)
// between two S2LatLng points.
S1Angle(constS2LatLng&x,constS2LatLng&y);constexprdoubleradians()const;constexprdoubledegrees()const;int32e5()const;int32e6()const;int32e7()const;// Return the absolute value of an angle.
S1Angleabs()const;// Return the angle normalized to the range (-180, 180] degrees.
S1AngleNormalized()const;// Normalize this angle to the range (-180, 180] degrees.
voidNormalize();};

See s1angle.h for additional methods, including comparison and arithmetic
operators. For example, if x and y are angles, then you can write

if (sin(0.5 * x) > (x + y) / (x - y)) { ... }

S2Point

The S2Point class represents a point on the unit sphere as a 3D vector.
Usually points are normalized to be unit length, but some methods do not require
this. The S2Point class is simply a synonym for the Vector_3d class from
util/math/vector.h, which defines overloaded operators that make it convenient
to write arithmetic expressions (e.g. x*p1 + (1-x)*p2).

S2LatLng

The S2LatLng class represents a point on the unit sphere as a pair of
latitude-longitude coordinates.

classS2LatLng{public:// Constructor. The latitude and longitude are allowed to be outside
// the is_valid() range. However, note that most methods that accept
// S2LatLngs expect them to be normalized (see Normalized() below).
S2LatLng(S1Anglelat,S1Anglelng);// The default constructor sets the latitude and longitude to zero. This is
// mainly useful when declaring arrays, STL containers, etc.
S2LatLng();// Convert a direction vector (not necessarily unit length) to an S2LatLng.
explicitS2LatLng(constS2Point&p);// Returns an S2LatLng for which is_valid() will return false.
staticS2LatLngInvalid();// Convenience functions -- shorter than calling S1Angle::Radians(), etc.
staticS2LatLngFromRadians(doublelat_radians,doublelng_radians);staticS2LatLngFromDegrees(doublelat_degrees,doublelng_degrees);staticS2LatLngFromE5(int32lat_e5,int32lng_e5);staticS2LatLngFromE6(int32lat_e6,int32lng_e6);staticS2LatLngFromE7(int32lat_e7,int32lng_e7);// Accessor methods.
S1Anglelat()const;S1Anglelng()const;constR2Point&coords()const;// Return true if the latitude is between -90 and 90 degrees inclusive
// and the longitude is between -180 and 180 degrees inclusive.
boolis_valid()const;// Clamps the latitude to the range [-90, 90] degrees, and adds or subtracts
// a multiple of 360 degrees to the longitude if necessary to reduce it to
// the range [-180, 180].
S2LatLngNormalized()const;// Convert a normalized S2LatLng to the equivalent unit-length vector.
S2PointToPoint()const;// Return the distance (measured along the surface of the sphere) to the
// given S2LatLng. This is mathematically equivalent to:
//
// S1Angle(ToPoint(), o.ToPoint())
//
// but this implementation is slightly more efficient. Both S2LatLngs
// must be normalized.
S1AngleGetDistance(constS2LatLng&o)const;};

See s2latlng.h for additional methods, including comparison and arithmetic
operators.

S2Region

An S2Region represents a two-dimensional region over the unit sphere. It is an
abstract interface with various concrete subtypes, such as discs, rectangles,
polylines, polygons, geometry collections, buffered shapes, etc.

The main purpose of this interface is to allow complex regions to be
approximated as simpler regions. So rather than having a wide variety of virtual
methods that are implemented by all subtypes, the interface is restricted to
methods that are useful for computing approximations. Here they are:

classS2Region{public:virtual~S2Region();// Return a deep copy of this region. If you want to narrow the result to a
// specific known region type, use down_cast<T*> from casts.h.
// Subtypes return pointers to that subtype from their Clone() methods.
virtualS2Region*Clone()const=0;// Return a bounding spherical cap. This is not guaranteed to be exact.
virtualS2CapGetCapBound()const=0;// Return a bounding latitude-longitude rectangle that contains the region.
// The bounds are not guaranteed to be tight.
virtualS2LatLngRectGetRectBound()const=0;// If this method returns true, the region completely contains the given
// cell. Otherwise, either the region does not contain the cell or the
// containment relationship could not be determined.
virtualboolContains(constS2Cell&cell)const=0;// If this method returns false, the region does not intersect the given
// cell. Otherwise, either region intersects the cell, or the intersection
// relationship could not be determined.
virtualboolMayIntersect(constS2Cell&cell)const=0;// Return true if and only if the given point is contained by the region.
// The point 'p' is generally required to be unit length, although some
// subtypes may relax this restriction.
virtualboolContains(constS2Point&p)const=0;//////////////////////////////////////////////////////////////////////////
// Many S2Region subtypes also define the following non-virtual methods.
// Appends a serialized representation of the region to "encoder".
voidEncode(Encoder*constencoder)const;// Decodes an S2Region encoded with Encode(). Note that this method
// requires that an S2Region object of the appropriate concrete type has
// already been constructed. It is not possible to decode regions of
// unknown type.
boolDecode(Decoder*constdecoder);};

See s2region.h for the full interface.

S2LatLngRect

An S2LatLngRect is a type of S2Region that represents a rectangle in
latitude-longitude space. It is capable of representing the empty and full
rectangles as well as single points. It has an AddPoint method that makes it
easy to construct a bounding rectangle for a set of points, including point sets
that span the 180 degree meridian. Here are its methods:

classS2LatLngRectfinal:publicS2Region{public:// Construct a rectangle from minimum and maximum latitudes and longitudes.
// If lo.lng() > hi.lng(), the rectangle spans the 180 degree longitude
// line. Both points must be normalized, with lo.lat() <= hi.lat().
// The rectangle contains all the points p such that 'lo' <= p <= 'hi',
// where '<=' is defined in the obvious way.
S2LatLngRect(constS2LatLng&lo,constS2LatLng&hi);// Construct a rectangle from latitude and longitude intervals. The two
// intervals must either be both empty or both non-empty, and the latitude
// interval must not extend outside [-90, +90] degrees.
S2LatLngRect(constR1Interval&lat,constS1Interval&lng);// The default constructor creates an empty S2LatLngRect.
S2LatLngRect();// Construct a rectangle of the given size centered around the given point.
staticS2LatLngRectFromCenterSize(constS2LatLng&center,constS2LatLng&size);// Construct a rectangle containing a single (normalized) point.
staticS2LatLngRectFromPoint(constS2LatLng&p);// Construct the minimal bounding rectangle containing the two given
// normalized points. The points do not need to be ordered.
staticS2LatLngRectFromPointPair(constS2LatLng&p1,constS2LatLng&p2);// Accessor methods.
S1Anglelat_lo()const;S1Anglelat_hi()const;S1Anglelng_lo()const;S1Anglelng_hi()const;constR1Interval&lat()const;constS1Interval&lng()const;R1Interval*mutable_lat();S1Interval*mutable_lng();S2LatLnglo()const;S2LatLnghi()const;// The canonical empty and full rectangles.
staticS2LatLngRectEmpty();staticS2LatLngRectFull();// Return true if the rectangle is valid, which essentially just means
// that the latitude bounds do not exceed Pi/2 in absolute value and
// the longitude bounds do not exceed Pi in absolute value. Also, if
// either the latitude or longitude bound is empty then both must be.
boolis_valid()const;// Return true if the rectangle is empty, i.e. it contains no points at all.
boolis_empty()const;// Return true if the rectangle is full, i.e. it contains all points.
boolis_full()const;// Return true if the rectangle is a point, i.e. lo() == hi()
boolis_point()const;// Return true if the rectangle crosses the 180 degree longitude line.
boolis_inverted()const;// Return the k-th vertex of the rectangle (k = 0,1,2,3) in CCW order (lower
// left, lower right, upper right, upper left).
S2LatLngGetVertex(intk)const;// Return the center of the rectangle in latitude-longitude space
// (in general this is not the center of the region on the sphere).
S2LatLngGetCenter()const;// Return the width and height of this rectangle in latitude-longitude
// space. Empty rectangles have a negative width and height.
S2LatLngGetSize()const;// Returns the surface area of this rectangle on the unit sphere.
doubleArea()const;// Return the true centroid of the rectangle multiplied by its surface area.
// The true centroid is the "center of mass" of the rectangle viewed as
// subset of the unit sphere, i.e. it is the point in space about which this
// curved shape would rotate.)
//
// The reason for multiplying the result by the rectangle area is to make it
// easier to compute the centroid of more complicated shapes.
S2PointGetCentroid()const;// More efficient version of Contains() that accepts a S2LatLng rather than
// an S2Point.
boolContains(constS2LatLng&ll)const;// Return true if and only if the given point is contained in the interior
// of the region (i.e. the region excluding its boundary).
boolInteriorContains(constS2Point&p)const;// More efficient version of InteriorContains() that accepts a S2LatLng
// rather than an S2Point.
boolInteriorContains(constS2LatLng&ll)const;// Return true if and only if the rectangle contains the given other
// rectangle.
boolContains(constS2LatLngRect&other)const;// Return true if and only if the interior of this rectangle contains all
// points of the given other rectangle (including its boundary).
boolInteriorContains(constS2LatLngRect&other)const;// Return true if this rectangle and the given other rectangle have any
// points in common.
boolIntersects(constS2LatLngRect&other)const;// Returns true if this rectangle intersects the given cell. (This is an
// exact test and may be fairly expensive, see also MayIntersect below.)
boolIntersects(constS2Cell&cell)const;// Return true if and only if the interior of this rectangle intersects
// any point (including the boundary) of the given other rectangle.
boolInteriorIntersects(constS2LatLngRect&other)const;// Increase the size of the bounding rectangle to include the given point.
// The rectangle is expanded by the minimum amount possible.
voidAddPoint(constS2Point&p);voidAddPoint(constS2LatLng&ll);// Return a rectangle that has been expanded by margin.lat() on each side in
// the latitude direction, and by margin.lng() on each side in the longitude
// direction. If either margin is negative, then shrink the rectangle on
// the corresponding sides instead. The resulting rectangle may be empty.
//
// If you are trying to grow a rectangle by a certain *distance* on the
// sphere (e.g. 5km), use the ExpandedByDistance() method instead.
S2LatLngRectExpanded(constS2LatLng&margin)const;// If the rectangle does not include either pole, return it unmodified.
// Otherwise expand the longitude range to Full() so that the rectangle
// contains all possible representations of the contained pole(s).
S2LatLngRectPolarClosure()const;// Return the smallest rectangle containing the union of this rectangle and
// the given rectangle.
S2LatLngRectUnion(constS2LatLngRect&other)const;// Return the smallest rectangle containing the intersection of this
// rectangle and the given rectangle. Note that the region of intersection
// may consist of two disjoint rectangles, in which case a single rectangle
// spanning both of them is returned.
S2LatLngRectIntersection(constS2LatLngRect&other)const;// Expand this rectangle so that it contains all points within the given
// distance of the boundary, and return the smallest such rectangle. If the
// distance is negative, then instead shrink this rectangle so that it
// excludes all points within the given absolute distance of the boundary,
// and return the largest such rectangle.
//
// Unlike Expanded(), this method treats the rectangle as a set of points on
// the sphere, and measures distances on the sphere. For example, you can
// use this method to find a rectangle that contains all points within 5km
// of a given rectangle.
S2LatLngRectExpandedByDistance(S1Angledistance)const;// Returns the minimum distance (measured along the surface of the sphere) to
// the given S2LatLngRect. Both S2LatLngRects must be non-empty.
S1AngleGetDistance(constS2LatLngRect&other)const;// Returns the minimum distance (measured along the surface of the sphere)
// from a given point to the rectangle (both its boundary and its interior).
S1AngleGetDistance(constS2LatLng&p)const;////////////////////////////////////////////////////////////////////////
// S2Region interface (see s2region.h for details):
S2LatLngRect*Clone()constoverride;S2CapGetCapBound()constoverride;S2LatLngRectGetRectBound()constoverride;// The point 'p' does not need to be normalized.
boolContains(constS2Cell&cell)constoverride;// This test is cheap but is NOT exact. Use Intersects() if you want a more
// accurate and more expensive test.
boolMayIntersect(constS2Cell&cell)constoverride;};

See s2latlngrect.h for additional methods.

S1ChordAngle

S1ChordAngle is a specialized angle type that represents the distance
between two points on the sphere. (Note that the distance between two
points can be expressed as the angle between those points measured from the
sphere’s center.) Its representation makes it very efficient for computing
and comparing distances, but unlike S1Angle it is only capable of
representing angles between 0 and 180 degrees. (Internally, S1ChordAngle
computes the squared distance between two points through the interior of
the sphere, i.e. the squared length of the chord between those points).

S1ChordAngle is the preferred representation for distances internally,
because it is much faster to compute than S1Angle and also supports the
exact predicates needed for robust geometric algorithms. S1ChordAngle
supports many of the same methods as S1Angle, and it is also easy to
convert back and forth as required.

S2Cap

An S2Cap represents a spherical cap, i.e. a portion of a sphere cut off by a
plane. This is the equivalent of a closed disc in planar geometry (i.e., a
circle together with its interior), so if you are looking for a way to represent
a circle or disc then you are probably looking for an S2Cap.

Here are the methods available:

classS2Capfinal:publicS2Region{public:// The default constructor returns an empty S2Cap.
S2Cap();// Construct a cap with the given center and radius. A negative radius
// yields an empty cap; a radius of 180 degrees or more yields a full cap
// (containing the entire sphere).
S2Cap(constS2Point&center,S1Angleradius);// Convenience function that creates a cap containing a single point. This
// method is more efficient that the S2Cap(center, radius) constructor.
staticS2CapFromPoint(constS2Point&center);// Return a cap with the given center and height. (The height of a cap is
// the distance from the cap center to the cutoff plane; see comments
// above.) A negative height yields an empty cap; a height of 2 or more
// yields a full cap.
staticS2CapFromCenterHeight(constS2Point&center,doubleheight);// Return a cap with the given center and surface area. Note that the area
// can also be interpreted as the solid angle subtended by the cap (because
// the sphere has unit radius). A negative area yields an empty cap; an
// area of 4*Pi or more yields a full cap.
staticS2CapFromCenterArea(constS2Point&center,doublearea);// Return an empty cap, i.e. a cap that contains no points.
staticS2CapEmpty();// Return a full cap, i.e. a cap that contains all points.
staticS2CapFull();// Accessor methods.
constS2Point&center()const;S1ChordAngleradius()const;doubleheight()const;// Return the cap radius. (This method is relatively expensive since only
// the cap height is stored internally, and may yield a slightly different
// result than the value passed to the (center, radius) constructor.)
S1AngleGetRadius()const;// Return the area of the cap.
doubleGetArea()const;// Return the true centroid of the cap multiplied by its surface area. Note
// that if you just want the "surface centroid", i.e. the normalized result,
// then it is much simpler just to call center().
//
// The reason for multiplying the result by the cap area is to make it
// easier to compute the centroid of more complicated shapes.
S2PointGetCentroid()const;// We allow negative heights (to represent empty caps) but heights are
// normalized so that they do not exceed 2.
boolis_valid()const;// Return true if the cap is empty, i.e. it contains no points.
boolis_empty()const;// Return true if the cap is full, i.e. it contains all points.
boolis_full()const;// Return the complement of the interior of the cap. A cap and its
// complement have the same boundary but do not share any interior points.
S2CapComplement()const;// Return true if and only if this cap contains the given other cap
// (in a set containment sense, e.g. every cap contains the empty cap).
boolContains(constS2Cap&other)const;// Return true if and only if this cap intersects the given other cap,
// i.e. whether they have any points in common.
boolIntersects(constS2Cap&other)const;// Return true if and only if the interior of this cap intersects the
// given other cap. (This relationship is not symmetric, since only
// the interior of this cap is used.)
boolInteriorIntersects(constS2Cap&other)const;// Return true if and only if the given point is contained in the interior
// of the cap (i.e. the cap excluding its boundary).
boolInteriorContains(constS2Point&p)const;// Increase the cap height if necessary to include the given point. If the
// cap is empty then the center is set to the given point, but otherwise the
// center is not changed.
voidAddPoint(constS2Point&p);// Increase the cap height if necessary to include "other". If the current
// cap is empty it is set to the given other cap.
voidAddCap(constS2Cap&other);// Return a cap that contains all points within a given distance of this
// cap. Note that any expansion of the empty cap is still empty.
S2CapExpanded(S1Angledistance)const;// Return the smallest cap which encloses this cap and "other".
S2CapUnion(constS2Cap&other)const;////////////////////////////////////////////////////////////////////////
// S2Region interface (see s2region.h for details):
S2Cap*Clone()constoverride;S2CapGetCapBound()constoverride;S2LatLngRectGetRectBound()constoverride;// The point "p" should be a unit-length vector.
boolContains(constS2Cell&cell)constoverride;boolMayIntersect(constS2Cell&cell)constoverride;};

See s2cap.h for additional methods.

S2Polyline

An S2Polyline represents a sequence of zero or more vertices connected by
straight edges (geodesics). Edges of length 0 and 180 degrees are not allowed,
i.e. adjacent vertices should not be identical or antipodal.

classS2Polylinefinal:publicS2Region{public:// Creates an empty S2Polyline that should be initialized by calling Init()
// or Decode().
S2Polyline();// Convenience constructors that call Init() with the given vertices.
explicitS2Polyline(conststd::vector<S2Point>&vertices);explicitS2Polyline(conststd::vector<S2LatLng>&vertices);~S2Polyline();// Initialize a polyline that connects the given vertices. Empty polylines are
// allowed. Adjacent vertices should not be identical or antipodal. All
// vertices should be unit length.
voidInit(conststd::vector<S2Point>&vertices);// Convenience initialization function that accepts latitude-longitude
// coordinates rather than S2Points.
voidInit(conststd::vector<S2LatLng>&vertices);// Return true if the given vertices form a valid polyline.
boolIsValid()const;// Returns true if this is *not* a valid polyline and sets "error"
// appropriately. Otherwise returns false and leaves "error" unchanged.
boolFindValidationError(S2Error*error)const;// Accessor methods.
intnum_vertices()const;constS2Point&vertex(intk)const;// Return the length of the polyline.
S1AngleGetLength()const;// Return the true centroid of the polyline multiplied by the length of the
// polyline. Prescaling by the polyline length makes it easy to compute the
// centroid of several polylines (by simply adding up their centroids).
S2PointGetCentroid()const;// Return the point whose distance from vertex 0 along the polyline is the
// given fraction of the polyline's total length. Fractions less than zero
// or greater than one are clamped. The return value is unit length.
S2PointInterpolate(doublefraction)const;// Like Interpolate(), but also return the index of the next polyline
// vertex after the interpolated point P. This allows the caller to easily
// construct a given suffix of the polyline by concatenating P with the
// polyline vertices starting at "next_vertex".
S2PointGetSuffix(doublefraction,int*next_vertex)const;// The inverse operation of GetSuffix/Interpolate. Given a point on the
// polyline, returns the ratio of the distance to the point from the
// beginning of the polyline over the length of the polyline. The return
// value is always betwen 0 and 1 inclusive. See GetSuffix() for the
// meaning of "next_vertex".
doubleUnInterpolate(constS2Point&point,intnext_vertex)const;// Given a point, returns a point on the polyline that is closest to the given
// point. See GetSuffix() for the meaning of "next_vertex".
S2PointProject(constS2Point&point,int*next_vertex)const;// Returns true if the point given is on the right hand side of the polyline,
// using a naive definition of "right-hand-sideness" where the point is on
// the RHS of the polyline iff the point is on the RHS of the line segment in
// the polyline which it is closest to.
boolIsOnRight(constS2Point&point)const;// Return true if this polyline intersects the given polyline. If the
// polylines share a vertex they are considered to be intersecting.
boolIntersects(constS2Polyline*line)const;// Reverse the order of the polyline vertices.
voidReverse();// Return a subsequence of vertex indices such that the polyline connecting
// these vertices is never further than "tolerance" from the original
// polyline.
voidSubsampleVertices(S1Angletolerance,std::vector<int>*indices)const;// Return true if "covered" is within "max_error" of a contiguous subpath of
// this polyline over its entire length. Specifically, this method returns
// true if this polyline has parameterization a:[0,1] -> S^2, "covered" has
// parameterization b:[0,1] -> S^2, and there is a non-decreasing function
// f:[0,1] -> [0,1] such that distance(a(f(t)), b(t)) <= max_error for all t.
//
// You can think of this as testing whether it is possible to drive a car
// along "covered" and a car along some subpath of this polyline such that no
// car ever goes backward, and the cars are always within "max_error" of each
// other.
boolNearlyCoversPolyline(constS2Polyline&covered,S1Anglemax_error)const;////////////////////////////////////////////////////////////////////////
// S2Region interface (see s2region.h for details):
S2Polyline*Clone()constoverride;S2CapGetCapBound()constoverride;S2LatLngRectGetRectBound()constoverride;boolContains(constS2Cell&cell)constoverride;boolMayIntersect(constS2Cell&cell)constoverride;};

S2Loop

An S2Loop represents a simple spherical polygon. It consists of a single chain
of vertices where the first vertex is implicitly connected to the last. All
loops are defined to have a CCW orientation, i.e. the interior of the loop is on
the left side of the edges. This implies that a clockwise loop enclosing a small
area is interpreted to be a CCW loop enclosing a very large area.

Loops are not allowed to have any duplicate vertices (whether adjacent or not),
and non-adjacent edges are not allowed to intersect. Loops must have at least 3
vertices (except for the “empty” and “full” loops discussed below). These
restrictions make it possible to implement exact polygon-polygon containment and
intersection tests very efficiently. See S2Builder if your data does not meet
these requirements.

There are two special loops: the “empty” loop contains no points, while the
“full” loop contains all points. These loops do not have any edges, but to
preserve the invariant that every loop can be represented as a vertex chain,
they are defined as having exactly one vertex each (see kEmpty and kFull).

Point containment of loops is defined such that if the sphere is subdivided into
faces (loops), every point is contained by exactly one face. This implies that
loops do not necessarily contain their vertices.

classS2Loopfinal:publicS2Region{public:// Default constructor. The loop must be initialized by calling Init() or
// Decode() before it is used.
S2Loop();// Convenience constructor that calls Init() with the given vertices.
explicitS2Loop(conststd::vector<S2Point>&vertices);// Construct a loop corresponding to the given cell.
//
// Note that the loop and cell *do not* contain exactly the same set of
// points, because S2Loop and S2Cell have slightly different definitions of
// point containment. For example, an S2Cell vertex is contained by all
// four neighboring S2Cells, but it is contained by exactly one of four
// S2Loops constructed from those cells.
explicitS2Loop(constS2Cell&cell);~S2Loop();// Initialize a loop with given vertices. The last vertex is implicitly
// connected to the first. All points should be unit length. Loops must
// have at least 3 vertices (except for the "empty" and "full" loops, see
// kEmpty and kFull). This method may be called multiple times.
voidInit(conststd::vector<S2Point>&vertices);// A special vertex chain of length 1 that creates an empty loop (i.e., a
// loop with no edges that contains no points). Example usage:
// S2Loop empty(S2Loop::kEmpty());
staticstd::vector<S2Point>kEmpty();// A special vertex chain of length 1 that creates a full loop (i.e., a loop
// with no edges that contains all points). See kEmpty() for details.
staticstd::vector<S2Point>kFull();// Returns true if this is a valid loop.
boolIsValid()const;// Returns true if this is *not* a valid loop and sets "error"
// appropriately. Otherwise returns false and leaves "error" unchanged.
boolFindValidationError(S2Error*error)const;intnum_vertices()const;// For convenience, we make two entire copies of the vertex list available:
// vertex(n..2*n-1) is mapped to vertex(0..n-1), where n == num_vertices().
constS2Point&vertex(inti)const;// Like vertex(), but this method returns vertices in reverse order if the
// loop represents a polygon hole. This ensures that the interior of the
// polygon is always to the left of the vertex chain.
constS2Point&oriented_vertex(inti)const;// Return true if this is the special "empty" loop that contains no points.
boolis_empty()const;// Return true if this is the special "full" loop that contains all points.
boolis_full()const;// Return true if this loop is either "empty" or "full".
boolis_empty_or_full()const;// The depth of a loop is defined as its nesting level within its containing
// polygon. "Outer shell" loops have depth 0, holes within those loops have
// depth 1, shells within those holes have depth 2, etc. This field is only
// used by the S2Polygon implementation.
intdepth()const;voidset_depth(intdepth);// Return true if this loop represents a hole in its containing polygon.
boolis_hole()const;// The sign of a loop is -1 if the loop represents a hole in its containing
// polygon, and +1 otherwise.
intsign()const;// Return true if the loop area is at most 2*Pi.
boolIsNormalized()const;// Invert the loop if necessary so that the area enclosed by the loop is at
// most 2*Pi.
voidNormalize();// Reverse the order of the loop vertices, effectively complementing
// the region represented by the loop.
voidInvert();// Return the area of the loop interior, i.e. the region on the left side of
// the loop. The return value is between 0 and 4*Pi.
doubleGetArea()const;// Return the true centroid of the loop multiplied by the area of the loop.
// We prescale by the loop area for two reasons: (1) it is cheaper to
// compute this way, and (2) it makes it easier to compute the centroid of
// more complicated shapes (by splitting them into disjoint regions and
// adding their centroids).
S2PointGetCentroid()const;// Return the sum of the turning angles at each vertex. The return value is
// positive if the loop is counter-clockwise, negative if the loop is
// clockwise, and zero if the loop is a great circle.
//
// This quantity is also called the "geodesic curvature" of the loop.
doubleGetCurvature()const;// Return the maximum error in GetCurvature(). The return value is not
// constant; it depends on the loop.
doubleGetCurvatureMaxError()const;// Return the distance from the given point to the loop interior. If the
// loop is empty, return S1Angle::Infinity().
S1AngleGetDistance(constS2Point&x)const;// Return the distance from the given point to the loop boundary. If the
// loop is empty or full, return S1Angle::Infinity() (since the loop has no
// boundary).
S1AngleGetDistanceToBoundary(constS2Point&x)const;// If the given point is contained by the loop, return it. Otherwise return
// the closest point on the loop boundary. If the loop is empty, return the
// input argument.
S2PointProject(constS2Point&x)const;// Return the closest point on the loop boundary to the given point. If the
// loop is empty or full, return the input argument (since the loop has no
// boundary).
S2PointProjectToBoundary(constS2Point&x)const;// Return true if the region contained by this loop is a superset of the
// region contained by the given other loop.
boolContains(constS2Loop*b)const;// Return true if the region contained by this loop intersects the region
// contained by the given other loop.
boolIntersects(constS2Loop*b)const;// Return true if two loops have the same vertices in the same linear order
// (i.e., cyclic rotations are not allowed).
boolEquals(constS2Loop*b)const;// Return true if two loops have the same boundary. This is true if and
// only if the loops have the same vertices in the same cyclic order (i.e.,
// the vertices may be cyclically rotated). The empty and full loops are
// considered to have different boundaries.
boolBoundaryEquals(constS2Loop*b)const;// Return true if two loops have the same boundary except for vertex
// perturbations. More precisely, the vertices in the two loops must be in
// the same cyclic order, and corresponding vertex pairs must be separated
// by no more than "max_error".
boolBoundaryApproxEquals(constS2Loop&b,S1Anglemax_error=S1Angle::Radians(1e-15))const;// Return true if the two loop boundaries are within "max_error" of each
// other along their entire lengths. The two loops may have different
// numbers of vertices. More precisely, this method returns true if the two
// loops have parameterizations a:[0,1] -> S^2, b:[0,1] -> S^2 such that
// distance(a(t), b(t)) <= max_error for all t. You can think of this as
// testing whether it is possible to drive two cars all the way around the
// two loops such that no car ever goes backward and the cars are always
// within "max_error" of each other.
boolBoundaryNear(constS2Loop&b,S1Anglemax_error=S1Angle::Radians(1e-15))const;// This method computes the oriented surface integral of some quantity f(x)
// over the loop interior, given a function f_tri(A,B,C) that returns the
// corresponding integral over the spherical triangle ABC.
template<classT>TGetSurfaceIntegral(Tf_tri(constS2Point&,constS2Point&,constS2Point&))const;////////////////////////////////////////////////////////////////////////
// S2Region interface (see s2region.h for details):
S2Loop*Clone()constoverride;// GetRectBound() returns essentially tight results, while GetCapBound()
// might have a lot of extra padding. Both bounds are conservative in that
// if the loop contains a point P, then the bound contains P also.
S2CapGetCapBound()constoverride;S2LatLngRectGetRectBound()constoverride;boolContains(constS2Cell&cell)constoverride;boolMayIntersect(constS2Cell&cell)constoverride;// Return true if the loop contains the given point. Point containment is
// defined such that if the sphere is subdivided into faces (loops), every
// point is contained by exactly one face. This implies that loops do not
// necessarily contain their vertices.
boolContains(constS2Point&p)constoverride;// Generally clients should not use S2Loop::Encode(). Instead they should
// encode an S2Polygon, which unlike this method supports (lossless)
// compression.
voidEncode(Encoder*constencoder)constoverride;// Decode a loop encoded with Encode() or EncodeCompressed(). These methods
// may be called with loops that have already been initialized.
boolDecode(Decoder*constdecoder)override;boolDecodeWithinScope(Decoder*constdecoder)override;};

S2Polygon

An S2Polygon is an S2Region object that represents a polygon. A polygon is
defined by zero or more loops; recall that the interior of a loop is defined to
be its left-hand side (see S2Loop). There are two different conventions for
creating an S2Polygon:

InitNested() expects the input loops to be nested hierarchically. The
polygon interior then consists of the set of points contained by an odd
number of loops. So for example, a circular region with a hole in it would
be defined as two CCW loops, with one loop containing the other. The loops
can be provided in any order.

When the orientation of the input loops is unknown, the nesting requirement
is typically met by calling S2Loop::Normalize() on each loop (which
inverts the loop if necessary so that it encloses at most half the sphere).
But in fact any set of loops can be used as long as (1) there is no pair of
loops that cross, and (2) there is no pair of loops whose union is the
entire sphere.

InitOriented() expects the input loops to be oriented such that the
polygon interior is on the left-hand side of every loop. So for example, a
circular region with a hole in it would be defined using a CCW outer loop
and a CW inner loop. The loop orientations must all be consistent; for
example, it is not valid to have one CCW loop nested inside another CCW
loop, because the region between the two loops is on the left-hand side of
one loop and the right-hand side of the other.

Most clients will not call these methods directly; instead they should use
S2Builder, which has better support for dealing with imperfect data.

When the polygon is initialized, the given loops are automatically converted
into a canonical form consisting of “shells” and “holes”. Shells and holes are
both oriented CCW, and are nested hierarchically. The loops are reordered to
correspond to a preorder traversal of the nesting hierarchy; InitOriented()
may also invert some loops.

Polygons may represent any region of the sphere with a polygonal boundary,
including the entire sphere (known as the “full” polygon). The full polygon
consists of a single full loop (see S2Loop), whereas the empty polygon has no
loops at all.

Polygons have the following restrictions:

Loops may not cross, i.e. the boundary of a loop may not intersect both the
interior and exterior of any other loop.

Loops may not share edges, i.e. if a loop contains an edge AB, then no other
loop may contain AB or BA.

Loops may share vertices, however no vertex may appear twice in a single
loop (see S2Loop).

No loop may be empty. The full loop may appear only in the full polygon.

classS2Polygonfinal:publicS2Region{public:// The default constructor creates an empty polygon. It can be made
// non-empty by calling Init(), Decode(), etc.
S2Polygon();// Convenience constructor that calls InitNested() with the given loops.
// Takes ownership of the loops and clears the vector.
explicitS2Polygon(std::vector<std::unique_ptr<S2Loop>>loops);// Convenience constructor that creates a polygon with a single loop
// corresponding to the given cell.
explicitS2Polygon(constS2Cell&cell);// Convenience constructor that calls Init(unique_ptr<S2Loop>).
explicitS2Polygon(std::unique_ptr<S2Loop>loop);// Destroys the polygon and frees its loops.
~S2Polygon();// Create a polygon from a set of hierarchically nested loops. The polygon
// interior consists of the points contained by an odd number of loops.
// (Recall that a loop contains the set of points on its left-hand side.)
//
// This method takes ownership of the given loops and clears the given
// vector. It then figures out the loop nesting hierarchy and assigns every
// loop a depth. Shells have even depths, and holes have odd depths. Note
// that the loops are reordered so the hierarchy can be traversed more
// easily (see GetParent(), GetLastDescendant(), and S2Loop::depth()).
//
// This method may be called more than once, in which case any existing
// loops are deleted before being replaced by the input loops.
voidInitNested(std::vector<std::unique_ptr<S2Loop>>loops);// Like InitNested(), but expects loops to be oriented such that the polygon
// interior is on the left-hand side of all loops. This implies that shells
// and holes should have opposite orientations in the input to this method.
voidInitOriented(std::vector<std::unique_ptr<S2Loop>>loops);// Initialize a polygon from a single loop. Takes ownership of the loop.
voidInit(std::unique_ptr<S2Loop>loop);// Releases ownership of and returns the loops of this polygon, and resets
// the polygon to be empty.
std::vector<std::unique_ptr<S2Loop>>Release();// Makes a deep copy of the given source polygon. The destination polygon
// will be cleared if necessary.
voidCopy(constS2Polygon*src);// Returns true if this is a valid polygon (including checking whether all
// the loops are themselves valid).
boolIsValid()const;// Returns true if this is *not* a valid polygon and sets "error"
// appropriately. Otherwise returns false and leaves "error" unchanged.
boolFindValidationError(S2Error*error)const;// Return true if this is the empty polygon (consisting of no loops).
boolis_empty()const;// Return true if this is the full polygon (consisting of a single loop that
// encompasses the entire sphere).
boolis_full()const;// Return the number of loops in this polygon.
intnum_loops()const;// Total number of vertices in all loops.
intnum_vertices()const;// Return the loop at the given index. Note that during initialization, the
// given loops are reordered according to a preorder traversal of the loop
// nesting hierarchy. This implies that every loop is immediately followed
// by its descendants. This hierarchy can be traversed using the methods
// GetParent(), GetLastDescendant(), and S2Loop::depth().
constS2Loop*loop(intk)const;S2Loop*loop(intk);// Return the index of the parent of loop k, or -1 if it has no parent.
intGetParent(intk)const;// Return the index of the last loop that is contained within loop k.
intGetLastDescendant(intk)const;// Return the area of the polygon interior, i.e. the region on the left side
// of an odd number of loops. The return value is between 0 and 4*Pi.
doubleGetArea()const;// Return the true centroid of the polygon multiplied by the area of the
// polygon. We prescale by the polygon area for two reasons: (1) it is
// cheaper to compute this way, and (2) it makes it easier to compute the
// centroid of more complicated shapes (by splitting them into disjoint
// regions and adding their centroids).
S2PointGetCentroid()const;// If all of the polygon's vertices happen to be the centers of S2Cells at
// some level, then return that level, otherwise return -1.
intGetSnapLevel()const;// Return the distance from the given point to the polygon interior. If the
// polygon is empty, return S1Angle::Infinity().
S1AngleGetDistance(constS2Point&x)const;// Return the distance from the given point to the polygon boundary. If the
// polygon is empty or full, return S1Angle::Infinity() (since the polygon
// has no boundary).
S1AngleGetDistanceToBoundary(constS2Point&x)const;// Return the overlap fractions between two polygons, i.e. the ratios of the
// area of intersection to the area of each polygon.
staticstd::pair<double,double>GetOverlapFractions(constS2Polygon*a,constS2Polygon*b);// If the given point is contained by the polygon, return it. Otherwise
// return the closest point on the polygon boundary. If the polygon is
// empty, return the input argument.
S2PointProject(constS2Point&x)const;// Return the closest point on the polygon boundary to the given point. If
// the polygon is empty or full, return the input argument (since the
// polygon has no boundary).
S2PointProjectToBoundary(constS2Point&x)const;// Return true if this polygon contains the given other polygon, i.e.
// if polygon A contains all points contained by polygon B.
boolContains(constS2Polygon*b)const;// Returns true if this polgyon (A) approximately contains the given other
// polygon (B). This is true if it is possible to move the vertices of B
// no further than "tolerance" such that A contains the modified B.
//
// For example, the empty polygon will contain any polygon whose maximum
// width is no more than "tolerance".
boolApproxContains(constS2Polygon*b,S1Angletolerance)const;// Return true if this polygon intersects the given other polygon, i.e.
// if there is a point that is contained by both polygons.
boolIntersects(constS2Polygon*b)const;// Returns true if this polgyon (A) and the given polygon (B) are
// approximately disjoint. This is true if it is possible to ensure that A
// and B do not intersect by moving their vertices no further than
// "tolerance".
//
// For example, any polygon is approximately disjoint from a polygon whose
// maximum width is no more than "tolerance".
boolApproxDisjoint(constS2Polygon&b,S1Angletolerance)const;// Initialize this polygon to the intersection, union, difference (A - B),
// or symmetric difference (XOR) of the given two polygons.
//
// "snap_function" allows you to specify a minimum spacing between output
// vertices, and/or that the vertices should be snapped to a discrete set of
// points (e.g. S2CellId centers or E7 lat/lng coordinates). Any snap
// function can be used, including the IdentitySnapFunction with a
// snap_radius of zero (which preserves the input vertices exactly).
voidInitToIntersection(constS2Polygon*a,constS2Polygon*b);voidInitToIntersection(constS2Polygon&a,constS2Polygon&b,constS2Builder::SnapFunction&snap_function);voidInitToUnion(constS2Polygon*a,constS2Polygon*b);voidInitToUnion(constS2Polygon&a,constS2Polygon&b,constS2Builder::SnapFunction&snap_function);voidInitToDifference(constS2Polygon*a,constS2Polygon*b);voidInitToDifference(constS2Polygon&a,constS2Polygon&b,constS2Builder::SnapFunction&snap_function);voidInitToSymmetricDifference(constS2Polygon*a,constS2Polygon*b);voidInitToSymmetricDifference(constS2Polygon&a,constS2Polygon&b,constS2Builder::SnapFunction&snap_function);// Convenience functions that use the IdentitySnapFunction with the given
// snap radius.
voidInitToApproxIntersection(constS2Polygon*a,constS2Polygon*b,S1Anglevertex_merge_radius);voidInitToApproxUnion(constS2Polygon*a,constS2Polygon*b,S1Anglevertex_merge_radius);voidInitToApproxDifference(constS2Polygon*a,constS2Polygon*b,S1Anglevertex_merge_radius);voidInitToApproxSymmetricDifference(constS2Polygon*a,constS2Polygon*b,S1Anglevertex_merge_radius);// Initializes this polygon according to the given "snap_function" and
// reduces the number of vertices if possible, while ensuring that no vertex
// moves further than snap_function.snap_radius().
//
// Simplification works by replacing nearly straight chains of short edges
// with longer edges, in a way that preserves the topology of the input
// polygon up to the creation of degeneracies. This means that loops or
// portions of loops may become degenerate, in which case they are removed.
voidInitToSimplified(constS2Polygon&a,constS2Builder::SnapFunction&snap_function);// Use S2Builder to build this polygon by assembling the edges of a
// given polygon after snapping its vertices to the center of leaf cells at
// the given "snap_level". The default snap level corresponds to a
// tolerance of approximately 1.5cm on the surface of the Earth.
// Such a polygon can be efficiently compressed when serialized.
voidInitToSnapped(constS2Polygon*polygon,intsnap_level=S2CellId::kMaxLevel);// Initialize this polygon to the complement of the given polygon.
voidInitToComplement(constS2Polygon*a);// Invert the polygon (replace it by its complement).
voidInvert();// Intersect this polygon with the polyline "in" and append the resulting
// zero or more polylines to "out" (which must be empty). The polylines
// are appended in the order they would be encountered by traversing "in"
// from beginning to end. Note that the output may include polylines with
// only one vertex, but there will not be any zero-vertex polylines.
std::vector<std::unique_ptr<S2Polyline>>IntersectWithPolyline(constS2Polyline&in)const;// Similar to IntersectWithPolyline(), except that vertices will be
// dropped as necessary to ensure that all adjacent vertices in the
// sequence obtained by concatenating the output polylines will be
// farther than "vertex_merge_radius" apart.
std::vector<std::unique_ptr<S2Polyline>>ApproxIntersectWithPolyline(constS2Polyline&in,S1Anglevertex_merge_radius)const;// Like IntersectWithPolyline, but subtracts this polygon from
// the given polyline.
std::vector<std::unique_ptr<S2Polyline>>SubtractFromPolyline(constS2Polyline&in)const;// Like ApproxIntersectWithPolyline, but subtracts this polygon
// from the given polyline.
std::vector<std::unique_ptr<S2Polyline>>ApproxSubtractFromPolyline(constS2Polyline&in,S1Anglevertex_merge_radius)const;// Return a polygon which is the union of the given polygons.
// Clears the vector and deletes the polygons.
staticstd::unique_ptr<S2Polygon>DestructiveUnion(std::vector<std::unique_ptr<S2Polygon>>polygons);staticstd::unique_ptr<S2Polygon>DestructiveApproxUnion(std::vector<std::unique_ptr<S2Polygon>>polygons,S1Anglevertex_merge_radius);// Initialize this polygon to the outline of the given cell union.
// In principle this polygon should exactly contain the cell union and
// this polygon's inverse should not intersect the cell union, but rounding
// issues may cause this not to be the case.
voidInitToCellUnionBorder(constS2CellUnion&cells);// Return true if every loop of this polygon shares at most one vertex with
// its parent loop. Every polygon has a unique normalized form. Normalized
// polygons are useful for testing since it is easy to compare whether two
// polygons represent the same region.
boolIsNormalized()const;// Return true if two polygons have exactly the same loops. The loops must
// appear in the same order, and corresponding loops must have the same
// linear vertex ordering (i.e., cyclic rotations are not allowed).
boolEquals(constS2Polygon*b)const;// Return true if two polygons have the same boundary. More precisely, this
// method requires that both polygons have loops with the same cyclic vertex
// order and the same nesting hierarchy. (This implies that vertices may be
// cyclically rotated between corresponding loops, and the loop ordering may
// be different between the two polygons as long as the nesting hierarchy is
// the same.)
boolBoundaryEquals(constS2Polygon*b)const;// Return true if two polygons have the same boundary except for vertex
// perturbations. Both polygons must have loops with the same cyclic vertex
// order and the same nesting hierarchy, but the vertex locations are
// allowed to differ by up to "max_error".
boolBoundaryApproxEquals(constS2Polygon&b,S1Anglemax_error=S1Angle::Radians(1e-15))const;// Return true if two polygons have boundaries that are within "max_error"
// of each other along their entire lengths. More precisely, there must be
// a bijection between the two sets of loops such that for each pair of
// loops, "a_loop->BoundaryNear(b_loop)" is true.
boolBoundaryNear(constS2Polygon&b,S1Anglemax_error=S1Angle::Radians(1e-15))const;////////////////////////////////////////////////////////////////////////
// S2Region interface (see s2region.h for details):
// GetRectBound() returns essentially tight results, while GetCapBound()
// might have a lot of extra padding. Both bounds are conservative in that
// if the loop contains a point P, then the bound contains P also.
S2Polygon*Clone()constoverride;S2CapGetCapBound()constoverride;S2LatLngRectGetRectBound()constoverride;boolContains(constS2Cell&cell)constoverride;boolMayIntersect(constS2Cell&cell)constoverride;// Return true if the polygon contains the given point. Point containment
// is defined such that if the sphere is subdivided into polygons, every
// point is contained by exactly one polygons. This implies that polygons
// do not necessarily contain their vertices.
boolContains(constS2Point&p)constoverride;// Encode the polygon with about 4 bytes per vertex, assuming the vertices
// have all been snapped to the centers of S2Cells at a given level
// (typically with InitToSnapped). The other vertices are stored using 24
// bytes. Decoding a polygon encoded this way always returns the original
// polygon, without any loss of precision.
voidEncode(Encoder*constencoder)constoverride;// Decode a polygon encoded with Encode().
boolDecode(Decoder*constdecoder)override;};