Package com.google.common.geometry
Class S2EdgeUtil
- java.lang.Object
-
- com.google.common.geometry.S2EdgeUtil
-
@GwtCompatible(serializable=false) public class S2EdgeUtil extends Object
This class contains various utility functions related to edges. It collects together common code that is needed to implement polygonal geometry such as polylines, loops, and general polygons.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classS2EdgeUtil.EdgeCrosserUsed to efficiently test a fixed edge AB against an edge chain.static classS2EdgeUtil.LongitudePrunerThe purpose of this class is to find edges that intersect a given longitude interval.static classS2EdgeUtil.RectBounderThis class computes a bounding rectangle that contains all edges defined by a vertex chain v0, v1, v2, ...static classS2EdgeUtil.WedgeContainsReturns true if wedge A contains wedge B.static classS2EdgeUtil.WedgeContainsOrCrossesstatic classS2EdgeUtil.WedgeContainsOrIntersectsstatic classS2EdgeUtil.WedgeIntersectsReturns true if wedge A intersects wedge B.static interfaceS2EdgeUtil.WedgeProcessorWedge processors are used to determine the local relationship between two polygons that share a common vertex.static classS2EdgeUtil.XYZPrunerThe purpose of this class is to find edges that intersect a given XYZ bounding box.
-
Field Summary
Fields Modifier and Type Field Description static S1AngleDEFAULT_INTERSECTION_TOLERANCEIEEE floating-point operations have a maximum error of 0.5 ULPS (units in the last place).static doubleEDGE_CLIP_ERROR_UV_COORDThe maximum error in a clipped point's u- or v-coordinate compared to the exact result, assuming that the points A and B are in the rectangle [-1,1]x[1,1] or slightly outside it (by 1e-10 or less).static doubleEDGE_CLIP_ERROR_UV_DISTThe maximum error between a clipped edge or boundary point and the corresponding exact result.static doubleFACE_CLIP_ERROR_RADIANSThe maximum angle between a returned vertex and the nearest point on the exact edge AB.static doubleFACE_CLIP_ERROR_UV_COORDThe same angle asFACE_CLIP_ERROR_RADIANS, expressed as the maximum error in an individual u- or v-coordinate.static doubleFACE_CLIP_ERROR_UV_DISTThe same angle asFACE_CLIP_ERROR_RADIANS, expressed as a maximum distance in (u,v)-space.static doubleINTERSECTION_ERRORINTERSECTION_ERROR can be set somewhat arbitrarily, because the algorithm uses more precision than necessary in order to achieve the specified error.static doubleINTERSECTS_RECT_ERROR_UV_DISTThe maximum error in IntersectRect.static doubleMAX_CELL_EDGE_ERRORMax error allowed when checking if a loop boundary approximately intersects a target cell
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static booleanclipToFace(S2Point a, S2Point b, int face, R2Vector aUv, R2Vector bUv)Given an edge AB and a face, return the (u,v) coordinates for the portion of AB that intersects that face.static booleanclipToPaddedFace(S2Point aXyz, S2Point bXyz, int face, double padding, R2Vector aUv, R2Vector bUv)AsclipToFace(S2Point, S2Point, int, R2Vector, R2Vector), but rather than clipping to the square [-1,1]x[-1,1] in (u,v) space, this method clips to [-R,R]x[-R,R] where R=(1+padding).static booleanedgeOrVertexCrossing(S2Point a, S2Point b, S2Point c, S2Point d)A convenience function that calls robustCrossing() to handle cases where all four vertices are distinct, and VertexCrossing() to handle cases where two or more vertices are the same.static S2PointgetClosestPoint(S2Point x, S2Point a, S2Point b)Returns the point on edge AB closest to X.static S2PointgetClosestPoint(S2Point x, S2Point a, S2Point b, S2Point aCrossB)AsgetClosestPoint(S2Point, S2Point, S2Point), but faster if the cross product between a and b has already been computed.static S1ChordAnglegetDistance(S2Point p, S2Edge e)Gets the distance fromptoe.static S1AnglegetDistance(S2Point x, S2Point a, S2Point b)Return the minimum distance from X to any point on the edge AB.static S1AnglegetDistance(S2Point x, S2Point a, S2Point b, S2Point aCrossB)A slightly more efficient version of getDistance() where the cross product of the two endpoints has been precomputed.static doublegetDistanceFraction(S2Point x, S2Point a0, S2Point a1)Given a point X and an edge AB, return the distance ratio AX / (AX + BX).static doublegetDistanceRadians(S2Point x, S2Point a, S2Point b, S2Point aCrossB)A more efficient version of getDistance() where the cross product of the endpoints has been precomputed and the result is returned as a direct radian measure rather than wrapping it in an S1Angle.static S1ChordAnglegetEdgePairDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1)Gets distance between edges with no minimum distance.static S1ChordAnglegetEdgePairMaxDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1, S1ChordAngle maxDist)LikeupdateMaxDistance(com.google.common.geometry.S2Point, com.google.common.geometry.S2Point, com.google.common.geometry.S2Point, com.google.common.geometry.S1ChordAngle), but computes the maximum distance between the given pair of edges.static S1ChordAnglegetEdgePairMinDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1, S1ChordAngle minDist)LikeupdateMinDistance(com.google.common.geometry.S2Point, com.google.common.geometry.S2Edge, com.google.common.geometry.S1ChordAngle), but computes the minimum distance between the given pair of edges.static S2PointgetIntersection(S2Point a0, S2Point a1, S2Point b0, S2Point b1)Given two edges AB and CD such that robustCrossing() is true, return their intersection point.static com.google.common.geometry.S2EdgeUtil.WedgeRelationgetWedgeRelation(S2Point a0, S2Point ab1, S2Point a2, S2Point b0, S2Point b2)Returns the relation from wedge A to B.static S2Pointinterpolate(double t, S2Point a, S2Point b)Return the point X along the line segment AB whose distance from A is the given fraction "t" of the distance AB.static S2PointinterpolateAtDistance(S1Angle ax, S2Point a, S2Point b)Likeinterpolate(double, com.google.common.geometry.S2Point, com.google.common.geometry.S2Point), except that the parameter "ax" represents the desired distance from A to the result X rather than a fraction between 0 and 1.static S2PointinterpolateAtDistance(S1Angle ax, S2Point a, S2Point b, S1Angle ab)A slightly more efficient version ofinterpolateAtDistance(com.google.common.geometry.S1Angle, com.google.common.geometry.S2Point, com.google.common.geometry.S2Point, com.google.common.geometry.S1Angle)that can be used when the distance AB is already known.static booleanlenientCrossing(S2Point a, S2Point b, S2Point c, S2Point d)Returns true if ab possibly crosses cd, by clipping tiny angles to zero.static introbustCrossing(S2Point a, S2Point b, S2Point c, S2Point d)Like SimpleCrossing, except that points that lie exactly on a line are arbitrarily classified as being on one side or the other (according to the rules of sign).static booleansimpleCrossing(S2Point a, S2Point b, S2Point c, S2Point d)Return true if edge AB crosses CD at a point that is interior to both edges.static S1ChordAngleupdateMaxDistance(S2Point x, S2Point a, S2Point b, S1ChordAngle maxDistance)Returns the maximum of the distance fromxto any point on edge AB and the givenmaxDistance.static S1ChordAngleupdateMinDistance(S2Point p, S2Edge e, S1ChordAngle minDistance)Gets the minimum of the distance fromatoeandminDistance.static S1ChordAngleupdateMinDistance(S2Point x, S2Point a, S2Point b, S1ChordAngle minDistance)Return the minimum of the distance fromxto any point on edge ab and the givenminDistance.static booleanvertexCrossing(S2Point a, S2Point b, S2Point c, S2Point d)Given two edges AB and CD where at least two vertices are identical (i.e.
-
-
-
Field Detail
-
DEFAULT_INTERSECTION_TOLERANCE
public static final S1Angle DEFAULT_INTERSECTION_TOLERANCE
IEEE floating-point operations have a maximum error of 0.5 ULPS (units in the last place). For double-precision numbers, this works out to 2**-53 (about 1.11e-16) times the magnitude of the result. It is possible to analyze the calculation done by getIntersection() and work out the worst-case rounding error. I have done a rough version of this, and my estimate is that the worst case distance from the intersection point X to the great circle through (a0, a1) is about 12 ULPS, or about 1.3e-15. This needs to be increased by a factor of (1/0.866) to account for the edgeSpliceFraction() in S2PolygonBuilder. Note that the maximum error measured by the unittest in 1,000,000 trials is less than 3e-16.
-
FACE_CLIP_ERROR_RADIANS
public static final double FACE_CLIP_ERROR_RADIANS
The maximum angle between a returned vertex and the nearest point on the exact edge AB. It is equal to the maximum directional error inS2.robustCrossProd(com.google.common.geometry.S2Point, com.google.common.geometry.S2Point), plus the error when projecting points onto a cube face.
-
FACE_CLIP_ERROR_UV_DIST
public static final double FACE_CLIP_ERROR_UV_DIST
The same angle asFACE_CLIP_ERROR_RADIANS, expressed as a maximum distance in (u,v)-space. In other words, a returned vertex is at most this far from the exact edge AB projected into (u,v)-space.
-
FACE_CLIP_ERROR_UV_COORD
public static final double FACE_CLIP_ERROR_UV_COORD
The same angle asFACE_CLIP_ERROR_RADIANS, expressed as the maximum error in an individual u- or v-coordinate. In other words, for each returned vertex there is a point on the exact edge AB whose u- and v-coordinates differ from the vertex by at most this amount.
-
INTERSECTS_RECT_ERROR_UV_DIST
public static final double INTERSECTS_RECT_ERROR_UV_DIST
The maximum error in IntersectRect. If some point of AB is inside the rectangle by at least this distance, the result is guaranteed to be true; if all points of AB are outside the rectangle by at least this distance, the result is guaranteed to be false. This bound assumes that "rect" is a subset of the rectangle [-1,1]x[-1,1] or extends slightly outside it (e.g., by 1e-10 or less).
-
EDGE_CLIP_ERROR_UV_COORD
public static final double EDGE_CLIP_ERROR_UV_COORD
The maximum error in a clipped point's u- or v-coordinate compared to the exact result, assuming that the points A and B are in the rectangle [-1,1]x[1,1] or slightly outside it (by 1e-10 or less).
-
EDGE_CLIP_ERROR_UV_DIST
public static final double EDGE_CLIP_ERROR_UV_DIST
The maximum error between a clipped edge or boundary point and the corresponding exact result. It is equal to the error in a single coordinate because at most one coordinate is subject to error.
-
MAX_CELL_EDGE_ERROR
public static final double MAX_CELL_EDGE_ERROR
Max error allowed when checking if a loop boundary approximately intersects a target cell
-
INTERSECTION_ERROR
public static final double INTERSECTION_ERROR
INTERSECTION_ERROR can be set somewhat arbitrarily, because the algorithm uses more precision than necessary in order to achieve the specified error. The only strict requirement is that INTERSECTION_ERROR >= 2 * S2.DBL_EPSILON radians. However, using a larger error tolerance makes the algorithm more efficient because it reduces the number of cases where exact arithmetic is needed.
-
-
Method Detail
-
getWedgeRelation
public static com.google.common.geometry.S2EdgeUtil.WedgeRelation getWedgeRelation(S2Point a0, S2Point ab1, S2Point a2, S2Point b0, S2Point b2)
Returns the relation from wedge A to B.
-
clipToPaddedFace
public static boolean clipToPaddedFace(S2Point aXyz, S2Point bXyz, int face, double padding, R2Vector aUv, R2Vector bUv)
AsclipToFace(S2Point, S2Point, int, R2Vector, R2Vector), but rather than clipping to the square [-1,1]x[-1,1] in (u,v) space, this method clips to [-R,R]x[-R,R] where R=(1+padding).
-
clipToFace
public static boolean clipToFace(S2Point a, S2Point b, int face, R2Vector aUv, R2Vector bUv)
Given an edge AB and a face, return the (u,v) coordinates for the portion of AB that intersects that face. This method guarantees that the clipped vertices lie within the [-1,1]x[-1,1] cube face rectangle and are within kFaceClipErrorUVDist of the line AB, but the results may differ from those produced by getFaceSegments. Returns false if AB does not intersect the given face.
-
simpleCrossing
public static boolean simpleCrossing(S2Point a, S2Point b, S2Point c, S2Point d)
Return true if edge AB crosses CD at a point that is interior to both edges. Properties:- simpleCrossing(b,a,c,d) == simpleCrossing(a,b,c,d)
- simpleCrossing(c,d,a,b) == simpleCrossing(a,b,c,d)
-
robustCrossing
public static int robustCrossing(S2Point a, S2Point b, S2Point c, S2Point d)
Like SimpleCrossing, except that points that lie exactly on a line are arbitrarily classified as being on one side or the other (according to the rules of sign). It returns +1 if there is a crossing, -1 if there is no crossing, and 0 if any two vertices from different edges are the same. Returns 0 or -1 if either edge is degenerate. Properties of robustCrossing:- robustCrossing(b,a,c,d) == robustCrossing(a,b,c,d)
- robustCrossing(c,d,a,b) == robustCrossing(a,b,c,d)
- robustCrossing(a,b,c,d) == 0 if a==c, a==d, b==c, b==d
- robustCrossing(a,b,c,d) <= 0 if a==b or c==d
Note that if you want to check an edge against a *chain* of other edges, it is much more efficient to use an EdgeCrosser (above).
-
vertexCrossing
public static boolean vertexCrossing(S2Point a, S2Point b, S2Point c, S2Point d)
Given two edges AB and CD where at least two vertices are identical (i.e. robustCrossing(a,b,c,d) == 0), this function defines whether the two edges "cross" in a such a way that point-in-polygon containment tests can be implemented by counting the number of edge crossings. The basic rule is that a "crossing" occurs if AB is encountered after CD during a CCW sweep around the shared vertex starting from a fixed reference point.Note that according to this rule, if AB crosses CD then in general CD does not cross AB. However, this leads to the correct result when counting polygon edge crossings. For example, suppose that A,B,C are three consecutive vertices of a CCW polygon. If we now consider the edge crossings of a segment BP as P sweeps around B, the crossing number changes parity exactly when BP crosses BA or BC.
Useful properties of VertexCrossing (VC):
- VC(a,a,c,d) == VC(a,b,c,c) == false
- VC(a,b,a,b) == VC(a,b,b,a) == true
- VC(a,b,c,d) == VC(a,b,d,c) == VC(b,a,c,d) == VC(b,a,d,c)
- If exactly one of a,b equals one of c,d, then exactly one of VC(a,b,c,d) and VC(c,d,a,b) is true
It is an error to call this method with 4 distinct vertices.
-
edgeOrVertexCrossing
public static boolean edgeOrVertexCrossing(S2Point a, S2Point b, S2Point c, S2Point d)
A convenience function that calls robustCrossing() to handle cases where all four vertices are distinct, and VertexCrossing() to handle cases where two or more vertices are the same. This defines a crossing function such that point-in-polygon containment tests can be implemented by simply counting edge crossings.
-
lenientCrossing
public static final boolean lenientCrossing(S2Point a, S2Point b, S2Point c, S2Point d)
Returns true if ab possibly crosses cd, by clipping tiny angles to zero.
-
getIntersection
public static S2Point getIntersection(S2Point a0, S2Point a1, S2Point b0, S2Point b1)
Given two edges AB and CD such that robustCrossing() is true, return their intersection point. Useful properties of getIntersection (GI):- GI(b,a,c,d) == GI(a,b,d,c) == GI(a,b,c,d)
- GI(c,d,a,b) == GI(a,b,c,d)
-
getDistanceFraction
public static double getDistanceFraction(S2Point x, S2Point a0, S2Point a1)
Given a point X and an edge AB, return the distance ratio AX / (AX + BX). If X happens to be on the line segment AB, this is the fraction "t" such that X == Interpolate(A, B, t). Requires that A and B are distinct.
-
getDistance
public static S1Angle getDistance(S2Point x, S2Point a, S2Point b)
Return the minimum distance from X to any point on the edge AB. The result is very accurate for small distances but may have some numerical error if the distance is large (approximately Pi/2 or greater). The case A == B is handled correctly.- Throws:
IllegalArgumentException- Thrown if the parameters are not all unit length.
-
getDistance
public static S1ChordAngle getDistance(S2Point p, S2Edge e)
Gets the distance fromptoe.
-
updateMinDistance
public static S1ChordAngle updateMinDistance(S2Point p, S2Edge e, S1ChordAngle minDistance)
Gets the minimum of the distance fromatoeandminDistance.
-
updateMinDistance
public static S1ChordAngle updateMinDistance(S2Point x, S2Point a, S2Point b, S1ChordAngle minDistance)
Return the minimum of the distance fromxto any point on edge ab and the givenminDistance. The casea.equals(b)is handled correctly.- Throws:
IllegalArgumentException- Thrown if the parameters are not all unit length.
-
updateMaxDistance
public static S1ChordAngle updateMaxDistance(S2Point x, S2Point a, S2Point b, S1ChordAngle maxDistance)
Returns the maximum of the distance fromxto any point on edge AB and the givenmaxDistance. The casea.equals(b)is handled correctly.
-
getEdgePairMinDistance
public static S1ChordAngle getEdgePairMinDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1, S1ChordAngle minDist)
LikeupdateMinDistance(com.google.common.geometry.S2Point, com.google.common.geometry.S2Edge, com.google.common.geometry.S1ChordAngle), but computes the minimum distance between the given pair of edges. (If the two edges cross, the distance is zero.) The casesa0.equals(a1)andb0.equals(b1)are handled correctly.
-
getEdgePairDistance
public static S1ChordAngle getEdgePairDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1)
Gets distance between edges with no minimum distance.
-
getEdgePairMaxDistance
public static S1ChordAngle getEdgePairMaxDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1, S1ChordAngle maxDist)
LikeupdateMaxDistance(com.google.common.geometry.S2Point, com.google.common.geometry.S2Point, com.google.common.geometry.S2Point, com.google.common.geometry.S1ChordAngle), but computes the maximum distance between the given pair of edges. If the two edges cross, the distance is zero. The casesa0.equals(a1)andb0.equals(b1)are handled correctly.
-
getDistance
public static S1Angle getDistance(S2Point x, S2Point a, S2Point b, S2Point aCrossB)
A slightly more efficient version of getDistance() where the cross product of the two endpoints has been precomputed. The cross product does not need to be normalized, but should be computed using S2.robustCrossProd() for the most accurate results.- Throws:
IllegalArgumentException- Thrown if the parameters are not all unit length.
-
getDistanceRadians
public static double getDistanceRadians(S2Point x, S2Point a, S2Point b, S2Point aCrossB)
A more efficient version of getDistance() where the cross product of the endpoints has been precomputed and the result is returned as a direct radian measure rather than wrapping it in an S1Angle. This is the recommended method for making large numbers of back-to-back edge distance tests, since it allocates no objects. The inputs are assumed to be unit length; results are undefined if they are not.
-
getClosestPoint
public static S2Point getClosestPoint(S2Point x, S2Point a, S2Point b, S2Point aCrossB)
AsgetClosestPoint(S2Point, S2Point, S2Point), but faster if the cross product between a and b has already been computed. All points must be unit length; results are undefined if that is not the case.
-
getClosestPoint
public static S2Point getClosestPoint(S2Point x, S2Point a, S2Point b)
Returns the point on edge AB closest to X. All points must be unit length; results are undefined if that is not the case.
-
interpolateAtDistance
public static S2Point interpolateAtDistance(S1Angle ax, S2Point a, S2Point b, S1Angle ab)
A slightly more efficient version ofinterpolateAtDistance(com.google.common.geometry.S1Angle, com.google.common.geometry.S2Point, com.google.common.geometry.S2Point, com.google.common.geometry.S1Angle)that can be used when the distance AB is already known. Requires that all vectors have unit length.
-
interpolateAtDistance
public static S2Point interpolateAtDistance(S1Angle ax, S2Point a, S2Point b)
Likeinterpolate(double, com.google.common.geometry.S2Point, com.google.common.geometry.S2Point), except that the parameter "ax" represents the desired distance from A to the result X rather than a fraction between 0 and 1. Requires thataandbare unit length.
-
interpolate
public static S2Point interpolate(double t, S2Point a, S2Point b)
Return the point X along the line segment AB whose distance from A is the given fraction "t" of the distance AB. Does NOT require that "t" be between 0 and 1. Note that all distances are measured on the surface of the sphere, so this is more complicated than just computing (1-t)*a + t*b and normalizing the result.
-
-