Skip to content

Commit f222371

Browse files
committed
Avoid unnecessary SimplePolygonXZ constructor checks to improve performance
1 parent 07db7e9 commit f222371

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

core-jvm/src/test/java/org/osm2world/math/shapes/SimplePolygonXZTest.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import static java.lang.Math.sqrt;
44
import static java.util.Arrays.asList;
55
import static org.junit.Assert.*;
6-
import static org.osm2world.math.shapes.SimplePolygonXZ.isSelfIntersecting;
76
import static org.osm2world.math.VectorXZ.NULL_VECTOR;
7+
import static org.osm2world.math.shapes.SimplePolygonXZ.isSelfIntersecting;
88
import static org.osm2world.test.TestUtil.assertAlmostEquals;
99
import static org.osm2world.test.TestUtil.assertSameCyclicOrder;
1010

@@ -18,15 +18,15 @@
1818

1919
public class SimplePolygonXZTest {
2020

21-
private SimplePolygonXZ p1 = new SimplePolygonXZ(asList(
21+
private final SimplePolygonXZ p1 = new SimplePolygonXZ(asList(
2222
new VectorXZ(-1, -1),
2323
new VectorXZ(-1, 0),
2424
new VectorXZ(-1, +1),
2525
new VectorXZ(+1, +1),
2626
new VectorXZ(+1, -1),
2727
new VectorXZ(-1, -1)));
2828

29-
private SimplePolygonXZ p2 = new SimplePolygonXZ(asList(
29+
private final SimplePolygonXZ p2 = new SimplePolygonXZ(asList(
3030
new VectorXZ(-0.5, -0.5),
3131
new VectorXZ(-0.5, +1.5),
3232
new VectorXZ(+1.5, +1.5),
@@ -127,7 +127,7 @@ public void testIsClockwise1() {
127127

128128
assertTrue(new SimplePolygonXZ(outlineA).isClockwise());
129129

130-
List<VectorXZ> outlineAInv = new ArrayList<VectorXZ>(outlineA);
130+
List<VectorXZ> outlineAInv = new ArrayList<>(outlineA);
131131
Collections.reverse(outlineAInv);
132132
assertFalse(new SimplePolygonXZ(outlineAInv).isClockwise());
133133

@@ -138,11 +138,33 @@ public void testIsClockwise2() {
138138

139139
assertTrue(new SimplePolygonXZ(outlineB).isClockwise());
140140

141-
List<VectorXZ> outlineBInv = new ArrayList<VectorXZ>(outlineB);
141+
List<VectorXZ> outlineBInv = new ArrayList<>(outlineB);
142142
Collections.reverse(outlineBInv);
143143
assertFalse(new SimplePolygonXZ(outlineBInv).isClockwise());
144144
}
145145

146+
@Test
147+
public void testMakeCounterclockwise() {
148+
149+
for (List<VectorXZ> outline : List.of(outlineA, outlineB)) {
150+
151+
var poly = new SimplePolygonXZ(outline);
152+
assertTrue(poly.isClockwise());
153+
154+
var polyCCW = poly.makeCounterclockwise();
155+
assertFalse(polyCCW.isClockwise());
156+
assertEquals(poly.getArea(), polyCCW.getArea(), 1e-3);
157+
158+
var polyInv = poly.reverse();
159+
assertFalse(polyInv.isClockwise());
160+
assertEquals(polyCCW, polyInv);
161+
162+
assertEquals(poly, polyInv.reverse());
163+
164+
}
165+
166+
}
167+
146168
@Test
147169
public void testIsClockwise3() {
148170

core/src/main/java/org/osm2world/math/shapes/SimplePolygonXZ.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ public SimplePolygonXZ(List<VectorXZ> vertexLoop) {
5050

5151
}
5252

53+
/**
54+
* Internal alternative to {@link #SimplePolygonXZ(List)} that omits validity checks
55+
* and, optionally, area calculations. This can avoid unnecessary performance costs for known-good data.
56+
*/
57+
private SimplePolygonXZ(List<VectorXZ> vertexLoop, Double signedArea) {
58+
59+
this.vertexLoop = vertexLoop;
60+
61+
if (signedArea != null) {
62+
this.signedArea = signedArea;
63+
this.area = Math.abs(signedArea);
64+
this.clockwise = signedArea < 0;
65+
}
66+
67+
}
68+
5369
public static final SimplePolygonXZ asSimplePolygon(SimpleClosedShapeXZ shape) {
5470
if (shape instanceof SimplePolygonXZ) {
5571
return (SimplePolygonXZ) shape;
@@ -310,9 +326,9 @@ private SimplePolygonXZ makeRotationSense(boolean clockwise) {
310326
}
311327

312328
public SimplePolygonXZ reverse() {
313-
List<VectorXZ> newVertexLoop = new ArrayList<VectorXZ>(vertexLoop);
329+
List<VectorXZ> newVertexLoop = new ArrayList<>(vertexLoop);
314330
Collections.reverse(newVertexLoop);
315-
return new SimplePolygonXZ(newVertexLoop);
331+
return new SimplePolygonXZ(newVertexLoop, -this.signedArea);
316332
}
317333

318334
@Override
@@ -690,7 +706,7 @@ private static void assertNotSelfIntersecting(List<VectorXZ> vertexLoop) {
690706
*/
691707
private static void assertNoDuplicates(List<VectorXZ> vertexLoop) {
692708
for (int i = 0; i < vertexLoop.size() - 1; i++) {
693-
if (vertexLoop.get(i + 1).distanceTo(vertexLoop.get(i)) == 0) {
709+
if (VectorXZ.distanceSquared(vertexLoop.get(i + 1), vertexLoop.get(i)) == 0) {
694710
throw new InvalidGeometryException(
695711
"polygon must not not have duplicate points\n"
696712
+ "Polygon vertices: " + vertexLoop);

0 commit comments

Comments
 (0)