- Timestamp:
- 2018-05-07T23:40:50+02:00 (5 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java
r13670 r13712 33 33 import org.openstreetmap.josm.gui.MainApplication; 34 34 import org.openstreetmap.josm.gui.Notification; 35 import org.openstreetmap.josm.tools.Geometry; 35 36 import org.openstreetmap.josm.tools.JosmRuntimeException; 36 37 import org.openstreetmap.josm.tools.Logging; … … 166 167 167 168 try { 168 final SequenceCommand command = orthogonalize(sel); 169 MainApplication.undoRedo.add(new SequenceCommand(tr("Orthogonalize"), command)); 169 MainApplication.undoRedo.add(orthogonalize(sel)); 170 170 } catch (InvalidUserInputException ex) { 171 171 Logging.debug(ex); … … 205 205 } 206 206 } 207 if (wayDataList.isEmpty() && nodeList.size() > 2) { 207 final int nodesCount = nodeList.size(); 208 if (wayDataList.isEmpty() && nodesCount > 2) { 208 209 final WayData data = new WayData(nodeList); 209 210 final Collection<Command> commands = orthogonalize(Collections.singletonList(data), Collections.<Node>emptyList()); … … 212 213 throw new InvalidUserInputException("usage"); 213 214 } else { 214 if (node List.size() == 2 || nodeList.isEmpty()) {215 if (nodesCount <= 2) { 215 216 OrthogonalizeAction.rememberMovements.clear(); 216 217 final Collection<Command> commands = new LinkedList<>(); 217 218 218 if (node List.size() == 2) { // fixed direction219 if (nodesCount == 2) { // fixed direction, or single node to move 219 220 commands.addAll(orthogonalize(wayDataList, nodeList)); 220 } else if (nodeList.isEmpty()) { 221 List<List<WayData>> groups = buildGroups(wayDataList); 222 for (List<WayData> g: groups) { 221 } else if (nodesCount == 1) { 222 commands.add(orthogonalize(wayDataList, nodeList.get(0))); 223 } else if (nodesCount == 0) { 224 for (List<WayData> g : buildGroups(wayDataList)) { 223 225 commands.addAll(orthogonalize(g, nodeList)); 224 226 } 225 } else {226 throw new IllegalStateException();227 227 } 228 228 … … 265 265 } 266 266 } 267 } 268 269 /** 270 * Try to orthogonalize the given ways by moving only a single given node 271 * @param wayDataList list of ways 272 * @param singleNode common node to ways to orthogonalize. Only this one will be moved 273 * @return the command to move the node 274 * @throws InvalidUserInputException if the command cannot be computed 275 */ 276 private static Command orthogonalize(List<WayData> wayDataList, Node singleNode) throws InvalidUserInputException { 277 List<EastNorth> rightAnglePositions = new ArrayList<>(); 278 int wayCount = wayDataList.size(); 279 for (WayData wd : wayDataList) { 280 int n = wd.wayNodes.size(); 281 int i = wd.wayNodes.indexOf(singleNode); 282 Node n0, n2; 283 if (i == 0 && n >= 3 && singleNode.equals(wd.wayNodes.get(n-1))) { 284 n0 = wd.wayNodes.get(n-2); 285 n2 = wd.wayNodes.get(1); 286 } else if (i > 0 && i < n-1) { 287 n0 = wd.wayNodes.get(i-1); 288 n2 = wd.wayNodes.get(i+1); 289 } else { 290 continue; 291 } 292 EastNorth n0en = n0.getEastNorth(); 293 EastNorth n1en = singleNode.getEastNorth(); 294 EastNorth n2en = n2.getEastNorth(); 295 double angle = Geometry.getNormalizedAngleInDegrees(Geometry.getCornerAngle(n0en, n1en, n2en)); 296 if (wayCount == 1 || (80 <= angle && angle <= 100)) { 297 EastNorth c = n0en.getCenter(n2en); 298 double r = n0en.distance(n2en) / 2d; 299 double vX = n1en.east() - c.east(); 300 double vY = n1en.north() - c.north(); 301 double magV = Math.sqrt(vX*vX + vY*vY); 302 rightAnglePositions.add(new EastNorth(c.east() + vX / magV * r, 303 c.north() + vY / magV * r)); 304 } 305 } 306 if (rightAnglePositions.isEmpty()) { 307 throw new InvalidUserInputException("Unable to orthogonalize " + singleNode); 308 } 309 return new MoveCommand(singleNode, Main.getProjection().eastNorth2latlon(Geometry.getCentroidEN(rightAnglePositions))); 267 310 } 268 311 … … 307 350 totSum = EN.sum(totSum, w.segSum); 308 351 } 309 headingAll = EN.polar( new EastNorth(0., 0.), totSum);352 headingAll = EN.polar(EastNorth.ZERO, totSum); 310 353 } else { 311 354 headingAll = EN.polar(headingNodes.get(0).getEastNorth(), headingNodes.get(1).getEastNorth()); … … 334 377 // calculate the centroid of all nodes 335 378 // it is used as rotation center 336 EastNorth pivot = new EastNorth(0., 0.);379 EastNorth pivot = EastNorth.ZERO; 337 380 for (Node n : allNodes) { 338 381 pivot = EN.sum(pivot, n.getEastNorth()); -
trunk/src/org/openstreetmap/josm/data/validation/tests/RightAngleBuildingTest.java
r13698 r13712 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.util. Collections;6 import java.util.Arrays; 7 7 import java.util.List; 8 8 … … 52 52 .primitives(w) 53 53 .highlight(pair.b); 54 if (angles.stream().noneMatch( 55 p -> Math.abs(p.a - 90) >= maxAngleDelta && Math.abs(p.a - 180) >= minAngleDelta)) { 56 builder.fix(() -> { 57 try { 58 return OrthogonalizeAction.orthogonalize(Collections.singleton(w)); 59 } catch (InvalidUserInputException e) { 60 Logging.warn(e); 61 return null; 62 } 63 }); 64 } 54 builder.fix(() -> { 55 try { 56 return OrthogonalizeAction.orthogonalize(Arrays.asList(w, pair.b)); 57 } catch (InvalidUserInputException e) { 58 Logging.warn(e); 59 return null; 60 } 61 }); 65 62 errors.add(builder.build()); 66 63 return; -
trunk/src/org/openstreetmap/josm/tools/Geometry.java
r13670 r13712 16 16 import java.util.Set; 17 17 import java.util.function.Predicate; 18 import java.util.stream.Collectors; 18 19 19 20 import org.openstreetmap.josm.Main; … … 796 797 } 797 798 798 /** 799 /** 799 800 * Get angles in radians and return it's value in range [0, 180]. 800 801 * … … 814 815 */ 815 816 public static EastNorth getCentroid(List<Node> nodes) { 817 return getCentroidEN(nodes.stream().map(Node::getEastNorth).collect(Collectors.toList())); 818 } 819 820 /** 821 * Compute the centroid/barycenter of nodes 822 * @param nodes Coordinates for which the centroid is wanted 823 * @return the centroid of nodes 824 * @since 13712 825 */ 826 public static EastNorth getCentroidEN(List<EastNorth> nodes) { 827 828 final int size = nodes.size(); 829 if (size == 1) { 830 return nodes.get(0); 831 } else if (size == 2) { 832 return nodes.get(0).getCenter(nodes.get(1)); 833 } 816 834 817 835 BigDecimal area = BigDecimal.ZERO; … … 819 837 BigDecimal east = BigDecimal.ZERO; 820 838 821 // See https://en.wikipedia.org/wiki/Centroid#Centroid_of_ polygon for the equation used here822 for (int i = 0; i < nodes.size(); i++) {823 EastNorth n0 = nodes.get(i) .getEastNorth();824 EastNorth n1 = nodes.get((i+1) % nodes.size()).getEastNorth();839 // See https://en.wikipedia.org/wiki/Centroid#Centroid_of_a_polygon for the equation used here 840 for (int i = 0; i < size; i++) { 841 EastNorth n0 = nodes.get(i); 842 EastNorth n1 = nodes.get((i+1) % size); 825 843 826 844 if (n0 != null && n1 != null && n0.isValid() && n1.isValid()) { -
trunk/test/unit/org/openstreetmap/josm/tools/GeometryTest.java
r13670 r13712 5 5 6 6 import java.io.FileInputStream; 7 import java.util.Arrays; 7 8 import java.util.List; 8 9 … … 145 146 assertEquals(162.66381817961337, angle, 1e-5); 146 147 } 148 149 /** 150 * Test of {@link Geometry#getCentroidEN} method. 151 */ 152 @Test 153 public void testCentroidEN() { 154 EastNorth en1 = new EastNorth(100, 200); 155 EastNorth en2 = new EastNorth(150, 400); 156 EastNorth en3 = new EastNorth(200, 200); 157 assertEquals(en1, Geometry.getCentroidEN(Arrays.asList(en1))); 158 assertEquals(new EastNorth(125, 300), Geometry.getCentroidEN(Arrays.asList(en1, en2))); 159 assertEquals(new EastNorth(150, 266d + 2d/3d), Geometry.getCentroidEN(Arrays.asList(en1, en2, en3))); 160 } 147 161 }
Note: See TracChangeset
for help on using the changeset viewer.