Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/AlignInCircleAction.java
r17416 r18615 150 150 * Case 3: Only nodes are selected 151 151 * --> Align these nodes, all are fix 152 * <p> 153 * Case 4: Circularize selected ways 154 * --> Circularize each way of the selection. 152 155 * @param ds data set in which the command operates 153 156 * @return the resulting command to execute to perform action, or null if nothing was changed … … 227 230 fixNodes.addAll(onWay); 228 231 nodes = collectNodesAnticlockwise(ways); 232 } else if (!ways.isEmpty() && selectedNodes.isEmpty()) { 233 List<Command> rcmds = new LinkedList<>(); 234 for (Way w : ways) { 235 if (!w.isDeleted() && w.isArea()) { 236 List<Node> wnodes = w.getNodes(); 237 wnodes.remove(wnodes.size() - 1); 238 if (validateGeometry(wnodes)) { 239 center = Geometry.getCenter(wnodes); 240 } 241 if (center == null) { 242 continue; 243 } 244 boolean skipThisWay = false; 245 radius = 0; 246 for (Node n : wnodes) { 247 if (!n.isLatLonKnown()) { 248 skipThisWay = true; 249 break; 250 } else { 251 radius += center.distance(n.getEastNorth()); 252 } 253 } 254 if (skipThisWay) { 255 continue; 256 } else { 257 radius /= wnodes.size(); 258 } 259 Command c = moveNodesCommand(wnodes, Collections.emptySet(), center, radius); 260 if (c != null) { 261 rcmds.add(c); 262 } 263 } 264 } 265 if (rcmds.isEmpty()) { 266 throw new InvalidSelection(); 267 } 268 return new SequenceCommand(tr("Align each Way in Circle"), rcmds); 229 269 } else { 230 270 throw new InvalidSelection(); … … 259 299 radius = radius / nodes.size(); 260 300 } 261 301 return moveNodesCommand(nodes, fixNodes, center, radius); 302 } 303 304 /** 305 * Move each node of the list of nodes to be arranged in a circle. 306 * @param nodes The list of nodes to be moved. 307 * @param fixNodes The list of nodes that must not be moved. 308 * @param center A center of the circle formed by the nodes. 309 * @param radius A radius of the circle formed by the nodes. 310 * @return the command that arranges the nodes in a circle. 311 * @since 18615 312 */ 313 public static Command moveNodesCommand( 314 List<Node> nodes, 315 Set<Node> fixNodes, 316 EastNorth center, 317 double radius) { 262 318 List<Command> cmds = new LinkedList<>(); 263 319 -
trunk/test/unit/org/openstreetmap/josm/actions/AlignInCircleActionTest.java
r17394 r18615 2 2 package org.openstreetmap.josm.actions; 3 3 4 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 4 5 import static org.junit.jupiter.api.Assertions.assertEquals; 5 6 import static org.junit.jupiter.api.Assertions.assertFalse; … … 7 8 import static org.junit.jupiter.api.Assertions.assertNull; 8 9 import static org.junit.jupiter.api.Assertions.assertTrue; 9 10 import static org.junit.jupiter.api.Assertions.fail; 11 12 import java.io.IOException; 13 import java.io.InputStream; 10 14 import java.nio.file.Files; 11 15 import java.nio.file.Paths; … … 18 22 import org.openstreetmap.josm.actions.AlignInCircleAction.InvalidSelection; 19 23 import org.openstreetmap.josm.command.Command; 24 import org.openstreetmap.josm.data.coor.ILatLon; 20 25 import org.openstreetmap.josm.data.osm.DataSet; 21 26 import org.openstreetmap.josm.data.osm.Node; 22 27 import org.openstreetmap.josm.data.osm.OsmPrimitive; 23 28 import org.openstreetmap.josm.data.osm.Way; 29 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 30 import org.openstreetmap.josm.io.IllegalDataException; 24 31 import org.openstreetmap.josm.io.OsmReader; 25 32 import org.openstreetmap.josm.testutils.JOSMTestRules; … … 182 189 } 183 190 } 191 192 /** 193 * Test case: Circularize a batch of (two) buildings. 194 * @throws IOException if the test file could not be read 195 * @throws IllegalDataException if the test file has been corrupted 196 */ 197 @Test 198 void testMultipleWaysSelected() throws IOException, IllegalDataException { 199 final DataSet before; 200 try (InputStream fis = Files.newInputStream(Paths.get(TestUtils.getTestDataRoot(), "alignCircleBuildingsBefore.osm"))) { 201 before = OsmReader.parseDataSet(fis, NullProgressMonitor.INSTANCE); 202 } 203 204 Way firstBefore = null; 205 Way secondBefore = null; 206 207 for (Way w : before.getWays()) { 208 if ("first".equals(w.get("test"))) { 209 firstBefore = w; 210 } else if ("second".equals(w.get("test"))) { 211 secondBefore = w; 212 } else { 213 fail("There should only be \"first\" or \"second\" values in the key \"test\""); 214 } 215 } 216 217 assertNotNull(firstBefore); 218 assertNotNull(secondBefore); 219 220 before.clearSelection(); 221 before.addSelected(firstBefore); 222 before.addSelected(secondBefore); 223 224 Command c = assertDoesNotThrow(() -> AlignInCircleAction.buildCommand(before)); 225 c.executeCommand(); 226 227 final DataSet after; 228 try (InputStream fis = Files.newInputStream(Paths.get(TestUtils.getTestDataRoot(), "alignCircleBuildingsAfter.osm"))) { 229 after = OsmReader.parseDataSet(fis, NullProgressMonitor.INSTANCE); 230 } 231 Way firstAfter = null; 232 Way secondAfter = null; 233 234 for (Way w : after.getWays()) { 235 if ("first".equals(w.get("test"))) { 236 firstAfter = w; 237 } else if ("second".equals(w.get("test"))) { 238 secondAfter = w; 239 } else { 240 fail("There should only be \"first\" or \"second\" values in the key \"test\""); 241 } 242 } 243 244 assertNotNull(firstAfter); 245 assertEquals(firstAfter.getNodesCount(), firstBefore.getNodesCount()); 246 for (int i = 0; i < firstAfter.getNodesCount(); i++) { 247 Node bn = firstBefore.getNode(i); 248 Node an = firstAfter.getNode(i); 249 assertEquals(bn.lat(), an.lat(), ILatLon.MAX_SERVER_PRECISION); 250 assertEquals(bn.lon(), an.lon(), ILatLon.MAX_SERVER_PRECISION); 251 } 252 253 assertNotNull(secondAfter); 254 assertEquals(secondAfter.getNodesCount(), secondBefore.getNodesCount()); 255 for (int i = 0; i < secondAfter.getNodesCount(); i++) { 256 Node bn = secondBefore.getNode(i); 257 Node an = secondAfter.getNode(i); 258 assertEquals(bn.lat(), an.lat(), ILatLon.MAX_SERVER_PRECISION); 259 assertEquals(bn.lon(), an.lon(), ILatLon.MAX_SERVER_PRECISION); 260 } 261 } 184 262 }
Note:
See TracChangeset
for help on using the changeset viewer.