Skip to content

Commit

Permalink
Sync to latest
Browse files Browse the repository at this point in the history
  • Loading branch information
rsned authored and rahul2393 committed Apr 20, 2023
1 parent c4acd7a commit eee7799
Show file tree
Hide file tree
Showing 89 changed files with 3,108 additions and 869 deletions.
221 changes: 131 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ S2 is a library for spherical geometry that aims to have the same robustness,
flexibility, and performance as the best planar geometry libraries.

This is a library for manipulating geometric shapes. Unlike many geometry
libraries, S2 is primarily designed to work with _spherical geometry_, i.e.,
libraries, S2 is primarily designed to work with *spherical geometry*, i.e.,
shapes drawn on a sphere rather than on a planar 2D map. (In fact, the name S2
is derived from the mathematical notation for the unit sphere **.) This makes
it especially suitable for working with geographic data.
Expand Down Expand Up @@ -92,109 +92,150 @@ This library is principally a port of the
where it makes sense. We detail the progress of this port below relative to that
C++ library.

Legend:

* ✅ - Feature Complete
* 🟡 - Mostly Complete
* ❌ - Not available

## [ℝ¹](https://godoc.org/github.com/golang/geo/r1) - One-dimensional Cartesian coordinates

Full parity with C++.
C++ Type | Go
:--------- | ---
R1Interval | ✅

## [ℝ²](https://godoc.org/github.com/golang/geo/r2) - Two-dimensional Cartesian coordinates

Full parity with C++.
C++ Type | Go
:------- | ---
R2Point | ✅
R2Rect | ✅

## [ℝ³](https://godoc.org/github.com/golang/geo/r3) - Three-dimensional Cartesian coordinates

Full parity with C++.
C++ Type | Go
:------------ | ---
R3Vector | ✅
R3ExactVector | ✅
Matrix3x3 | ✅

## [](https://godoc.org/github.com/golang/geo/s1) - Circular Geometry

Full parity with C++.
C++ Type | Go
:----------- | ---
S1Angle | ✅
S1ChordAngle | ✅
S1Interval | ✅

## [](https://godoc.org/github.com/golang/geo/s2) - Spherical Geometry

Approximately ~40% complete.

**Complete** These files have full parity with the C++ implementation.

* Cap
* Cell
* CellID
* CellUnion
* ContainsVertexQuery
* ConvexHullQuery
* CrossingEdgeQuery
* LatLng
* matrix3x3
* Metric
* PaddedCell
* Point
* PointCompression
* Region
* RegionCoverer
* RegionUnion
* s2edge_clipping
* s2edge_crosser
* s2edge_crossings
* s2edge_distances
* edgeVectorShape
* laxLoop
* laxPolyline
* s2projections - Helpers for projecting points between R2 and S2.
* s2rect_bounder
* s2stuv.go (s2coords.h in C++) - This file is a collection of helper and
conversion methods to and from ST-space, UV-space, and XYZ-space.
* s2wedge_relations
* ShapeIndex
* idSetLexicon,sequenceLexicon

**Mostly Complete** Files that have almost all of the features of the original
C++ code, and are reasonably complete enough to use in live code. Up to date
listing of the incomplete methods are documented at the end of each file.

* EdgeQuery/Closest/Furthest - missing Project, GetEdge
* ContainsPointQuery - missing visit edges
* laxPolygon
* Loop - Loop is mostly complete now. Missing Project, Distance, Union, etc.
* Polyline - Missing InitTo... methods, NearlyCoversPolyline
* Rect (AKA s2latlngrect in C++) - Missing Centroid, InteriorContains.
* s2_test.go (AKA s2testing and s2textformat in C++) - Missing Fractal test
shape generation. This file is a collection of testing helper methods.
* s2edge_distances - Missing Intersection

**In Progress** Files that have some work done, but are probably not complete
enough for general use in production code.

* CellIndex - A queryable index of CellIDs.
* Polygon - Polygons with multiple loops are supported. It fully implements
Shape and Region, but it's missing most other methods. (Area, Centroid,
Distance, Projection, Intersection, Union, Contains, Normalized, etc.)
* PolylineSimplifier - Initial work has begun on this.
* s2predicates.go - This file is a collection of helper methods used by other
parts of the library.
* s2shapeutil - Initial elements added. Missing VisitCrossings.

**Not Started Yet.** These files (and their associated unit tests) have
dependencies on most of the In Progress files before they can begin to be
started.

* BooleanOperation - used when assembling polygons and loops.
* Builder - This is a robust tool for creating the various Shape types from
collection of simpler S2 types.
* BuilderClosedSetNormalizer
* BuilderFindPolygonDegneracies
* BuilderGraph
* BuilderLayers
* BuilderSnapFunctions
* BuilderTesting
* Centroids
* ClosestPointQuery
* EdgeTesselator
* LoopMeasures
* PointIndex
* PointRegion
* PointUtil
* PolygonMeasures
* RegionIntersection
* RegionTermIndexer
* ShapeIndexRegion - Allows ShapeIndexes to be used as Regions for things like
### Basic Types

C++ Type | Go
:------------------- | ---
S2Cap | ✅
S2Cell | ✅
S2CellId | ✅
S2CellIdVector | ❌
S2CellIndex | 🟡
S2CellUnion | ✅
S2Coords | ✅
S2DensityTree | ❌
S2DistanceTarget | ✅
S2EdgeVector | ✅
S2LatLng | ✅
S2LatLngRect | ✅
S2LaxLoop | 🟡
S2LaxPolygon | 🟡
S2LaxPolyline | 🟡
S2Loop | ✅
S2PaddedCell | ✅
S2Point | ✅
S2PointIndex | ❌
S2PointSpan | ❌
S2PointRegion | ❌
S2PointVector | ✅
S2Polygon | 🟡
S2Polyline | ✅
S2R2Rect | ❌
S2Region | ✅
S2RegionCoverer | ✅
S2RegionIntersection | ❌
S2RegionUnion | ✅
S2Shape | ✅
S2ShapeIndex | ✅
S2ShapeIndexRegion | ❌
EncodedLaxPolygon | ❌
EncodedLaxPolyline | ❌
EncodedShapeIndex | ❌
EncodedStringVector | ❌
EncodedUintVector | ❌
IdSetLexicon | ❌
ValueSetLexicon | ❌
SequenceLexicon | ❌
LaxClosedPolyline | ❌
VertexIDLaxLoop | ❌

### Query Types

C++ Type | Go
:------------------- | ---
S2ChainInterpolation | ❌
S2ClosestCell | ❌
S2FurthestCell | ❌
S2ClosestEdge | ✅
S2FurthestEdge | ✅
S2ClosestPoint | ❌
S2FurthestPoint | ❌
S2ContainsPoint | ✅
S2ContainsVertex | ✅
S2ConvexHull | ✅
S2CrossingEdge | ✅
S2HausdorffDistance | ❌
S2ShapeNesting | ❌

### Supporting Types

C++ Type | Go
:------------------------------- | ---
S2BooleanOperation | ❌
S2BufferOperation | ❌
S2Builder | ❌
S2BuilderClosedSetNormalizer | ❌
S2BuilderFindPolygonDegeneracies | ❌
S2BuilderGraph | ❌
S2BuilderLayers | ❌
S2BuilderSnapFunctions | ❌
S2BuilderTesting | ❌
S2Builderutil\* | ❌
S2Coder | ❌
S2EdgeClipping | ✅
S2EdgeCrosser | ✅
S2EdgeCrossings | ✅
S2EdgeDistances | ✅
S2EdgeTessellator | ✅
S2LoopMeasures | ❌
S2Measures | ✅
S2MemoryTracker | ❌
S2Metrics | ❌
S2PointUtil | 🟡
S2PolygonBuilder | ❌
S2PolylineAlignment | ❌
S2PolylineMeasures | ✅
S2PolylineSimplifier | ❌
S2Predicates | ✅
S2Projections | ❌
S2rectBounder | ❌
S2RegionTermIndexer | ❌
S2ShapeIndexMeasures | ❌
S2ShapeIndexUtil\* | 🟡
S2ShapeMeasures | ❌
S2ShapeUtil\* | 🟡
S2Stats | ❌
S2Testing | ✅
S2TextFormat | ✅
S2WedgeRelations | ✅
S2WindingOperation | ❌

### Encode/Decode

Expand Down
3 changes: 2 additions & 1 deletion r1/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ func (i Interval) ApproxEqual(other Interval) bool {

// DirectedHausdorffDistance returns the Hausdorff distance to the given interval. For two
// intervals x and y, this distance is defined as
// h(x, y) = max_{p in x} min_{q in y} d(p, q).
//
// h(x, y) = max_{p in x} min_{q in y} d(p, q).
func (i Interval) DirectedHausdorffDistance(other Interval) float64 {
if i.IsEmpty() {
return 0
Expand Down
5 changes: 5 additions & 0 deletions r3/precisevector.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,8 @@ func (v PreciseVector) SmallestComponent() Axis {
}
return ZAxis
}

// IsZero reports if this vector is exactly 0 efficiently.
func (v PreciseVector) IsZero() bool {
return v.X.Sign() == 0 && v.Y.Sign() == 0 && v.Z.Sign() == 0
}
46 changes: 46 additions & 0 deletions r3/precisevector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,49 @@ func TestPreciseLargestSmallestComponents(t *testing.T) {
}
}
}

func TestPreciseVectorIsZero(t *testing.T) {

x := NewPreciseVector(1e20, 0, 0)
y := NewPreciseVector(1, 0, 0)
xy := x.Add(y)

tests := []struct {
have PreciseVector
want bool
}{
{
have: NewPreciseVector(0, 0, 0),
want: true,
},
{
// Test with one element being negatively signed 0.
have: NewPreciseVector(0, -0, 0),
want: true,
},
{
// Test a non-zero value.
have: NewPreciseVector(0, 0, 1),
want: false,
},
{
// 1e20+1-1e20 should equal 1. Testing the case where the
// numbers are outside the range a traditional double would
// be able to handle correctly.
have: x.Add(y).Add(x.Mul(precFloat(-1))),
want: false,
},
{
// (1e20+1) - (1e20+1) should be zero. Test the same case
// where a non-representable double minus itself is 0.
have: xy.Sub(xy),
want: true,
},
}

for _, test := range tests {
if got := test.have.IsZero(); got != test.want {
t.Errorf("%s.IsZero() = %v, want %v", test.have, got, test.want)
}
}
}
18 changes: 10 additions & 8 deletions r3/vector.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,16 @@ func (v Vector) Sub(ov Vector) Vector { return Vector{v.X - ov.X, v.Y - ov.Y, v.
func (v Vector) Mul(m float64) Vector { return Vector{m * v.X, m * v.Y, m * v.Z} }

// Dot returns the standard dot product of v and ov.
func (v Vector) Dot(ov Vector) float64 { return v.X*ov.X + v.Y*ov.Y + v.Z*ov.Z }
func (v Vector) Dot(ov Vector) float64 {
return float64(v.X*ov.X) + float64(v.Y*ov.Y) + float64(v.Z*ov.Z)
}

// Cross returns the standard cross product of v and ov.
func (v Vector) Cross(ov Vector) Vector {
return Vector{
v.Y*ov.Z - v.Z*ov.Y,
v.Z*ov.X - v.X*ov.Z,
v.X*ov.Y - v.Y*ov.X,
float64(v.Y*ov.Z) - float64(v.Z*ov.Y),
float64(v.Z*ov.X) - float64(v.X*ov.Z),
float64(v.X*ov.Y) - float64(v.Y*ov.X),
}
}

Expand All @@ -100,7 +102,7 @@ const (
// Ortho returns a unit vector that is orthogonal to v.
// Ortho(-v) = -Ortho(v) for all v.
func (v Vector) Ortho() Vector {
ov := Vector{0.012, 0.0053, 0.00457}
ov := Vector{}
switch v.LargestComponent() {
case XAxis:
ov.Z = 1
Expand Down Expand Up @@ -146,9 +148,9 @@ func (v Vector) SmallestComponent() Axis {

// Cmp compares v and ov lexicographically and returns:
//
// -1 if v < ov
// 0 if v == ov
// +1 if v > ov
// -1 if v < ov
// 0 if v == ov
// +1 if v > ov
//
// This method is based on C++'s std::lexicographical_compare. Two entities
// are compared element by element with the given operator. The first mismatch
Expand Down
17 changes: 17 additions & 0 deletions r3/vector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,23 @@ func TestVectorOrtho(t *testing.T) {
}
}

func TestVectorOrthoAlignment(t *testing.T) {
tests := []struct {
have Vector
want Vector
}{
{have: Vector{1, 0, 0}, want: Vector{0, -1, 0}},
{have: Vector{0, 1, 0}, want: Vector{0, 0, -1}},
{have: Vector{0, 0, 1}, want: Vector{-1, 0, 0}},
}

for _, test := range tests {
if got := test.have.Ortho(); got != test.want {
t.Errorf("%v.Ortho() = %v, want %v", test.have, got, test.want)
}
}
}

func TestVectorIdentities(t *testing.T) {
tests := []struct {
v1, v2 Vector
Expand Down
Loading

0 comments on commit eee7799

Please sign in to comment.