Skip to content

Commit 75271af

Browse files
Merge pull request #297 from aodn/feature/8278-add-polygon-to-email-template
Feature/8278 add polygon to email template
2 parents fa63ea5 + 409fbf6 commit 75271af

2 files changed

Lines changed: 64 additions & 37 deletions

File tree

server/src/main/java/au/org/aodn/ogcapi/server/core/util/EmailUtils.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.io.IOException;
1111
import java.io.InputStream;
1212
import java.math.BigDecimal;
13+
import java.math.RoundingMode;
1314
import java.util.ArrayList;
1415
import java.util.List;
1516
import java.util.Map;
@@ -164,14 +165,13 @@ public static String generateBboxHtml(Object multipolygon, ObjectMapper objectMa
164165
Polygon normalizedPolygon = (Polygon) normalizedBbox.getGeometryN(i);
165166
Envelope envelope = normalizedPolygon.getEnvelopeInternal();
166167

167-
String north = String.valueOf(envelope.getMaxY());
168-
String south = String.valueOf(envelope.getMinY());
169-
String west = String.valueOf(envelope.getMinX());
170-
String east = String.valueOf(envelope.getMaxX());
168+
String north = formatCoordinate(envelope.getMaxY());
169+
String south = formatCoordinate(envelope.getMinY());
170+
String west = formatCoordinate(envelope.getMinX());
171+
String east = formatCoordinate(envelope.getMaxX());
171172

172173
bboxCounter++;
173-
int displayIndex = bboxCounter > 1 ? bboxCounter : 0;
174-
html.append(buildBboxSection(north, south, west, east, displayIndex));
174+
html.append(buildBboxSection(north, south, west, east));
175175
}
176176
}
177177

@@ -231,6 +231,13 @@ public static String generatePolygonHtml(Object multipolygon, ObjectMapper objec
231231
}
232232
}
233233

234+
/**
235+
* Format a coordinate to a fixed 5 decimal places (~1m precision), avoiding scientific notation.
236+
*/
237+
protected static String formatCoordinate(double value) {
238+
return BigDecimal.valueOf(value).setScale(5, RoundingMode.HALF_UP).toPlainString();
239+
}
240+
234241
/**
235242
* Remove the GeoJSON closing point (where the last vertex repeats the first) to get the unique vertices.
236243
*
@@ -583,8 +590,8 @@ protected static String buildPolygonSection(List<List<BigDecimal>> vertices, int
583590
for (int i = 0; i < vertices.size(); i++) {
584591
List<BigDecimal> point = vertices.get(i);
585592
// GeoJSON stores [lon, lat]; display latitude-first per geographic convention.
586-
String lon = point.get(0).toPlainString();
587-
String lat = point.get(1).toPlainString();
593+
String lon = formatCoordinate(point.get(0).doubleValue());
594+
String lat = formatCoordinate(point.get(1).doubleValue());
588595
coordinateRows.append(buildCoordinateRow("Point " + (i + 1) + ": (" + lat + ", " + lon + ")"));
589596
}
590597

@@ -632,8 +639,8 @@ protected static String buildPolygonSection(List<List<BigDecimal>> vertices, int
632639
/**
633640
* Build a bounding box section showing its north, west, south and east bounds
634641
*/
635-
protected static String buildBboxSection(String north, String south, String west, String east, int index) {
636-
String title = index > 0 ? "Bounding Box " + index : "Bounding Box Selection";
642+
protected static String buildBboxSection(String north, String south, String west, String east) {
643+
String title = "Bounding Box Selection";
637644

638645
// Coordinate display order groups the latitude bounds (N, S) then the longitude bounds (W, E).
639646
// Keep this list as the single source of truth for the order.

server/src/test/java/au/org/aodn/ogcapi/server/core/util/EmailUtilsTest.java

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ void testPolygonImageResourceExists() throws IOException {
3939
*/
4040
@Test
4141
void testSingleBbox() {
42-
String html = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0", 0);
42+
String html = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0");
4343

4444
assertTrue(html.contains("Bounding Box Selection"));
4545
assertTrue(html.contains("N: -40.0"));
@@ -53,7 +53,7 @@ void testSingleBbox() {
5353
*/
5454
@Test
5555
void testBboxCoordinateOrder() {
56-
String html = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0", 0);
56+
String html = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0");
5757

5858
int n = html.indexOf("N: -40.0");
5959
int s = html.indexOf("S: -41.0");
@@ -64,49 +64,69 @@ void testBboxCoordinateOrder() {
6464
}
6565

6666
/**
67-
* Test multiple bboxes with numbers
67+
* Test that every bbox always shows "Bounding Box Selection", never a number
6868
*/
6969
@Test
7070
void testMultipleBboxes() {
71-
String html1 = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0", 1);
72-
String html2 = EmailUtils.buildBboxSection("-38.0", "-39.0", "147.0", "148.0", 2);
71+
String html1 = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0");
72+
String html2 = EmailUtils.buildBboxSection("-38.0", "-39.0", "147.0", "148.0");
7373

74-
assertTrue(html1.contains("Bounding Box 1"));
75-
assertTrue(html2.contains("Bounding Box 2"));
74+
assertTrue(html1.contains("Bounding Box Selection"));
75+
assertTrue(html2.contains("Bounding Box Selection"));
76+
assertFalse(html2.contains("Bounding Box 2"));
7677
}
7778

7879
/**
79-
* Test decimal formatting - now tests that original string values are preserved
80+
* Test coordinates are rounded to a fixed 5 decimal places
8081
*/
8182
@Test
82-
void testDecimalFormat() {
83-
String html = EmailUtils.buildBboxSection("-35.12345", "-36.54321", "150.11111", "151.99999", 0);
83+
void testCoordinateRoundsToFiveDecimals() {
84+
assertEquals("-35.12346", EmailUtils.formatCoordinate(-35.123456789));
85+
assertEquals("145.00000", EmailUtils.formatCoordinate(145.0));
86+
}
8487

85-
assertTrue(html.contains("N: -35.12345"));
86-
assertTrue(html.contains("S: -36.54321"));
87-
assertTrue(html.contains("W: 150.11111"));
88-
assertTrue(html.contains("E: 151.99999"));
88+
/**
89+
* Test coordinates never use scientific notation
90+
*/
91+
@Test
92+
void testCoordinateAvoidsScientificNotation() {
93+
assertEquals("0.00000", EmailUtils.formatCoordinate(4.9E-324));
94+
assertEquals("-11.91981", EmailUtils.formatCoordinate(-11.919807423710694));
8995
}
9096

9197
/**
92-
* Test scientific notation values are preserved
98+
* Test that generated bbox HTML rounds high-precision input to 5 decimals with no scientific notation
9399
*/
94100
@Test
95-
void testScientificNotation() {
96-
String html = EmailUtils.buildBboxSection("4.9E-324", "-11.919807423710694", "-45.42305428582753", "4.9E-324", 0);
101+
void testGenerateBboxHtmlRoundsCoordinates() {
102+
Map<String, Object> bbox = Map.of(
103+
"type", "MultiPolygon",
104+
"coordinates", List.of(
105+
List.of(
106+
List.of(
107+
List.of(145.123456789, -40.987654321),
108+
List.of(145.123456789, -41.0),
109+
List.of(146.0, -41.0),
110+
List.of(146.0, -40.987654321),
111+
List.of(145.123456789, -40.987654321)
112+
)
113+
)
114+
)
115+
);
116+
117+
String html = EmailUtils.generateBboxHtml(bbox, new ObjectMapper());
97118

98-
assertTrue(html.contains("N: 4.9E-324"));
99-
assertTrue(html.contains("S: -11.919807423710694"));
100-
assertTrue(html.contains("W: -45.42305428582753"));
101-
assertTrue(html.contains("E: 4.9E-324"));
119+
assertTrue(html.contains("W: 145.12346"));
120+
assertTrue(html.contains("N: -40.98765"));
121+
assertFalse(html.contains("E-"));
102122
}
103123

104124
/**
105125
* Test image placeholder exists
106126
*/
107127
@Test
108128
void testImagePlaceholder() {
109-
String html = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0", 0);
129+
String html = EmailUtils.buildBboxSection("-40.0", "-41.0", "145.0", "146.0");
110130

111131
assertTrue(html.contains("{{BBOX_IMG}}"));
112132
}
@@ -327,8 +347,8 @@ void testSinglePolygon() {
327347
String html = EmailUtils.buildPolygonSection(vertices, 0);
328348

329349
assertTrue(html.contains("Polygon Selection"));
330-
assertTrue(html.contains("Point 1: (-40.0, 145.0)"));
331-
assertTrue(html.contains("Point 5: (-41.0, 144.5)"));
350+
assertTrue(html.contains("Point 1: (-40.00000, 145.00000)"));
351+
assertTrue(html.contains("Point 5: (-41.00000, 144.50000)"));
332352
}
333353

334354
/**
@@ -352,12 +372,12 @@ void testMultiplePolygons() {
352372
}
353373

354374
/**
355-
* Test polygon vertices preserve full precision (no scientific notation)
375+
* Test polygon vertices are rounded to 5 decimals (no scientific notation)
356376
*/
357377
@Test
358378
void testPolygonDecimalFormat() {
359379
List<List<BigDecimal>> vertices = List.of(
360-
List.of(new BigDecimal("150.11111"), new BigDecimal("-35.12345")),
380+
List.of(new BigDecimal("150.123456"), new BigDecimal("-35.123454")),
361381
List.of(new BigDecimal("151.99999"), new BigDecimal("-36.54321")),
362382
List.of(new BigDecimal("152.50000"), new BigDecimal("-37.00001")),
363383
List.of(new BigDecimal("151.00000"), new BigDecimal("-38.00002")),
@@ -366,7 +386,7 @@ void testPolygonDecimalFormat() {
366386

367387
String html = EmailUtils.buildPolygonSection(vertices, 0);
368388

369-
assertTrue(html.contains("Point 1: (-35.12345, 150.11111)"));
389+
assertTrue(html.contains("Point 1: (-35.12345, 150.12346)"));
370390
assertTrue(html.contains("Point 2: (-36.54321, 151.99999)"));
371391
}
372392

0 commit comments

Comments
 (0)