Skip to content

Commit f80e493

Browse files
authored
to improve performance do not use BigDecimal for rounding (#938)
1 parent fcc4091 commit f80e493

5 files changed

Lines changed: 89 additions & 28 deletions

File tree

services-geojson/src/main/java/com/mapbox/geojson/gson/BoundingBoxSerializer.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.mapbox.geojson.BoundingBox;
99
import com.mapbox.geojson.Point;
1010
import com.mapbox.geojson.shifter.CoordinateShifterManager;
11+
import com.mapbox.geojson.utils.GeoJsonUtils;
1112

1213
import java.lang.reflect.Type;
1314
import java.util.List;
@@ -48,8 +49,8 @@ public JsonElement serialize(BoundingBox src, Type typeOfSrc, JsonSerializationC
4849
List<Double> unshiftedCoordinates =
4950
CoordinateShifterManager.getCoordinateShifter().unshiftPoint(point);
5051

51-
bbox.add(new JsonPrimitive(unshiftedCoordinates.get(0)));
52-
bbox.add(new JsonPrimitive(unshiftedCoordinates.get(1)));
52+
bbox.add(new JsonPrimitive(GeoJsonUtils.trim(unshiftedCoordinates.get(0))));
53+
bbox.add(new JsonPrimitive(GeoJsonUtils.trim(unshiftedCoordinates.get(1))));
5354
if (point.hasAltitude()) {
5455
bbox.add(new JsonPrimitive(unshiftedCoordinates.get(2)));
5556
}
@@ -58,8 +59,8 @@ public JsonElement serialize(BoundingBox src, Type typeOfSrc, JsonSerializationC
5859
point = src.northeast();
5960
unshiftedCoordinates =
6061
CoordinateShifterManager.getCoordinateShifter().unshiftPoint(point);
61-
bbox.add(new JsonPrimitive(unshiftedCoordinates.get(0)));
62-
bbox.add(new JsonPrimitive(unshiftedCoordinates.get(1)));
62+
bbox.add(new JsonPrimitive(GeoJsonUtils.trim(unshiftedCoordinates.get(0))));
63+
bbox.add(new JsonPrimitive(GeoJsonUtils.trim(unshiftedCoordinates.get(1))));
6364
if (point.hasAltitude()) {
6465
bbox.add(new JsonPrimitive(unshiftedCoordinates.get(2)));
6566
}

services-geojson/src/main/java/com/mapbox/geojson/gson/CoordinateTypeAdapter.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
import com.google.gson.stream.JsonWriter;
66

77
import com.mapbox.geojson.shifter.CoordinateShifterManager;
8+
import com.mapbox.geojson.utils.GeoJsonUtils;
89

910
import java.io.IOException;
10-
import java.math.BigDecimal;
11-
import java.math.RoundingMode;
1211
import java.util.ArrayList;
1312
import java.util.List;
1413

@@ -27,16 +26,8 @@ public void write(JsonWriter out, List<Double> value) throws IOException {
2726
List<Double> unshiftedCoordinates =
2827
CoordinateShifterManager.getCoordinateShifter().unshiftPoint(value);
2928

30-
BigDecimal lon = BigDecimal.valueOf(unshiftedCoordinates.get(0));
31-
String lonString = lon.setScale(7, RoundingMode.HALF_UP)
32-
.stripTrailingZeros().toPlainString();
33-
34-
BigDecimal lat = BigDecimal.valueOf(unshiftedCoordinates.get(1));
35-
String latString = lat.setScale(7, RoundingMode.HALF_UP)
36-
.stripTrailingZeros().toPlainString();
37-
38-
out.value(Double.valueOf(lonString));
39-
out.value(Double.valueOf(latString));
29+
out.value(GeoJsonUtils.trim(unshiftedCoordinates.get(0)));
30+
out.value(GeoJsonUtils.trim(unshiftedCoordinates.get(1)));
4031

4132
// Includes altitude
4233
if (value.size() > 2) {

services-geojson/src/main/java/com/mapbox/geojson/gson/PointSerializer.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
import com.google.gson.JsonSerializer;
88
import com.mapbox.geojson.Point;
99
import com.mapbox.geojson.shifter.CoordinateShifterManager;
10+
import com.mapbox.geojson.utils.GeoJsonUtils;
1011

1112
import java.lang.reflect.Type;
12-
import java.math.BigDecimal;
13-
import java.math.RoundingMode;
1413
import java.util.List;
1514

1615
/**
@@ -50,16 +49,8 @@ public JsonElement serialize(Point src, Type typeOfSrc, JsonSerializationContext
5049
List<Double> unshiftedCoordinates =
5150
CoordinateShifterManager.getCoordinateShifter().unshiftPoint(src);
5251

53-
BigDecimal lon = BigDecimal.valueOf(unshiftedCoordinates.get(0));
54-
String lonString = lon.setScale(7, RoundingMode.HALF_UP)
55-
.stripTrailingZeros().toPlainString();
56-
57-
BigDecimal lat = BigDecimal.valueOf(unshiftedCoordinates.get(1));
58-
String latString = lat.setScale(7, RoundingMode.HALF_UP)
59-
.stripTrailingZeros().toPlainString();
60-
61-
rawCoordinates.add(new JsonPrimitive(Double.valueOf(lonString)));
62-
rawCoordinates.add(new JsonPrimitive(Double.valueOf(latString)));
52+
rawCoordinates.add(new JsonPrimitive(GeoJsonUtils.trim(unshiftedCoordinates.get(0))));
53+
rawCoordinates.add(new JsonPrimitive(GeoJsonUtils.trim(unshiftedCoordinates.get(1))));
6354

6455
// Includes altitude
6556
if (src.hasAltitude()) {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.mapbox.geojson.utils;
2+
3+
/**
4+
* GeoJson utils class contains method that can be used throughout geojson package.
5+
*
6+
* @since 4.3.0
7+
*/
8+
public class GeoJsonUtils {
9+
10+
private static double ROUND_PRECISION = 10000000.0;
11+
private static long MAX_DOUBLE_TO_ROUND = (long) (Long.MAX_VALUE / ROUND_PRECISION);
12+
13+
/**
14+
* Trims a double value to have only 7 digits after period.
15+
*
16+
* @param value to be trimed
17+
* @return trimmed value
18+
*/
19+
public static double trim(double value) {
20+
if (value > MAX_DOUBLE_TO_ROUND || value < -MAX_DOUBLE_TO_ROUND) {
21+
return value;
22+
}
23+
return Math.round(value * ROUND_PRECISION) / ROUND_PRECISION;
24+
}
25+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.mapbox.geojson.utils;
2+
3+
import static org.junit.Assert.assertEquals;
4+
5+
import com.mapbox.core.TestUtils;
6+
import org.junit.Test;
7+
8+
9+
public class GeoJsonUtilsTest extends TestUtils {
10+
11+
12+
@Test
13+
public void trimPositiveRoundUp() {
14+
double trimmedValue = GeoJsonUtils.trim(3.123456789);
15+
double expected = 3.1234568;
16+
assertEquals("trim to 7 digits after period", expected, trimmedValue, 1e-8);
17+
}
18+
19+
@Test
20+
public void trimPositiveRoundDown() {
21+
double trimmedValue = GeoJsonUtils.trim(3.123456712);
22+
double expected = 3.1234567;
23+
assertEquals("trim to 7 digits after period", expected, trimmedValue, 1e-8);
24+
}
25+
26+
@Test
27+
public void trimNegative() {
28+
double trimmedValue = GeoJsonUtils.trim(-3.123456789);
29+
double expected = -3.1234568;
30+
assertEquals("trim to 7 digits after period", expected, trimmedValue, 1e-8);
31+
}
32+
33+
@Test
34+
public void trimZero() {
35+
double trimmedValue = GeoJsonUtils.trim(0);
36+
double expected = 0;
37+
assertEquals("trim to 7 digits after period", expected, trimmedValue, 1e-8);
38+
}
39+
40+
@Test
41+
public void trimInt() {
42+
double trimmedValue = GeoJsonUtils.trim(8);
43+
double expected = 8;
44+
assertEquals("trim to 7 digits after period", expected, trimmedValue, 1e-8);
45+
}
46+
47+
@Test
48+
public void trimMaxLong() {
49+
double trimmedValue = GeoJsonUtils.trim(Long.MAX_VALUE + 0.1);
50+
double expected = Long.MAX_VALUE;
51+
assertEquals("trim to 7 digits after period", expected, trimmedValue, 1e-8);
52+
}
53+
}

0 commit comments

Comments
 (0)