From f2ca01bc8417ad662e1826f72135fba47e8b9a26 Mon Sep 17 00:00:00 2001 From: Nishant Mehta Date: Fri, 26 Jun 2026 14:39:31 -0400 Subject: [PATCH] Avoid Coordinate allocations in Area and Length sequence computations Area.ofRingSigned(CoordinateSequence) and Length.ofLine(CoordinateSequence) allocated Coordinate objects (three and one respectively) per call via CoordinateSequence.createCoordinate(), purely to read x/y values while iterating. These back Geometry.getArea() and getLength(), which are commonly called in hot paths. Read coordinates through the primitive CoordinateSequence.getX(int)/getY(int) accessors instead. The arithmetic is unchanged (Area still uses the Shoelace formula, caching the y values so each is read once; Length still sums segment hypotenuses), and no Coordinate instances are created. Measured with a ThreadMXBean allocation driver (200k warmed ops): Geometry.getArea 28.5 -> 0 B/op, Geometry.getLength 40 -> 0 B/op. The full jts-core test suite (2294 tests) passes unchanged. Signed-off-by: Nishant Mehta --- .../org/locationtech/jts/algorithm/Area.java | 20 +++++++------------ .../locationtech/jts/algorithm/Length.java | 14 +++++-------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/modules/core/src/main/java/org/locationtech/jts/algorithm/Area.java b/modules/core/src/main/java/org/locationtech/jts/algorithm/Area.java index 386ab8f375..8a0b1469d9 100644 --- a/modules/core/src/main/java/org/locationtech/jts/algorithm/Area.java +++ b/modules/core/src/main/java/org/locationtech/jts/algorithm/Area.java @@ -93,21 +93,15 @@ public static double ofRingSigned(CoordinateSequence ring) * Based on the Shoelace formula. * http://en.wikipedia.org/wiki/Shoelace_formula */ - Coordinate p0 = ring.createCoordinate(); - Coordinate p1 = ring.createCoordinate(); - Coordinate p2 = ring.createCoordinate(); - ring.getCoordinate(0, p1); - ring.getCoordinate(1, p2); - double x0 = p1.x; - p2.x -= x0; + double x0 = ring.getX(0); + double yPrev = ring.getY(0); + double yCurr = ring.getY(1); double sum = 0.0; for (int i = 1; i < n - 1; i++) { - p0.y = p1.y; - p1.x = p2.x; - p1.y = p2.y; - ring.getCoordinate(i + 1, p2); - p2.x -= x0; - sum += p1.x * (p0.y - p2.y); + double yNext = ring.getY(i + 1); + sum += (ring.getX(i) - x0) * (yPrev - yNext); + yPrev = yCurr; + yCurr = yNext; } return sum / 2.0; } diff --git a/modules/core/src/main/java/org/locationtech/jts/algorithm/Length.java b/modules/core/src/main/java/org/locationtech/jts/algorithm/Length.java index 60834051be..8df8b17134 100644 --- a/modules/core/src/main/java/org/locationtech/jts/algorithm/Length.java +++ b/modules/core/src/main/java/org/locationtech/jts/algorithm/Length.java @@ -11,7 +11,6 @@ */ package org.locationtech.jts.algorithm; -import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.math.MathUtil; @@ -38,15 +37,12 @@ public static double ofLine(CoordinateSequence pts) double len = 0.0; - Coordinate p = pts.createCoordinate(); - pts.getCoordinate(0, p); - double x0 = p.x; - double y0 = p.y; - + double x0 = pts.getX(0); + double y0 = pts.getY(0); + for (int i = 1; i < n; i++) { - pts.getCoordinate(i, p); - double x1 = p.x; - double y1 = p.y; + double x1 = pts.getX(i); + double y1 = pts.getY(i); double dx = x1 - x0; double dy = y1 - y0;