| 1 | ### Eclipse Workspace Patch 1.0
|
|---|
| 2 | #P josm
|
|---|
| 3 | diff --git src/org/openstreetmap/josm/actions/AlignInLineAction.java src/org/openstreetmap/josm/actions/AlignInLineAction.java
|
|---|
| 4 | index 9d85c4f..0feb334 100644
|
|---|
| 5 | --- src/org/openstreetmap/josm/actions/AlignInLineAction.java
|
|---|
| 6 | +++ src/org/openstreetmap/josm/actions/AlignInLineAction.java
|
|---|
| 7 | @@ -93,11 +93,12 @@
|
|---|
| 8 | // Get ways passing though all selected nodes.
|
|---|
| 9 | Set<Way> waysRef = null;
|
|---|
| 10 | for (Node n: nodes) {
|
|---|
| 11 | - Collection<Way> ref = n.getParentWays();
|
|---|
| 12 | - if (waysRef == null)
|
|---|
| 13 | - waysRef = new HashSet<>(ref);
|
|---|
| 14 | - else
|
|---|
| 15 | - waysRef.retainAll(ref);
|
|---|
| 16 | + final Collection<Way> ref = n.getParentWays();
|
|---|
| 17 | + if (waysRef == null) {
|
|---|
| 18 | + waysRef = new HashSet<>(ref);
|
|---|
| 19 | + } else {
|
|---|
| 20 | + waysRef.retainAll(ref);
|
|---|
| 21 | + }
|
|---|
| 22 | }
|
|---|
| 23 |
|
|---|
| 24 | if (waysRef == null) {
|
|---|
| 25 | @@ -105,11 +106,12 @@
|
|---|
| 26 | }
|
|---|
| 27 |
|
|---|
| 28 | // Nodes belongs to multiple ways, return most distant nodes.
|
|---|
| 29 | - if (waysRef.size() != 1)
|
|---|
| 30 | - return nodeFurthestAppart(nodes);
|
|---|
| 31 | + if (waysRef.size() != 1) {
|
|---|
| 32 | + return nodeFurthestAppart(nodes);
|
|---|
| 33 | + }
|
|---|
| 34 |
|
|---|
| 35 | // All nodes are part of the same way. See #9605.
|
|---|
| 36 | - Way way = waysRef.iterator().next();
|
|---|
| 37 | + final Way way = waysRef.iterator().next();
|
|---|
| 38 |
|
|---|
| 39 | if (way.isClosed()) {
|
|---|
| 40 | // Align these nodes on the line passing through the most distant nodes.
|
|---|
| 41 | @@ -121,12 +123,14 @@
|
|---|
| 42 |
|
|---|
| 43 | // The way is open, align nodes on the line passing through the extremity nodes (most distant in the way
|
|---|
| 44 | // sequence). See #9605#comment:3.
|
|---|
| 45 | - Set<Node> remainNodes = new HashSet<>(nodes);
|
|---|
| 46 | + final Set<Node> remainNodes = new HashSet<>(nodes);
|
|---|
| 47 | for (Node n : way.getNodes()) {
|
|---|
| 48 | - if (!remainNodes.contains(n))
|
|---|
| 49 | - continue;
|
|---|
| 50 | - if (nodea == null)
|
|---|
| 51 | - nodea = n;
|
|---|
| 52 | + if (!remainNodes.contains(n)) {
|
|---|
| 53 | + continue;
|
|---|
| 54 | + }
|
|---|
| 55 | + if (nodea == null) {
|
|---|
| 56 | + nodea = n;
|
|---|
| 57 | + }
|
|---|
| 58 | if (remainNodes.size() == 1) {
|
|---|
| 59 | nodeb = remainNodes.iterator().next();
|
|---|
| 60 | break;
|
|---|
| 61 | @@ -146,14 +150,14 @@
|
|---|
| 62 | private static Node[] nodeFurthestAppart(List<Node> nodes) {
|
|---|
| 63 | Node node1 = null, node2 = null;
|
|---|
| 64 | double minSqDistance = 0;
|
|---|
| 65 | - int nb;
|
|---|
| 66 | + final int nb;
|
|---|
| 67 |
|
|---|
| 68 | nb = nodes.size();
|
|---|
| 69 | for (int i = 0; i < nb - 1; i++) {
|
|---|
| 70 | - Node n = nodes.get(i);
|
|---|
| 71 | + final Node n = nodes.get(i);
|
|---|
| 72 | for (int j = i + 1; j < nb; j++) {
|
|---|
| 73 | - Node m = nodes.get(j);
|
|---|
| 74 | - double sqDist = n.getEastNorth().distanceSq(m.getEastNorth());
|
|---|
| 75 | + final Node m = nodes.get(j);
|
|---|
| 76 | + final double sqDist = n.getEastNorth().distanceSq(m.getEastNorth());
|
|---|
| 77 | if (sqDist > minSqDistance) {
|
|---|
| 78 | node1 = n;
|
|---|
| 79 | node2 = m;
|
|---|
| 80 | @@ -170,11 +174,12 @@
|
|---|
| 81 | */
|
|---|
| 82 | @Override
|
|---|
| 83 | public void actionPerformed(ActionEvent e) {
|
|---|
| 84 | - if (!isEnabled())
|
|---|
| 85 | - return;
|
|---|
| 86 | + if (!isEnabled()) {
|
|---|
| 87 | + return;
|
|---|
| 88 | + }
|
|---|
| 89 |
|
|---|
| 90 | try {
|
|---|
| 91 | - Command cmd = buildCommand(getLayerManager().getEditDataSet());
|
|---|
| 92 | + final Command cmd = buildCommand(getLayerManager().getEditDataSet());
|
|---|
| 93 | if (cmd != null) {
|
|---|
| 94 | UndoRedoHandler.getInstance().add(cmd);
|
|---|
| 95 | }
|
|---|
| 96 | @@ -194,8 +199,8 @@
|
|---|
| 97 | * @since 13108
|
|---|
| 98 | */
|
|---|
| 99 | public Command buildCommand(DataSet ds) throws InvalidSelection {
|
|---|
| 100 | - List<Node> selectedNodes = new ArrayList<>(ds.getSelectedNodes());
|
|---|
| 101 | - List<Way> selectedWays = new ArrayList<>(ds.getSelectedWays());
|
|---|
| 102 | + final List<Node> selectedNodes = new ArrayList<>(ds.getSelectedNodes());
|
|---|
| 103 | + final List<Way> selectedWays = new ArrayList<>(ds.getSelectedWays());
|
|---|
| 104 | selectedWays.removeIf(w -> w.isIncomplete() || w.isEmpty());
|
|---|
| 105 |
|
|---|
| 106 | // Decide what to align based on selection:
|
|---|
| 107 | @@ -204,17 +209,19 @@
|
|---|
| 108 | return alignMultiWay(selectedWays);
|
|---|
| 109 | } else if (selectedNodes.size() == 1) {
|
|---|
| 110 | // Only 1 node selected -> align this node relative to referrers way
|
|---|
| 111 | - Node selectedNode = selectedNodes.get(0);
|
|---|
| 112 | - List<Way> involvedWays;
|
|---|
| 113 | - if (selectedWays.isEmpty())
|
|---|
| 114 | - // No selected way, all way containing this node are used
|
|---|
| 115 | + final Node selectedNode = selectedNodes.get(0);
|
|---|
| 116 | + final List<Way> involvedWays;
|
|---|
| 117 | + if (selectedWays.isEmpty()) {
|
|---|
| 118 | + // No selected way, all way containing this node are used
|
|---|
| 119 | involvedWays = selectedNode.getParentWays();
|
|---|
| 120 | - else
|
|---|
| 121 | - // Selected way, use only these ways
|
|---|
| 122 | + } else {
|
|---|
| 123 | + // Selected way, use only these ways
|
|---|
| 124 | involvedWays = selectedWays;
|
|---|
| 125 | - List<Line> lines = getInvolvedLines(selectedNode, involvedWays);
|
|---|
| 126 | - if (lines.size() > 2 || lines.isEmpty())
|
|---|
| 127 | - throw new InvalidSelection();
|
|---|
| 128 | + }
|
|---|
| 129 | + final List<Line> lines = getInvolvedLines(selectedNode, involvedWays);
|
|---|
| 130 | + if (lines.size() > 2 || lines.isEmpty()) {
|
|---|
| 131 | + throw new InvalidSelection();
|
|---|
| 132 | + }
|
|---|
| 133 | return alignSingleNode(selectedNodes.get(0), lines);
|
|---|
| 134 | } else if (selectedNodes.size() >= 3) {
|
|---|
| 135 | // More than 3 nodes and way(s) selected -> align selected nodes. Don't care of way(s).
|
|---|
| 136 | @@ -234,9 +241,9 @@
|
|---|
| 137 | */
|
|---|
| 138 | private static Command alignOnlyNodes(List<Node> nodes) throws InvalidSelection {
|
|---|
| 139 | // Choose nodes used as anchor points for projection.
|
|---|
| 140 | - Node[] anchors = nodePairFurthestApart(nodes);
|
|---|
| 141 | - Line line = new Line(anchors[0], anchors[1]);
|
|---|
| 142 | - Collection<Command> cmds = nodes.stream()
|
|---|
| 143 | + final Node[] anchors = nodePairFurthestApart(nodes);
|
|---|
| 144 | + final Line line = new Line(anchors[0], anchors[1]);
|
|---|
| 145 | + final Collection<Command> cmds = nodes.stream()
|
|---|
| 146 | .filter(node -> node != anchors[0] && node != anchors[1])
|
|---|
| 147 | .map(line::projectionCommand)
|
|---|
| 148 | .collect(Collectors.toList());
|
|---|
| 149 | @@ -251,11 +258,12 @@
|
|---|
| 150 | */
|
|---|
| 151 | private static Command alignMultiWay(Collection<Way> ways) throws InvalidSelection {
|
|---|
| 152 | // Collect all nodes and compute line equation
|
|---|
| 153 | - Set<Node> nodes = new HashSet<>();
|
|---|
| 154 | - Map<Way, Line> lines = new HashMap<>();
|
|---|
| 155 | + final Set<Node> nodes = new HashSet<>();
|
|---|
| 156 | + final Map<Way, Line> lines = new HashMap<>();
|
|---|
| 157 | for (Way w: ways) {
|
|---|
| 158 | - if (w.isClosed())
|
|---|
| 159 | - throw new InvalidSelection(tr("Can not align a polygon. Abort."));
|
|---|
| 160 | + if (w.isClosed()) {
|
|---|
| 161 | + throw new InvalidSelection(tr("Can not align a polygon. Abort."));
|
|---|
| 162 | + }
|
|---|
| 163 | if (!w.isEmpty()) {
|
|---|
| 164 | nodes.addAll(w.getNodes());
|
|---|
| 165 | lines.put(w, new Line(w));
|
|---|
| 166 | @@ -264,22 +272,26 @@
|
|---|
| 167 | if (nodes.isEmpty()) {
|
|---|
| 168 | throw new InvalidSelection(tr("Intersection of three or more ways can not be solved. Abort."));
|
|---|
| 169 | }
|
|---|
| 170 | - Collection<Command> cmds = new ArrayList<>(nodes.size());
|
|---|
| 171 | - List<Way> referrers = new ArrayList<>(ways.size());
|
|---|
| 172 | + final Collection<Command> cmds = new ArrayList<>(nodes.size());
|
|---|
| 173 | + final List<Way> referrers = new ArrayList<>(ways.size());
|
|---|
| 174 | for (Node n: nodes) {
|
|---|
| 175 | referrers.clear();
|
|---|
| 176 | for (OsmPrimitive o: n.getReferrers()) {
|
|---|
| 177 | - if (ways.contains(o))
|
|---|
| 178 | - referrers.add((Way) o);
|
|---|
| 179 | + if (ways.contains(o)) {
|
|---|
| 180 | + referrers.add((Way) o);
|
|---|
| 181 | + }
|
|---|
| 182 | }
|
|---|
| 183 | if (referrers.size() == 1) {
|
|---|
| 184 | - Way way = referrers.get(0);
|
|---|
| 185 | - if (way.isFirstLastNode(n)) continue;
|
|---|
| 186 | + final Way way = referrers.get(0);
|
|---|
| 187 | + if (way.isFirstLastNode(n)) {
|
|---|
| 188 | + continue;
|
|---|
| 189 | + }
|
|---|
| 190 | cmds.add(lines.get(way).projectionCommand(n));
|
|---|
| 191 | } else if (referrers.size() == 2) {
|
|---|
| 192 | cmds.add(lines.get(referrers.get(0)).intersectionCommand(n, lines.get(referrers.get(1))));
|
|---|
| 193 | - } else
|
|---|
| 194 | - throw new InvalidSelection(tr("Intersection of three or more ways can not be solved. Abort."));
|
|---|
| 195 | + } else {
|
|---|
| 196 | + throw new InvalidSelection(tr("Intersection of three or more ways can not be solved. Abort."));
|
|---|
| 197 | + }
|
|---|
| 198 | }
|
|---|
| 199 | return cmds.isEmpty() ? null : new SequenceCommand(tr("Align Nodes in Line"), cmds);
|
|---|
| 200 | }
|
|---|
| 201 | @@ -292,10 +304,10 @@
|
|---|
| 202 | * @throws InvalidSelection if a node got more than 4 neighbours (self-crossing way)
|
|---|
| 203 | */
|
|---|
| 204 | private static List<Line> getInvolvedLines(Node node, List<Way> refWays) throws InvalidSelection {
|
|---|
| 205 | - List<Line> lines = new ArrayList<>();
|
|---|
| 206 | - List<Node> neighbors = new ArrayList<>();
|
|---|
| 207 | + final List<Line> lines = new ArrayList<>();
|
|---|
| 208 | + final List<Node> neighbors = new ArrayList<>();
|
|---|
| 209 | for (Way way: refWays) {
|
|---|
| 210 | - List<Node> nodes = way.getNodes();
|
|---|
| 211 | + final List<Node> nodes = way.getNodes();
|
|---|
| 212 | neighbors.clear();
|
|---|
| 213 | for (int i = 1; i < nodes.size()-1; i++) {
|
|---|
| 214 | if (nodes.get(i) == node) {
|
|---|
| 215 | @@ -303,26 +315,31 @@
|
|---|
| 216 | neighbors.add(nodes.get(i+1));
|
|---|
| 217 | }
|
|---|
| 218 | }
|
|---|
| 219 | - if (neighbors.isEmpty())
|
|---|
| 220 | - continue;
|
|---|
| 221 | - else if (neighbors.size() == 2)
|
|---|
| 222 | - // Non self crossing
|
|---|
| 223 | + if (neighbors.isEmpty()) {
|
|---|
| 224 | + continue;
|
|---|
| 225 | + } else if (neighbors.size() == 2) {
|
|---|
| 226 | + // Non self crossing
|
|---|
| 227 | lines.add(new Line(neighbors.get(0), neighbors.get(1)));
|
|---|
| 228 | - else if (neighbors.size() == 4) {
|
|---|
| 229 | + } else if (neighbors.size() == 4) {
|
|---|
| 230 | // Self crossing, have to make 2 lines with 4 neighbors
|
|---|
| 231 | // see #9081 comment 6
|
|---|
| 232 | - EastNorth c = node.getEastNorth();
|
|---|
| 233 | - double[] angle = IntStream.range(0, 4)
|
|---|
| 234 | + final EastNorth c = node.getEastNorth();
|
|---|
| 235 | + final double[] angle = IntStream.range(0, 4)
|
|---|
| 236 | .mapToDouble(i -> PolarCoor.computeAngle(neighbors.get(i).getEastNorth(), c)).toArray();
|
|---|
| 237 | - double[] deltaAngle = new double[3];
|
|---|
| 238 | + final double[] deltaAngle = new double[3];
|
|---|
| 239 | for (int i = 0; i < 3; i++) {
|
|---|
| 240 | deltaAngle[i] = angle[i+1] - angle[0];
|
|---|
| 241 | - if (deltaAngle[i] < 0)
|
|---|
| 242 | - deltaAngle[i] += 2*Math.PI;
|
|---|
| 243 | + if (deltaAngle[i] < 0) {
|
|---|
| 244 | + deltaAngle[i] += 2*Math.PI;
|
|---|
| 245 | + }
|
|---|
| 246 | }
|
|---|
| 247 | int nb = 0;
|
|---|
| 248 | - if (deltaAngle[1] < deltaAngle[0]) nb++;
|
|---|
| 249 | - if (deltaAngle[2] < deltaAngle[0]) nb++;
|
|---|
| 250 | + if (deltaAngle[1] < deltaAngle[0]) {
|
|---|
| 251 | + nb++;
|
|---|
| 252 | + }
|
|---|
| 253 | + if (deltaAngle[2] < deltaAngle[0]) {
|
|---|
| 254 | + nb++;
|
|---|
| 255 | + }
|
|---|
| 256 | if (nb == 1) {
|
|---|
| 257 | // Align along [neighbors[0], neighbors[1]] and [neighbors[0], neighbors[2]]
|
|---|
| 258 | lines.add(new Line(neighbors.get(0), neighbors.get(1)));
|
|---|
| 259 | @@ -332,8 +349,9 @@
|
|---|
| 260 | lines.add(new Line(neighbors.get(0), neighbors.get(2)));
|
|---|
| 261 | lines.add(new Line(neighbors.get(1), neighbors.get(3)));
|
|---|
| 262 | }
|
|---|
| 263 | - } else
|
|---|
| 264 | - throw new InvalidSelection("cannot treat more than 4 neighbours, got "+neighbors.size());
|
|---|
| 265 | + } else {
|
|---|
| 266 | + throw new InvalidSelection("cannot treat more than 4 neighbours, got "+neighbors.size());
|
|---|
| 267 | + }
|
|---|
| 268 | }
|
|---|
| 269 | return lines;
|
|---|
| 270 | }
|
|---|
| 271 | @@ -346,10 +364,11 @@
|
|---|
| 272 | * @throws InvalidSelection if more than 2 lines
|
|---|
| 273 | */
|
|---|
| 274 | private static Command alignSingleNode(Node node, List<Line> lines) throws InvalidSelection {
|
|---|
| 275 | - if (lines.size() == 1)
|
|---|
| 276 | - return lines.get(0).projectionCommand(node);
|
|---|
| 277 | - else if (lines.size() == 2)
|
|---|
| 278 | - return lines.get(0).intersectionCommand(node, lines.get(1));
|
|---|
| 279 | + if (lines.size() == 1) {
|
|---|
| 280 | + return lines.get(0).projectionCommand(node);
|
|---|
| 281 | + } else if (lines.size() == 2) {
|
|---|
| 282 | + return lines.get(0).intersectionCommand(node, lines.get(1));
|
|---|
| 283 | + }
|
|---|
| 284 | throw new InvalidSelection();
|
|---|
| 285 | }
|
|---|
| 286 |
|
|---|
| 287 | @@ -378,18 +397,24 @@
|
|---|
| 288 | * @throws InvalidSelection if nodes have same coordinates
|
|---|
| 289 | */
|
|---|
| 290 | Line(Node first, Node last) throws InvalidSelection {
|
|---|
| 291 | - xM = first.getEastNorth().getX();
|
|---|
| 292 | - yM = first.getEastNorth().getY();
|
|---|
| 293 | - double xB = last.getEastNorth().getX();
|
|---|
| 294 | - double yB = last.getEastNorth().getY();
|
|---|
| 295 | - a = yB - yM;
|
|---|
| 296 | - b = xM - xB;
|
|---|
| 297 | - double norm = Math.sqrt(a*a + b*b);
|
|---|
| 298 | - if (norm == 0)
|
|---|
| 299 | - throw new InvalidSelection("Nodes have same coordinates!");
|
|---|
| 300 | - a /= norm;
|
|---|
| 301 | - b /= norm;
|
|---|
| 302 | - c = -(a*xM + b*yM);
|
|---|
| 303 | + final var coordFirst = first.getEastNorth();
|
|---|
| 304 | + xM = coordFirst.getX();
|
|---|
| 305 | + yM = coordFirst.getY();
|
|---|
| 306 | +
|
|---|
| 307 | + final var coordLast = last.getEastNorth();
|
|---|
| 308 | + final double xB = coordLast.getX();
|
|---|
| 309 | + final double yB = coordLast.getY();
|
|---|
| 310 | +
|
|---|
| 311 | +
|
|---|
| 312 | + this.a = yB - yM;
|
|---|
| 313 | + this.b = xM - xB;
|
|---|
| 314 | + final double norm = Math.hypot(this.a, this.b);
|
|---|
| 315 | + if (norm == 0) {
|
|---|
| 316 | + throw new InvalidSelection("Nodes have same coordinates!");
|
|---|
| 317 | + }
|
|---|
| 318 | + this.a /= norm;
|
|---|
| 319 | + this.b /= norm;
|
|---|
| 320 | + this.c = -(this.a * this.xM + this.b * this.yM);
|
|---|
| 321 | }
|
|---|
| 322 |
|
|---|
| 323 | /**
|
|---|
| 324 | @@ -407,7 +432,7 @@
|
|---|
| 325 | * @return The command that do the projection of this node
|
|---|
| 326 | */
|
|---|
| 327 | public Command projectionCommand(Node n) {
|
|---|
| 328 | - double s = (xM - n.getEastNorth().getX()) * a + (yM - n.getEastNorth().getY()) * b;
|
|---|
| 329 | + final double s = (xM - n.getEastNorth().getX()) * a + (yM - n.getEastNorth().getY()) * b;
|
|---|
| 330 | return new MoveCommand(n, a*s, b*s);
|
|---|
| 331 | }
|
|---|
| 332 |
|
|---|
| 333 | @@ -419,19 +444,22 @@
|
|---|
| 334 | * @throws InvalidSelection if two parallels ways found
|
|---|
| 335 | */
|
|---|
| 336 | public Command intersectionCommand(Node n, Line other) throws InvalidSelection {
|
|---|
| 337 | - double d = this.a * other.b - other.a * this.b;
|
|---|
| 338 | - if (Math.abs(d) < 10e-6)
|
|---|
| 339 | - // parallels lines
|
|---|
| 340 | - throw new InvalidSelection(tr("Two parallels ways found. Abort."));
|
|---|
| 341 | - double x = (this.b * other.c - other.b * this.c) / d;
|
|---|
| 342 | - double y = (other.a * this.c - this.a * other.c) / d;
|
|---|
| 343 | - return new MoveCommand(n, x - n.getEastNorth().getX(), y - n.getEastNorth().getY());
|
|---|
| 344 | + final double d = this.a * other.b - other.a * this.b;
|
|---|
| 345 | + if (Math.abs(d) < 10e-6) {
|
|---|
| 346 | + // parallels lines
|
|---|
| 347 | + throw new InvalidSelection(tr("Two parallel ways found. Abort."));
|
|---|
| 348 | + }
|
|---|
| 349 | + final double x = (this.b * other.c - other.b * this.c) / d;
|
|---|
| 350 | + final double y = (other.a * this.c - this.a * other.c) / d;
|
|---|
| 351 | +
|
|---|
| 352 | + final var eastNorth = n.getEastNorth();
|
|---|
| 353 | + return new MoveCommand(n, x - eastNorth.getX(), y - eastNorth.getY());
|
|---|
| 354 | }
|
|---|
| 355 | }
|
|---|
| 356 |
|
|---|
| 357 | @Override
|
|---|
| 358 | protected void updateEnabledState() {
|
|---|
| 359 | - DataSet ds = getLayerManager().getEditDataSet();
|
|---|
| 360 | + final DataSet ds = getLayerManager().getEditDataSet();
|
|---|
| 361 | setEnabled(ds != null && !ds.selectionEmpty());
|
|---|
| 362 | }
|
|---|
| 363 |
|
|---|