Skip to content

Commit c62752d

Browse files
authored
Merge pull request #101 from rahul2393/master
Sync in the last couple years of fixes and updates to the extenal repo.
2 parents c4acd7a + eee7799 commit c62752d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+3108
-869
lines changed

README.md

+131-90
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ S2 is a library for spherical geometry that aims to have the same robustness,
44
flexibility, and performance as the best planar geometry libraries.
55

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

95+
Legend:
96+
97+
* ✅ - Feature Complete
98+
* 🟡 - Mostly Complete
99+
* ❌ - Not available
100+
95101
## [ℝ¹](https://godoc.org/github.com/golang/geo/r1) - One-dimensional Cartesian coordinates
96102

97-
Full parity with C++.
103+
C++ Type | Go
104+
:--------- | ---
105+
R1Interval | ✅
98106

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

101-
Full parity with C++.
109+
C++ Type | Go
110+
:------- | ---
111+
R2Point | ✅
112+
R2Rect | ✅
102113

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

105-
Full parity with C++.
116+
C++ Type | Go
117+
:------------ | ---
118+
R3Vector | ✅
119+
R3ExactVector | ✅
120+
Matrix3x3 | ✅
106121

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

109-
Full parity with C++.
124+
C++ Type | Go
125+
:----------- | ---
126+
S1Angle | ✅
127+
S1ChordAngle | ✅
128+
S1Interval | ✅
110129

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

113-
Approximately ~40% complete.
114-
115-
**Complete** These files have full parity with the C++ implementation.
116-
117-
* Cap
118-
* Cell
119-
* CellID
120-
* CellUnion
121-
* ContainsVertexQuery
122-
* ConvexHullQuery
123-
* CrossingEdgeQuery
124-
* LatLng
125-
* matrix3x3
126-
* Metric
127-
* PaddedCell
128-
* Point
129-
* PointCompression
130-
* Region
131-
* RegionCoverer
132-
* RegionUnion
133-
* s2edge_clipping
134-
* s2edge_crosser
135-
* s2edge_crossings
136-
* s2edge_distances
137-
* edgeVectorShape
138-
* laxLoop
139-
* laxPolyline
140-
* s2projections - Helpers for projecting points between R2 and S2.
141-
* s2rect_bounder
142-
* s2stuv.go (s2coords.h in C++) - This file is a collection of helper and
143-
conversion methods to and from ST-space, UV-space, and XYZ-space.
144-
* s2wedge_relations
145-
* ShapeIndex
146-
* idSetLexicon,sequenceLexicon
147-
148-
**Mostly Complete** Files that have almost all of the features of the original
149-
C++ code, and are reasonably complete enough to use in live code. Up to date
150-
listing of the incomplete methods are documented at the end of each file.
151-
152-
* EdgeQuery/Closest/Furthest - missing Project, GetEdge
153-
* ContainsPointQuery - missing visit edges
154-
* laxPolygon
155-
* Loop - Loop is mostly complete now. Missing Project, Distance, Union, etc.
156-
* Polyline - Missing InitTo... methods, NearlyCoversPolyline
157-
* Rect (AKA s2latlngrect in C++) - Missing Centroid, InteriorContains.
158-
* s2_test.go (AKA s2testing and s2textformat in C++) - Missing Fractal test
159-
shape generation. This file is a collection of testing helper methods.
160-
* s2edge_distances - Missing Intersection
161-
162-
**In Progress** Files that have some work done, but are probably not complete
163-
enough for general use in production code.
164-
165-
* CellIndex - A queryable index of CellIDs.
166-
* Polygon - Polygons with multiple loops are supported. It fully implements
167-
Shape and Region, but it's missing most other methods. (Area, Centroid,
168-
Distance, Projection, Intersection, Union, Contains, Normalized, etc.)
169-
* PolylineSimplifier - Initial work has begun on this.
170-
* s2predicates.go - This file is a collection of helper methods used by other
171-
parts of the library.
172-
* s2shapeutil - Initial elements added. Missing VisitCrossings.
173-
174-
**Not Started Yet.** These files (and their associated unit tests) have
175-
dependencies on most of the In Progress files before they can begin to be
176-
started.
177-
178-
* BooleanOperation - used when assembling polygons and loops.
179-
* Builder - This is a robust tool for creating the various Shape types from
180-
collection of simpler S2 types.
181-
* BuilderClosedSetNormalizer
182-
* BuilderFindPolygonDegneracies
183-
* BuilderGraph
184-
* BuilderLayers
185-
* BuilderSnapFunctions
186-
* BuilderTesting
187-
* Centroids
188-
* ClosestPointQuery
189-
* EdgeTesselator
190-
* LoopMeasures
191-
* PointIndex
192-
* PointRegion
193-
* PointUtil
194-
* PolygonMeasures
195-
* RegionIntersection
196-
* RegionTermIndexer
197-
* ShapeIndexRegion - Allows ShapeIndexes to be used as Regions for things like
132+
### Basic Types
133+
134+
C++ Type | Go
135+
:------------------- | ---
136+
S2Cap | ✅
137+
S2Cell | ✅
138+
S2CellId | ✅
139+
S2CellIdVector | ❌
140+
S2CellIndex | 🟡
141+
S2CellUnion | ✅
142+
S2Coords | ✅
143+
S2DensityTree | ❌
144+
S2DistanceTarget | ✅
145+
S2EdgeVector | ✅
146+
S2LatLng | ✅
147+
S2LatLngRect | ✅
148+
S2LaxLoop | 🟡
149+
S2LaxPolygon | 🟡
150+
S2LaxPolyline | 🟡
151+
S2Loop | ✅
152+
S2PaddedCell | ✅
153+
S2Point | ✅
154+
S2PointIndex | ❌
155+
S2PointSpan | ❌
156+
S2PointRegion | ❌
157+
S2PointVector | ✅
158+
S2Polygon | 🟡
159+
S2Polyline | ✅
160+
S2R2Rect | ❌
161+
S2Region | ✅
162+
S2RegionCoverer | ✅
163+
S2RegionIntersection | ❌
164+
S2RegionUnion | ✅
165+
S2Shape | ✅
166+
S2ShapeIndex | ✅
167+
S2ShapeIndexRegion | ❌
168+
EncodedLaxPolygon | ❌
169+
EncodedLaxPolyline | ❌
170+
EncodedShapeIndex | ❌
171+
EncodedStringVector | ❌
172+
EncodedUintVector | ❌
173+
IdSetLexicon | ❌
174+
ValueSetLexicon | ❌
175+
SequenceLexicon | ❌
176+
LaxClosedPolyline | ❌
177+
VertexIDLaxLoop | ❌
178+
179+
### Query Types
180+
181+
C++ Type | Go
182+
:------------------- | ---
183+
S2ChainInterpolation | ❌
184+
S2ClosestCell | ❌
185+
S2FurthestCell | ❌
186+
S2ClosestEdge | ✅
187+
S2FurthestEdge | ✅
188+
S2ClosestPoint | ❌
189+
S2FurthestPoint | ❌
190+
S2ContainsPoint | ✅
191+
S2ContainsVertex | ✅
192+
S2ConvexHull | ✅
193+
S2CrossingEdge | ✅
194+
S2HausdorffDistance | ❌
195+
S2ShapeNesting | ❌
196+
197+
### Supporting Types
198+
199+
C++ Type | Go
200+
:------------------------------- | ---
201+
S2BooleanOperation | ❌
202+
S2BufferOperation | ❌
203+
S2Builder | ❌
204+
S2BuilderClosedSetNormalizer | ❌
205+
S2BuilderFindPolygonDegeneracies | ❌
206+
S2BuilderGraph | ❌
207+
S2BuilderLayers | ❌
208+
S2BuilderSnapFunctions | ❌
209+
S2BuilderTesting | ❌
210+
S2Builderutil\* | ❌
211+
S2Coder | ❌
212+
S2EdgeClipping | ✅
213+
S2EdgeCrosser | ✅
214+
S2EdgeCrossings | ✅
215+
S2EdgeDistances | ✅
216+
S2EdgeTessellator | ✅
217+
S2LoopMeasures | ❌
218+
S2Measures | ✅
219+
S2MemoryTracker | ❌
220+
S2Metrics | ❌
221+
S2PointUtil | 🟡
222+
S2PolygonBuilder | ❌
223+
S2PolylineAlignment | ❌
224+
S2PolylineMeasures | ✅
225+
S2PolylineSimplifier | ❌
226+
S2Predicates | ✅
227+
S2Projections | ❌
228+
S2rectBounder | ❌
229+
S2RegionTermIndexer | ❌
230+
S2ShapeIndexMeasures | ❌
231+
S2ShapeIndexUtil\* | 🟡
232+
S2ShapeMeasures | ❌
233+
S2ShapeUtil\* | 🟡
234+
S2Stats | ❌
235+
S2Testing | ✅
236+
S2TextFormat | ✅
237+
S2WedgeRelations | ✅
238+
S2WindingOperation | ❌
198239

199240
### Encode/Decode
200241

r1/interval.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ func (i Interval) ApproxEqual(other Interval) bool {
165165

166166
// DirectedHausdorffDistance returns the Hausdorff distance to the given interval. For two
167167
// intervals x and y, this distance is defined as
168-
// h(x, y) = max_{p in x} min_{q in y} d(p, q).
168+
//
169+
// h(x, y) = max_{p in x} min_{q in y} d(p, q).
169170
func (i Interval) DirectedHausdorffDistance(other Interval) float64 {
170171
if i.IsEmpty() {
171172
return 0

r3/precisevector.go

+5
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,8 @@ func (v PreciseVector) SmallestComponent() Axis {
196196
}
197197
return ZAxis
198198
}
199+
200+
// IsZero reports if this vector is exactly 0 efficiently.
201+
func (v PreciseVector) IsZero() bool {
202+
return v.X.Sign() == 0 && v.Y.Sign() == 0 && v.Z.Sign() == 0
203+
}

r3/precisevector_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -473,3 +473,49 @@ func TestPreciseLargestSmallestComponents(t *testing.T) {
473473
}
474474
}
475475
}
476+
477+
func TestPreciseVectorIsZero(t *testing.T) {
478+
479+
x := NewPreciseVector(1e20, 0, 0)
480+
y := NewPreciseVector(1, 0, 0)
481+
xy := x.Add(y)
482+
483+
tests := []struct {
484+
have PreciseVector
485+
want bool
486+
}{
487+
{
488+
have: NewPreciseVector(0, 0, 0),
489+
want: true,
490+
},
491+
{
492+
// Test with one element being negatively signed 0.
493+
have: NewPreciseVector(0, -0, 0),
494+
want: true,
495+
},
496+
{
497+
// Test a non-zero value.
498+
have: NewPreciseVector(0, 0, 1),
499+
want: false,
500+
},
501+
{
502+
// 1e20+1-1e20 should equal 1. Testing the case where the
503+
// numbers are outside the range a traditional double would
504+
// be able to handle correctly.
505+
have: x.Add(y).Add(x.Mul(precFloat(-1))),
506+
want: false,
507+
},
508+
{
509+
// (1e20+1) - (1e20+1) should be zero. Test the same case
510+
// where a non-representable double minus itself is 0.
511+
have: xy.Sub(xy),
512+
want: true,
513+
},
514+
}
515+
516+
for _, test := range tests {
517+
if got := test.have.IsZero(); got != test.want {
518+
t.Errorf("%s.IsZero() = %v, want %v", test.have, got, test.want)
519+
}
520+
}
521+
}

r3/vector.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,16 @@ func (v Vector) Sub(ov Vector) Vector { return Vector{v.X - ov.X, v.Y - ov.Y, v.
6868
func (v Vector) Mul(m float64) Vector { return Vector{m * v.X, m * v.Y, m * v.Z} }
6969

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

7375
// Cross returns the standard cross product of v and ov.
7476
func (v Vector) Cross(ov Vector) Vector {
7577
return Vector{
76-
v.Y*ov.Z - v.Z*ov.Y,
77-
v.Z*ov.X - v.X*ov.Z,
78-
v.X*ov.Y - v.Y*ov.X,
78+
float64(v.Y*ov.Z) - float64(v.Z*ov.Y),
79+
float64(v.Z*ov.X) - float64(v.X*ov.Z),
80+
float64(v.X*ov.Y) - float64(v.Y*ov.X),
7981
}
8082
}
8183

@@ -100,7 +102,7 @@ const (
100102
// Ortho returns a unit vector that is orthogonal to v.
101103
// Ortho(-v) = -Ortho(v) for all v.
102104
func (v Vector) Ortho() Vector {
103-
ov := Vector{0.012, 0.0053, 0.00457}
105+
ov := Vector{}
104106
switch v.LargestComponent() {
105107
case XAxis:
106108
ov.Z = 1
@@ -146,9 +148,9 @@ func (v Vector) SmallestComponent() Axis {
146148

147149
// Cmp compares v and ov lexicographically and returns:
148150
//
149-
// -1 if v < ov
150-
// 0 if v == ov
151-
// +1 if v > ov
151+
// -1 if v < ov
152+
// 0 if v == ov
153+
// +1 if v > ov
152154
//
153155
// This method is based on C++'s std::lexicographical_compare. Two entities
154156
// are compared element by element with the given operator. The first mismatch

r3/vector_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,23 @@ func TestVectorOrtho(t *testing.T) {
261261
}
262262
}
263263

264+
func TestVectorOrthoAlignment(t *testing.T) {
265+
tests := []struct {
266+
have Vector
267+
want Vector
268+
}{
269+
{have: Vector{1, 0, 0}, want: Vector{0, -1, 0}},
270+
{have: Vector{0, 1, 0}, want: Vector{0, 0, -1}},
271+
{have: Vector{0, 0, 1}, want: Vector{-1, 0, 0}},
272+
}
273+
274+
for _, test := range tests {
275+
if got := test.have.Ortho(); got != test.want {
276+
t.Errorf("%v.Ortho() = %v, want %v", test.have, got, test.want)
277+
}
278+
}
279+
}
280+
264281
func TestVectorIdentities(t *testing.T) {
265282
tests := []struct {
266283
v1, v2 Vector

0 commit comments

Comments
 (0)