Changeset 18183 in josm
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Geometry.java
r17994 r18183 45 45 Area area = null; 46 46 // MVT uses delta encoding. Each feature starts at (0, 0). 47 doublex = 0;48 doubley = 0;47 int x = 0; 48 int y = 0; 49 49 // Area is used to determine the inner/outer of a polygon 50 double areaAreaSq = 0; 50 final int maxArraySize = commands.stream().filter(command -> command.getType() != Command.ClosePath).mapToInt(command -> command.getOperations().length).sum(); 51 final List<Integer> xArray = new ArrayList<>(maxArraySize); 52 final List<Integer> yArray = new ArrayList<>(maxArraySize); 51 53 for (CommandInteger command : commands) { 52 54 final short[] operations = command.getOperations(); 53 55 // Technically, there is no reason why there can be multiple MoveTo operations in one command, but that is undefined behavior 54 56 if (command.getType() == Command.MoveTo && operations.length == 2) { 55 areaAreaSq = 0;56 57 x += operations[0]; 57 58 y += operations[1]; 58 59 line = new Path2D.Float(); 59 60 line.moveTo(x, y); 61 xArray.add(x); 62 yArray.add(y); 60 63 shapes.add(line); 61 64 } else if (command.getType() == Command.LineTo && operations.length % 2 == 0 && line != null) { 62 65 for (int i = 0; i < operations.length / 2; i++) { 63 final double lx = x;64 final double ly = y;65 66 x += operations[2 * i]; 66 67 y += operations[2 * i + 1]; 67 areaAreaSq += lx * y - x * ly; 68 xArray.add(x); 69 yArray.add(y); 68 70 line.lineTo(x, y); 69 71 } … … 77 79 } 78 80 81 final double areaAreaSq = calculateSurveyorsArea(xArray.stream().mapToInt(i -> i).toArray(), yArray.stream().mapToInt(i -> i).toArray()); 79 82 Area nArea = new Area(line); 80 83 // SonarLint thinks that this is never > 0. It can be. … … 94 97 95 98 /** 99 * This is also known as the "shoelace formula". 100 * @param xArray The array of x coordinates 101 * @param yArray The array of y coordinates 102 * @return The area of the object 103 * @throws IllegalArgumentException if the array lengths are not equal 104 */ 105 static double calculateSurveyorsArea(int[] xArray, int[] yArray) { 106 if (xArray.length != yArray.length) { 107 throw new IllegalArgumentException("Cannot calculate areas when arrays are uneven"); 108 } 109 // Lines have no area 110 if (xArray.length < 3) { 111 return 0; 112 } 113 int area = 0; 114 // Do the non-special stuff first (x0 * y1 - x1 * y0) 115 for (int i = 0; i < xArray.length - 1; i++) { 116 area += xArray[i] * yArray[i + 1] - xArray[i + 1] * yArray[i]; 117 } 118 // Now calculate the edges (xn * y0 - x0 * yn) 119 area += xArray[xArray.length - 1] * yArray[0] - xArray[0] * yArray[yArray.length - 1]; 120 return area / 2d; 121 } 122 123 /** 96 124 * Get the shapes to draw this geometry with 97 125 * @return A collection of shapes -
trunk/test/unit/org/openstreetmap/josm/data/imagery/vectortile/mapbox/GeometryTest.java
r17867 r18183 6 6 import static org.junit.jupiter.api.Assertions.assertThrows; 7 7 import static org.junit.jupiter.api.Assertions.assertTrue; 8 9 8 10 9 import java.awt.geom.Area; … … 139 138 } 140 139 140 /** 141 * This checks that the area is properly calculated 142 */ 143 @Test 144 void testNonRegression20971And21254() { 145 assertEquals(15.0, Geometry.calculateSurveyorsArea(new int[]{1507, 1509, 1509}, new int[]{3029, 3018, 3033})); 146 assertEquals(0.0, Geometry.calculateSurveyorsArea(new int[]{0, 0, 0}, new int[]{0, 0, 0})); 147 assertEquals(0.0, Geometry.calculateSurveyorsArea(new int[2], new int[2])); 148 assertThrows(IllegalArgumentException.class, () -> Geometry.calculateSurveyorsArea(new int[3], new int[4])); 149 } 150 141 151 @Test 142 152 void testMultiPolygon() {
Note:
See TracChangeset
for help on using the changeset viewer.