Skip to content

Commit 7d86027

Browse files
S2 AuthorsTorreyHoffman
authored andcommitted
Project import generated by Copybara.
PiperOrigin-RevId: 755519727
1 parent 5a90565 commit 7d86027

280 files changed

Lines changed: 57898 additions & 7565 deletions

File tree

Some content is hidden

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

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,50 @@ varying degrees of completeness and maturity. This Java implementation is
5757
heavily used within Google and is generally mature, aside from the newest
5858
features, but is not as complete as C++.
5959

60+
## 2025 Q2 Release Highlights
61+
62+
Over 100 additional classes have been ported from C++, as well as more methods
63+
on existing classes. There have been performance improvements and bug fixes, as
64+
well as many Javadoc improvements. Some changes are not backward compatible.
65+
66+
A few highlights:
67+
68+
* S2Builder, S2BooleanOperation, and supporting classes have been ported from
69+
C++.
70+
71+
* S2RobustCellClipper and its supporting classes have been ported from C++.
72+
73+
* S2ValidationQueries has been ported from C++, with internal classes
74+
S2ValidQuery (for validating that geometry is compatible with
75+
S2BooleanOperation) and S2LegacyValidQuery (for validating that geometry is
76+
compatible with the S2Polygon and S2Polyline isValid() methods).
77+
78+
* S2 now depends on Fastutil (https://fastutil.di.unimi.it/) and Guava's
79+
Truth library (https://truth.dev/).
80+
81+
* S2 used to support three possible projections from cell space to cube space:
82+
linear, tangent, and quadratic. In practice, only quadratic was used, and it
83+
is now the only supported option. See S2Projections.java for more details.
84+
85+
* Many Java assertions that were formerly commented out are now present. These
86+
typically match DCHECKs in the C++ implementation. Work is ongoing to enable
87+
more of these.
88+
89+
* A global boolean "S2.skipAssertions" is provided to allow deliberate
90+
construction of invalid S2 Objects when Java assertions are enabled, for
91+
testing. Use via GeometryTestCase.unsafeCreate() and related methods.
92+
93+
* The "robustCrossProd" implementation is now truly robust.
94+
95+
* An internal "primitives" subpackage provides some low-level collections and
96+
other utility classes. These are not intended to be used by clients. They
97+
may be removed in future releases.
98+
99+
* S2Polyline no longer implements S2Shape directly, but provides a shape()
100+
method. Also, single-vertex S2Polylines are now considered to represent
101+
degenerate lines, which are not empty. When viewed as a S2Shape, they have
102+
one edge with two identical vertices.
103+
60104
## 2022 Q4 Release Highlights
61105

62106
Many improvements have been made to the Java implementation of S2 since the last

benchmarks/pom.xml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@
4343
<version>${project.parent.version}</version>
4444
</dependency>
4545

46-
<dependency>
47-
<groupId>com.google.geometry</groupId>
48-
<artifactId>s2-geometry-testdatagenerator</artifactId>
49-
<version>${project.parent.version}</version>
50-
</dependency>
51-
5246
<dependency>
5347
<groupId>org.openjdk.jmh</groupId>
5448
<artifactId>jmh-core</artifactId>

benchmarks/src/com/google/common/geometry/BestEdgesBenchmarkHarness.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,14 @@
1515
*/
1616
package com.google.common.geometry.benchmarks;
1717

18-
import static com.google.common.geometry.S2Projections.PROJ;
18+
import static com.google.common.geometry.S2Projections.MAX_DIAG;
1919
import static com.google.common.geometry.TestDataGenerator.kmToAngle;
2020
import static java.util.concurrent.TimeUnit.MICROSECONDS;
2121
import static java.util.concurrent.TimeUnit.SECONDS;
2222

2323
import com.google.common.geometry.PrimitiveArrays.Bytes;
2424
import com.google.common.geometry.PrimitiveArrays.Cursor;
2525
import com.google.common.geometry.S1Angle;
26-
import com.google.common.geometry.S1ChordAngle;
27-
import com.google.common.geometry.S2BestDistanceTarget;
28-
import com.google.common.geometry.S2BestEdgesQueryBase;
2926
import com.google.common.geometry.S2Cap;
3027
import com.google.common.geometry.S2Cell;
3128
import com.google.common.geometry.S2CellId;
@@ -84,12 +81,6 @@ public abstract static class BestEdgeQueryWithTargets {
8481
// The number of edges in 'index'. Stored here to avoid repeated counting.
8582
public int numIndexEdges;
8683

87-
// The query built on the index.
88-
public abstract S2BestEdgesQueryBase<S1ChordAngle> query();
89-
90-
// Targets to query against the index.
91-
public abstract ArrayList<? extends S2BestDistanceTarget<S1ChordAngle>> targets();
92-
9384
// If the index is encoded, this is the list of shapes in it, which are encoded separately.
9485
public List<S2Shape> shapes;
9586
}
@@ -379,7 +370,7 @@ protected S2Cell getTargetCell(BestEdgeQueryWithTargets output, S2Cap targetCap)
379370
chooseTargetFromIndex
380371
? data.sampleCell(output.index)
381372
: S2CellId.fromPoint(targetCap.axis())
382-
.parent(PROJ.maxDiag.getClosestLevel(targetCap.radius().radians()));
373+
.parent(MAX_DIAG.getClosestLevel(targetCap.radius().radians()));
383374
return new S2Cell(cellId);
384375
}
385376

@@ -410,7 +401,7 @@ protected S2ShapeIndex getTargetIndex(BestEdgeQueryWithTargets output, S2Cap tar
410401
targetIndex = factory.getShape(targetCap, numTargetEdges);
411402
}
412403

413-
targetIndex.iterator(); // Force an index build.
404+
targetIndex.applyUpdates();
414405
return targetIndex;
415406
}
416407

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2024 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.common.geometry.benchmarks;
17+
18+
import static java.util.concurrent.TimeUnit.NANOSECONDS;
19+
import static java.util.concurrent.TimeUnit.SECONDS;
20+
21+
import com.google.common.geometry.primitives.DisjointSet;
22+
import org.openjdk.jmh.annotations.Benchmark;
23+
import org.openjdk.jmh.annotations.BenchmarkMode;
24+
import org.openjdk.jmh.annotations.Level;
25+
import org.openjdk.jmh.annotations.Measurement;
26+
import org.openjdk.jmh.annotations.Mode;
27+
import org.openjdk.jmh.annotations.OutputTimeUnit;
28+
import org.openjdk.jmh.annotations.Param;
29+
import org.openjdk.jmh.annotations.Scope;
30+
import org.openjdk.jmh.annotations.Setup;
31+
import org.openjdk.jmh.annotations.State;
32+
import org.openjdk.jmh.annotations.Warmup;
33+
34+
/**
35+
* Benchmark for {@link DisjointSet}.
36+
*/
37+
public final class DisjointSetBenchmark {
38+
39+
private DisjointSetBenchmark() { }
40+
41+
/** Benchmark state that sets up a disjoint set with consecutive Integer values. */
42+
@State(Scope.Thread)
43+
@BenchmarkMode(Mode.AverageTime)
44+
@OutputTimeUnit(NANOSECONDS)
45+
@Warmup(iterations = 3, time = 5, timeUnit = SECONDS)
46+
@Measurement(iterations = 5, time = 5, timeUnit = SECONDS)
47+
public static class ConsecutiveIntegerState extends S2BenchmarkBaseState {
48+
@Param({"64", "512", "4096", "32768", "262144"})
49+
int numElements;
50+
51+
private final DisjointSet<Integer> set = new DisjointSet<>(numElements);
52+
53+
@Setup(Level.Trial)
54+
@Override
55+
public void setup() {
56+
super.setup();
57+
}
58+
59+
/**
60+
* Measures the amount of time it takes to add numElements, union consecutive sets together, and
61+
* then find the root of the first element. Equivalent to BM_FindRoot in the C++ implementation.
62+
*/
63+
@Benchmark
64+
public int findRoot() {
65+
set.clear();
66+
for (int i = 0; i < numElements; i++) {
67+
set.add(i);
68+
}
69+
for (int i = 0; i < numElements; i++) {
70+
set.union(i, i + 1);
71+
}
72+
73+
return set.findRoot(1);
74+
}
75+
}
76+
}

benchmarks/src/com/google/common/geometry/S2Benchmark.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.google.common.geometry.S2Cap;
2424
import com.google.common.geometry.S2Point;
2525
import com.google.common.geometry.TestDataGenerator;
26-
import java.io.IOException;
2726
import org.openjdk.jmh.annotations.Benchmark;
2827
import org.openjdk.jmh.annotations.BenchmarkMode;
2928
import org.openjdk.jmh.annotations.Level;
@@ -65,7 +64,7 @@ public static class AngleState extends S2BenchmarkBaseState {
6564

6665
@Setup(Level.Trial)
6766
@Override
68-
public void setup() throws IOException {
67+
public void setup() {
6968
super.setup();
7069
a = data.getRandomPoint();
7170
S2Cap sampleCapNearParallel = S2Cap.fromAxisAngle(a, capSize);

benchmarks/src/com/google/common/geometry/S2BenchmarkBaseState.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public class S2BenchmarkBaseState {
4545
* Reinitializes the TestDataGenerator, which reinitializes the contained Random to a known state.
4646
* This is equivalent to calling data.resetSeed().
4747
*/
48-
public void setup() throws IOException {
48+
public void setup() {
4949
data = new TestDataGenerator();
5050
}
5151

@@ -81,7 +81,6 @@ public abstract static class ContainsPointBaseState extends S2BenchmarkBaseState
8181
protected static final int NUM_QUERY_SAMPLES = 10;
8282
protected static final int NUM_POLYGONS = 5;
8383

84-
protected boolean preindexOption;
8584
protected List<S2Polygon> polygons = new ArrayList<>(NUM_POLYGONS);
8685
protected List<List<S2Point>> queries = new ArrayList<>(NUM_POLYGONS);
8786
protected int polygonIndex;
@@ -97,8 +96,6 @@ protected void setupPolygonsAndQueries(
9796
int totalNumVertices,
9897
boolean preindexOption)
9998
throws IOException {
100-
// Saved so subclasses can use it to index their polygons.
101-
this.preindexOption = preindexOption;
10299
polygons.clear();
103100
queries.clear();
104101

@@ -149,7 +146,6 @@ protected S2Point currentQuery() {
149146
*/
150147
public abstract static class PolygonListState extends S2BenchmarkBaseState {
151148
protected static final int NUM_POLYGONS = 10;
152-
protected boolean preindexOption;
153149
protected ArrayList<S2Polygon> polygons = new ArrayList<>(NUM_POLYGONS);
154150
protected ArrayList<S2Polygon> copies = new ArrayList<>(NUM_POLYGONS);
155151
protected ArrayList<S2Polygon> bounds = new ArrayList<>(NUM_POLYGONS);
@@ -163,7 +159,6 @@ protected void setupPolygons(
163159
boolean preindexOption)
164160
throws IOException {
165161
super.setup();
166-
this.preindexOption = preindexOption;
167162

168163
polygons.clear();
169164
copies.clear();

0 commit comments

Comments
 (0)