Changeset 35975 in osm for applications/editors/josm/plugins/tracer2
- Timestamp:
- 2022-06-13T19:51:10+02:00 (3 years ago)
- Location:
- applications/editors/josm/plugins/tracer2
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/tracer2/build.xml
r34564 r35975 5 5 <property name="commit.message" value="see #josm11090"/> 6 6 <!-- enter the *lowest* JOSM version this plugin is currently compatible with --> 7 <property name="plugin.main.version" value="1 4153"/>7 <property name="plugin.main.version" value="18464"/> 8 8 9 9 <!-- Configure these properties (replace "..." accordingly). -
applications/editors/josm/plugins/tracer2/src/org/openstreetmap/josm/plugins/tracer2/ConnectWays.java
r34976 r35975 16 16 import org.openstreetmap.josm.command.MoveCommand; 17 17 import org.openstreetmap.josm.command.SequenceCommand; 18 import org.openstreetmap.josm.data.coor.ILatLon; 18 19 import org.openstreetmap.josm.data.coor.LatLon; 19 20 import org.openstreetmap.josm.data.osm.BBox; … … 29 30 public final class ConnectWays { 30 31 31 private ConnectWays() { 32 // Hide default constructor for utilities classes 33 } 34 35 // CHECKSTYLE.OFF: SingleSpaceSeparator 36 static double s_dMinDistance = 0.000006; // Minimal distance, for objects 37 static double s_dMinDistanceN2N = 0.0000005; // Minimal distance, when nodes are merged 38 static double s_dMinDistanceN2oW = 0.000001; // Minimal distance, when node is connected to other way 39 static double s_dMinDistanceN2tW = 0.000001; // Minimal distance, when other node is connected this way 40 static final double MAX_ANGLE = 30; // Minimal angle, when other node is connected this way 41 // CHECKSTYLE.ON: SingleSpaceSeparator 42 43 static Way s_oWay; 44 static Way s_oWayOld; 45 static List<Way> s_oWays; 46 static List<Node> s_oNodes; 47 48 static ServerParam s_oParam; 49 static boolean s_bCtrl; 50 static boolean s_bAlt; 51 52 static boolean s_bAddNewWay; 53 54 private static void calcDistance() { 55 double dTileSize = Double.parseDouble(s_oParam.getTileSize()); 56 double dResolution = Double.parseDouble(s_oParam.getResolution()); 57 double dMin = dTileSize / dResolution; 58 59 s_dMinDistance = dMin * 30; 60 s_dMinDistanceN2N = dMin * 2.5; 61 s_dMinDistanceN2oW = dMin * 5; 62 s_dMinDistanceN2tW = dMin * 5; 63 } 64 65 private static void getWays(Way way) { 66 BBox bbox = new BBox(way); 67 bbox.addPrimitive(way, s_dMinDistance); 68 s_oWays = MainApplication.getLayerManager().getEditDataSet().searchWays(bbox); 69 } 70 71 private static List<Way> getWaysOfNode(Node node) { 72 List<Way> ways; 73 ways = new LinkedList<>(Utils.filteredCollection(node.getReferrers(), Way.class)); 74 return ways; 75 } 76 77 private static void getNodes(Way way) { 78 BBox bbox = new BBox(way); 79 bbox.addPrimitive(way, s_dMinDistance); 80 s_oNodes = MainApplication.getLayerManager().getEditDataSet().searchNodes(bbox); 81 } 82 83 private static double calcAlpha(LatLon oP1, Node n) { 84 LatLon oP2 = n.getCoor(); 85 86 double dAlpha = Math.atan((oP2.getY() - oP1.getY()) / (oP2.getX() - oP1.getX())) * 180 / Math.PI + (oP1.getX() > oP2.getX() ? 180 : 0); 87 return checkAlpha(dAlpha); 88 } 89 90 private static Double checkAlpha(Double dAlpha) { 91 if (dAlpha > 180) { 92 return dAlpha - 360; 93 } 94 if (dAlpha <= -180) { 95 return dAlpha + 360; 96 } 97 return dAlpha; 98 } 99 100 private static boolean isNodeInsideWay(LatLon pos, Way way) { 101 List<Node> listNode = way.getNodes(); 102 103 double dAlpha; 104 double dAlphaOld = calcAlpha(pos, listNode.get(listNode.size()-1)); 105 double dSumAlpha = 0; 106 107 for (Node n : listNode) { 108 dAlpha = calcAlpha(pos, n); 109 dSumAlpha += checkAlpha(dAlpha - dAlphaOld); 110 dAlphaOld = dAlpha; 111 } 112 dSumAlpha = Math.abs(dSumAlpha); 113 114 return dSumAlpha > 359 && dSumAlpha < 361; 115 } 116 117 private static Way getOldWay(LatLon pos) { 118 int i; 119 120 for (i = 0; i < s_oWays.size(); i++) { 121 Way way = s_oWays.get(i); 122 if (!isSameTag(way)) { 123 continue; 124 } 125 if (isNodeInsideWay(pos, way)) { 126 s_oWays.remove(way); 127 return way; 128 } 129 } 130 return null; 131 } 132 133 /** 134 * Try connect way to other buildings. 135 * @param way Way to connect. 136 * @return Commands. 137 */ 138 public static Command connect(Way newWay, LatLon pos, ServerParam param, boolean ctrl, boolean alt) { 139 LinkedList<Command> cmds = new LinkedList<>(); 140 LinkedList<Command> cmds2 = new LinkedList<>(); 141 142 s_oParam = param; 143 s_bCtrl = ctrl; 144 s_bAlt = alt; 145 146 boolean bAddWay = false; 147 148 calcDistance(); 149 getNodes(newWay); 150 getWays(newWay); 151 152 s_oWayOld = getOldWay(pos); 153 154 if (s_oWayOld == null) { 155 s_bAddNewWay = true; 156 //cmds.add(new AddCommand(newWay)); 157 bAddWay = true; 158 s_oWayOld = newWay; 159 s_oWay = new Way(newWay); 160 } else { 161 int i; 162 Way tempWay; 163 s_bAddNewWay = false; 164 165 //Main.main.getCurrentDataSet().setSelected(m_wayOld); 166 167 tempWay = new Way(s_oWayOld); 168 169 for (i = 0; i < newWay.getNodesCount(); i++) { 170 tempWay.addNode(tempWay.getNodesCount(), newWay.getNode(i)); 171 } 172 i++; 173 for (i = 0; i < s_oWayOld.getNodesCount() - 1; i++) { 174 tempWay.removeNode(s_oWayOld.getNode(i)); 175 } 176 //cmds.add(new ChangeCommand(m_wayOld, tempWay)); 177 for (i = 0; i < s_oWayOld.getNodesCount() - 1; i++) { 178 Node n = s_oWayOld.getNode(i); 179 List<Way> ways = getWaysOfNode(n); 180 if (ways.size() <= 1) { 181 cmds2.add(new DeleteCommand(s_oWayOld.getNode(i))); 182 } 183 s_oNodes.remove(s_oWayOld.getNode(i)); 184 } 185 s_oWay = tempWay; 186 } 187 188 cmds2.addAll(connectTo()); 189 DataSet ds = MainApplication.getLayerManager().getEditDataSet(); 190 191 // add new Node 192 Node firstNode = null; 193 Way way = new Way(s_oWay); 194 for (Node node : s_oWay.getNodes()) { 195 if (node.getDataSet() != null) { 196 way.removeNode(node); 197 } 198 } 199 if (way.getNodes().size() > 0) { 200 if (way.firstNode() != way.lastNode()) { 201 way.addNode(way.firstNode()); 202 } 203 for (Node node : way.getNodes()) { 204 if (firstNode == null || firstNode != node) { 205 cmds.add(new AddCommand(ds, node)); 206 } 207 if (firstNode == null) { 208 firstNode = node; 209 } 210 } 211 } 212 213 // add new way 214 if (bAddWay == true) { 215 cmds.add(new AddCommand(ds, s_oWay)); 216 } 217 218 cmds.add(new ChangeCommand(ds, s_oWayOld, trySplitWayByAnyNodes(s_oWay))); 219 cmds.addAll(cmds2); 220 221 TracerDebug oTracerDebug = new TracerDebug(); 222 oTracerDebug.OutputCommands(cmds); 223 224 Command cmd = new SequenceCommand(tr("Merge objects nodes"), cmds); 225 226 return cmd; 227 } 228 229 230 /** 231 * Try connect way to other buildings. 232 * @param way Way to connect. 233 * @return Commands. 234 */ 235 public static List<Command> connectTo() { 236 Map<Way, Way> modifiedWays = new HashMap<>(); 237 LinkedList<Command> cmds = new LinkedList<>(); 238 Way way = new Way(s_oWay); 239 for (int i = 0; i < way.getNodesCount() - 1; i++) { 240 Node n = way.getNode(i); 241 System.out.println("-------"); 242 System.out.println("Node: " + n); 243 LatLon ll = n.getCoor(); 244 //BBox bbox = new BBox( 245 // ll.getX() - MIN_DISTANCE, 246 // ll.getY() - MIN_DISTANCE, 247 // ll.getX() + MIN_DISTANCE, 248 // ll.getY() + MIN_DISTANCE); 249 250 // bude se node slucovat s jinym? 251 double minDistanceSq = s_dMinDistanceN2N; 252 //List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(bbox); 253 Node nearestNode = null; 254 for (Node nn : s_oNodes) { 255 System.out.println("Node: " + nn); 256 if (!nn.isUsable() || way.containsNode(nn) || s_oWay.containsNode(nn) || !isInSameTag(nn)) { 257 continue; 258 } 259 double dist = nn.getCoor().distance(ll); 260 if (dist < minDistanceSq) { 261 minDistanceSq = dist; 262 nearestNode = nn; 263 } 264 } 265 266 System.out.println("Nearest: " + nearestNode + " distance: " + minDistanceSq); 267 if (nearestNode == null) { 268 tryConnectNodeToAnyWay(n, modifiedWays); 269 } else { 270 System.out.println("+add Node distance: " + minDistanceSq); 271 cmds.addAll(mergeNodes(n, nearestNode)); 272 } 273 } 274 275 for (Map.Entry<Way, Way> e : modifiedWays.entrySet()) { 276 cmds.add(new ChangeCommand(e.getKey(), e.getValue())); 277 } 278 279 //cmds.addFirst(new ChangeCommand(way, trySplitWayByAnyNodes(newWay))); 280 281 List<Command> cmd = cmds; 282 return cmd; 283 } 284 285 /** 286 * Merges two nodes 287 * @param n1 First node 288 * @param n2 Second node 289 * @param way Way containing first node 290 * @return List of Commands. 291 */ 292 private static List<Command> mergeNodes(Node n1, Node n2) { 293 List<Command> cmds = new LinkedList<>(); 294 cmds.add(new MoveCommand(n2, 295 (n1.getEastNorth().getX() - n2.getEastNorth().getX())/2, 296 (n1.getEastNorth().getY() - n2.getEastNorth().getY())/2 297 )); 298 299 Way newWay = new Way(s_oWay); 300 301 int j = s_oWay.getNodes().indexOf(n1); 302 newWay.addNode(j, n2); 303 if (j == 0) { 304 // first + last point 305 newWay.addNode(newWay.getNodesCount(), n2); 306 } 307 308 newWay.removeNode(n1); 309 // cmds.add(new ChangeCommand(m_way, newWay)); 310 311 if (newWay.firstNode() != newWay.lastNode()) { 312 newWay.addNode(newWay.firstNode()); 313 } 314 s_oWay = new Way(newWay); 315 316 //cmds.add(new DeleteCommand(n1)); 317 return cmds; 318 } 319 320 /** 321 * Try connect node "node" to way of other building. 322 * 323 * Zkusi zjistit, zda node neni tak blizko nejake usecky existujici budovy, 324 * ze by mel byt zacnenen do teto usecky. Pokud ano, provede to. 325 * 326 * @param node Node to connect. 327 * @return List of Commands. 328 */ 329 private static void tryConnectNodeToAnyWay(Node node, Map<Way, Way> m) 330 throws IllegalStateException, IndexOutOfBoundsException { 331 332 //List<Command> cmds = new LinkedList<Command>(); 333 334 LatLon ll = node.getCoor(); 335 //BBox bbox = new BBox( 336 // ll.getX() - MIN_DISTANCE_TW, 337 // ll.getY() - MIN_DISTANCE_TW, 338 // ll.getX() + MIN_DISTANCE_TW, 339 // ll.getY() + MIN_DISTANCE_TW); 340 341 // node nebyl slouceny s jinym 342 // hledani pripadne blizke usecky, kam bod pridat 343 //List<Way> ways = Main.main.getCurrentDataSet().searchWays(bbox); 344 double minDist = Double.MAX_VALUE; 345 Way nearestWay = null; 346 int nearestNodeIndex = 0; 347 for (Way ww : s_oWays) { 348 System.out.println("Way: " + ww); 349 if (!ww.isUsable() || ww.containsNode(node) || !isSameTag(ww)) { 350 continue; 351 } 352 353 if (m.get(ww) != null) { 354 ww = m.get(ww); 355 } 356 357 for (Pair<Node, Node> np : ww.getNodePairs(false)) { 358 //double dist1 = TracerGeometry.distanceFromSegment(ll, np.a.getCoor(), np.b.getCoor()); 359 double dist = distanceFromSegment2(ll, np.a.getCoor(), np.b.getCoor()); 360 //System.out.println(" distance: " + dist1 + " " + dist); 361 362 if (dist < minDist) { 363 minDist = dist; 364 nearestWay = ww; 365 nearestNodeIndex = ww.getNodes().indexOf(np.a); 366 } 367 } 368 } 369 System.out.println("Nearest way: " + nearestWay + " distance: " + minDist); 370 if (minDist < s_dMinDistanceN2oW) { 371 Way newNWay = new Way(nearestWay); 372 373 newNWay.addNode(nearestNodeIndex + 1, node); 374 System.out.println("New way:" + newNWay); 375 System.out.println("+add WayOld.Node distance: " + minDist); 376 m.put(nearestWay, newNWay); 377 s_oWays.remove(newNWay); 378 s_oWays.add(nearestWay); 379 } 380 } 381 382 private static double distanceFromSegment2(LatLon c, LatLon a, LatLon b) { 383 double x; 384 double y; 385 386 StraightLine oStraightLine1 = new StraightLine( 387 new Point2D.Double(a.getX(), a.getY()), 388 new Point2D.Double(b.getX(), b.getY())); 389 StraightLine oStraightLine2 = new StraightLine( 390 new Point2D.Double(c.getX(), c.getY()), 391 new Point2D.Double(c.getX() + (a.getY()-b.getY()), c.getY() - (a.getX()-b.getX()))); 392 Point2D.Double oPoint = oStraightLine1.GetIntersectionPoint(oStraightLine2); 393 394 if ((oPoint.x > a.getX() && oPoint.x > b.getX()) || (oPoint.x < a.getX() && oPoint.x < b.getX()) || 395 (oPoint.y > a.getY() && oPoint.y > b.getY()) || (oPoint.y < a.getY() && oPoint.y < b.getY())) { 396 return 100000; 397 } 398 399 x = c.getX()-oPoint.getX(); 400 y = c.getY()-oPoint.getY(); 401 402 return Math.sqrt((x*x)+(y*y)); 403 } 404 405 /** 406 * Try split way by any existing building nodes. 407 * 408 * Zkusi zjistit zda nejake usecka z way by nemela prochazet nejakym existujicim bodem, 409 * ktery je ji velmi blizko. Pokud ano, tak puvodni usecku rozdeli na dve tak, aby 410 * prochazela takovym bodem. 411 * 412 * @param way Way to split. 413 * @return Modified way 414 */ 415 private static Way trySplitWayByAnyNodes(Way way) 416 throws IndexOutOfBoundsException, IllegalStateException { 417 418 // projdi kazdou novou usecku a zjisti, zda by nemela vest pres existujici body 419 int i = 0; 420 while (i < way.getNodesCount()) { 421 // usecka n1, n2 422 LatLon n1 = way.getNodes().get(i).getCoor(); 423 LatLon n2 = way.getNodes().get((i + 1) % way.getNodesCount()).getCoor(); 424 System.out.println(way.getNodes().get(i) + "-----" + way.getNodes().get((i + 1) % way.getNodesCount())); 425 double minDistanceSq = Double.MAX_VALUE; 426 // double maxAngle = MAX_ANGLE; 427 //List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(new BBox( 428 // Math.min(n1.getX(), n2.getX()) - minDistanceSq, 429 // Math.min(n1.getY(), n2.getY()) - minDistanceSq, 430 // Math.max(n1.getX(), n2.getX()) + minDistanceSq, 431 // Math.max(n1.getY(), n2.getY()) + minDistanceSq 432 //)); 433 434 Node nearestNode = null; 435 for (Node nod : s_oNodes) { 436 if (!nod.isUsable() || way.containsNode(nod) || !isInSameTag(nod)) { 437 continue; 438 } 439 LatLon nn = nod.getCoor(); 440 //double dist = TracerGeometry.distanceFromSegment(nn, n1, n2); 441 double dist = distanceFromSegment2(nn, n1, n2); 442 // double angle = TracerGeometry.angleOfLines(n1, nn, nn, n2); 443 //System.out.println("Angle: " + angle + " distance: " + dist + " Node: " + nod); 444 if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq) { // && Math.abs(angle) < maxAngle) { 445 minDistanceSq = dist; 446 // maxAngle = angle; 447 nearestNode = nod; 448 } 449 } 450 System.out.println("Nearest_: " + nearestNode + " distance: " + minDistanceSq); 451 if (nearestNode == null || minDistanceSq >= s_dMinDistanceN2tW) { 452 // tato usecka se nerozdeli 453 i++; 454 System.out.println(""); 455 continue; 456 } else { 457 // rozdeleni usecky 458 way.addNode(i + 1, nearestNode); 459 i++; 460 System.out.println("+add Way.Node distance: " + minDistanceSq); 461 System.out.println(""); 462 //i++; 463 continue; // i nezvetsuji, treba bude treba rozdelit usecku znovu 464 } 465 } 466 return way; 467 } 468 469 private static boolean isInSameTag(Node n) { 470 for (OsmPrimitive op : n.getReferrers()) { 471 if (op instanceof Way) { 472 if (isSameTag(op)) { 473 return true; 474 } 475 } 476 } 477 return false; 478 } 479 480 /** 481 * Determines if the specified primitive denotes a building. 482 * @param p The primitive to be tested 483 * @return True if building key is set and different from no,entrance 484 */ 485 protected static boolean isSameTag(OsmPrimitive p) { 486 String v = p.get(s_oParam.getTag()); 487 if (s_bCtrl || s_oParam.getTag().equals("")) { 488 return v == null || v.equals("no"); 489 } 490 if (s_oParam.getTag().equals("building")) { 491 return v != null && !v.equals("no") && !v.equals("entrance"); 492 } 493 return v != null && !v.equals("no"); 494 } 32 private ConnectWays() { 33 // Hide default constructor for utilities classes 34 } 35 36 // CHECKSTYLE.OFF: SingleSpaceSeparator 37 static double s_dMinDistance = 0.000006; // Minimal distance, for objects 38 static double s_dMinDistanceN2N = 0.0000005; // Minimal distance, when nodes are merged 39 static double s_dMinDistanceN2oW = 0.000001; // Minimal distance, when node is connected to other way 40 static double s_dMinDistanceN2tW = 0.000001; // Minimal distance, when other node is connected this way 41 static final double MAX_ANGLE = 30; // Minimal angle, when other node is connected this way 42 // CHECKSTYLE.ON: SingleSpaceSeparator 43 44 static Way s_oWay; 45 static Way s_oWayOld; 46 static List<Way> s_oWays; 47 static List<Node> s_oNodes; 48 49 static ServerParam s_oParam; 50 static boolean s_bCtrl; 51 static boolean s_bAlt; 52 53 static boolean s_bAddNewWay; 54 55 private static void calcDistance() { 56 double dTileSize = Double.parseDouble(s_oParam.getTileSize()); 57 double dResolution = Double.parseDouble(s_oParam.getResolution()); 58 double dMin = dTileSize / dResolution; 59 60 s_dMinDistance = dMin * 30; 61 s_dMinDistanceN2N = dMin * 2.5; 62 s_dMinDistanceN2oW = dMin * 5; 63 s_dMinDistanceN2tW = dMin * 5; 64 } 65 66 private static void getWays(Way way) { 67 BBox bbox = new BBox(way); 68 bbox.addPrimitive(way, s_dMinDistance); 69 s_oWays = MainApplication.getLayerManager().getEditDataSet().searchWays(bbox); 70 } 71 72 private static List<Way> getWaysOfNode(Node node) { 73 List<Way> ways; 74 ways = new LinkedList<>(Utils.filteredCollection(node.getReferrers(), Way.class)); 75 return ways; 76 } 77 78 private static void getNodes(Way way) { 79 BBox bbox = new BBox(way); 80 bbox.addPrimitive(way, s_dMinDistance); 81 s_oNodes = MainApplication.getLayerManager().getEditDataSet().searchNodes(bbox); 82 } 83 84 private static double calcAlpha(LatLon oP1, Node n) { 85 LatLon oP2 = n.getCoor(); 86 87 double dAlpha = Math.atan((oP2.getY() - oP1.getY()) / (oP2.getX() - oP1.getX())) * 180 / Math.PI + (oP1.getX() > oP2.getX() ? 180 : 0); 88 return checkAlpha(dAlpha); 89 } 90 91 private static Double checkAlpha(Double dAlpha) { 92 if (dAlpha > 180) { 93 return dAlpha - 360; 94 } 95 if (dAlpha <= -180) { 96 return dAlpha + 360; 97 } 98 return dAlpha; 99 } 100 101 private static boolean isNodeInsideWay(LatLon pos, Way way) { 102 List<Node> listNode = way.getNodes(); 103 104 double dAlpha; 105 double dAlphaOld = calcAlpha(pos, listNode.get(listNode.size()-1)); 106 double dSumAlpha = 0; 107 108 for (Node n : listNode) { 109 dAlpha = calcAlpha(pos, n); 110 dSumAlpha += checkAlpha(dAlpha - dAlphaOld); 111 dAlphaOld = dAlpha; 112 } 113 dSumAlpha = Math.abs(dSumAlpha); 114 115 return dSumAlpha > 359 && dSumAlpha < 361; 116 } 117 118 private static Way getOldWay(LatLon pos) { 119 int i; 120 121 for (i = 0; i < s_oWays.size(); i++) { 122 Way way = s_oWays.get(i); 123 if (!isSameTag(way)) { 124 continue; 125 } 126 if (isNodeInsideWay(pos, way)) { 127 s_oWays.remove(way); 128 return way; 129 } 130 } 131 return null; 132 } 133 134 /** 135 * Try connect way to other buildings. 136 * @param way Way to connect. 137 * @return Commands. 138 */ 139 public static Command connect(Way newWay, LatLon pos, ServerParam param, boolean ctrl, boolean alt) { 140 LinkedList<Command> cmds = new LinkedList<>(); 141 LinkedList<Command> cmds2 = new LinkedList<>(); 142 143 s_oParam = param; 144 s_bCtrl = ctrl; 145 s_bAlt = alt; 146 147 boolean bAddWay = false; 148 149 calcDistance(); 150 getNodes(newWay); 151 getWays(newWay); 152 153 s_oWayOld = getOldWay(pos); 154 155 if (s_oWayOld == null) { 156 s_bAddNewWay = true; 157 //cmds.add(new AddCommand(newWay)); 158 bAddWay = true; 159 s_oWayOld = newWay; 160 s_oWay = new Way(newWay); 161 } else { 162 int i; 163 Way tempWay; 164 s_bAddNewWay = false; 165 166 //Main.main.getCurrentDataSet().setSelected(m_wayOld); 167 168 tempWay = new Way(s_oWayOld); 169 170 for (i = 0; i < newWay.getNodesCount(); i++) { 171 tempWay.addNode(tempWay.getNodesCount(), newWay.getNode(i)); 172 } 173 i++; 174 for (i = 0; i < s_oWayOld.getNodesCount() - 1; i++) { 175 tempWay.removeNode(s_oWayOld.getNode(i)); 176 } 177 //cmds.add(new ChangeCommand(m_wayOld, tempWay)); 178 for (i = 0; i < s_oWayOld.getNodesCount() - 1; i++) { 179 Node n = s_oWayOld.getNode(i); 180 List<Way> ways = getWaysOfNode(n); 181 if (ways.size() <= 1) { 182 cmds2.add(new DeleteCommand(s_oWayOld.getNode(i))); 183 } 184 s_oNodes.remove(s_oWayOld.getNode(i)); 185 } 186 s_oWay = tempWay; 187 } 188 189 cmds2.addAll(connectTo()); 190 DataSet ds = MainApplication.getLayerManager().getEditDataSet(); 191 192 // add new Node 193 Node firstNode = null; 194 Way way = new Way(s_oWay); 195 for (Node node : s_oWay.getNodes()) { 196 if (node.getDataSet() != null) { 197 way.removeNode(node); 198 } 199 } 200 if (way.getNodes().size() > 0) { 201 if (way.firstNode() != way.lastNode()) { 202 way.addNode(way.firstNode()); 203 } 204 for (Node node : way.getNodes()) { 205 if (firstNode == null || firstNode != node) { 206 cmds.add(new AddCommand(ds, node)); 207 } 208 if (firstNode == null) { 209 firstNode = node; 210 } 211 } 212 } 213 214 // add new way 215 if (bAddWay == true) { 216 cmds.add(new AddCommand(ds, s_oWay)); 217 } 218 219 cmds.add(new ChangeCommand(ds, s_oWayOld, trySplitWayByAnyNodes(s_oWay))); 220 cmds.addAll(cmds2); 221 222 TracerDebug oTracerDebug = new TracerDebug(); 223 oTracerDebug.OutputCommands(cmds); 224 225 Command cmd = new SequenceCommand(tr("Merge objects nodes"), cmds); 226 227 return cmd; 228 } 229 230 231 /** 232 * Try connect way to other buildings. 233 * @param way Way to connect. 234 * @return Commands. 235 */ 236 public static List<Command> connectTo() { 237 Map<Way, Way> modifiedWays = new HashMap<>(); 238 LinkedList<Command> cmds = new LinkedList<>(); 239 Way way = new Way(s_oWay); 240 for (int i = 0; i < way.getNodesCount() - 1; i++) { 241 Node n = way.getNode(i); 242 System.out.println("-------"); 243 System.out.println("Node: " + n); 244 LatLon ll = n.getCoor(); 245 //BBox bbox = new BBox( 246 // ll.getX() - MIN_DISTANCE, 247 // ll.getY() - MIN_DISTANCE, 248 // ll.getX() + MIN_DISTANCE, 249 // ll.getY() + MIN_DISTANCE); 250 251 // bude se node slucovat s jinym? 252 double minDistanceSq = s_dMinDistanceN2N; 253 //List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(bbox); 254 Node nearestNode = null; 255 for (Node nn : s_oNodes) { 256 System.out.println("Node: " + nn); 257 if (!nn.isUsable() || way.containsNode(nn) || s_oWay.containsNode(nn) || !isInSameTag(nn)) { 258 continue; 259 } 260 double dist = nn.getCoor().distance(ll); 261 if (dist < minDistanceSq) { 262 minDistanceSq = dist; 263 nearestNode = nn; 264 } 265 } 266 267 System.out.println("Nearest: " + nearestNode + " distance: " + minDistanceSq); 268 if (nearestNode == null) { 269 tryConnectNodeToAnyWay(n, modifiedWays); 270 } else { 271 System.out.println("+add Node distance: " + minDistanceSq); 272 cmds.addAll(mergeNodes(n, nearestNode)); 273 } 274 } 275 276 for (Map.Entry<Way, Way> e : modifiedWays.entrySet()) { 277 cmds.add(new ChangeCommand(e.getKey(), e.getValue())); 278 } 279 280 //cmds.addFirst(new ChangeCommand(way, trySplitWayByAnyNodes(newWay))); 281 282 List<Command> cmd = cmds; 283 return cmd; 284 } 285 286 /** 287 * Merges two nodes 288 * @param n1 First node 289 * @param n2 Second node 290 * @param way Way containing first node 291 * @return List of Commands. 292 */ 293 private static List<Command> mergeNodes(Node n1, Node n2) { 294 List<Command> cmds = new LinkedList<>(); 295 cmds.add(new MoveCommand(n2, 296 (n1.getEastNorth().getX() - n2.getEastNorth().getX())/2, 297 (n1.getEastNorth().getY() - n2.getEastNorth().getY())/2 298 )); 299 300 Way newWay = new Way(s_oWay); 301 302 int j = s_oWay.getNodes().indexOf(n1); 303 newWay.addNode(j, n2); 304 if (j == 0) { 305 // first + last point 306 newWay.addNode(newWay.getNodesCount(), n2); 307 } 308 309 newWay.removeNode(n1); 310 // cmds.add(new ChangeCommand(m_way, newWay)); 311 312 if (newWay.firstNode() != newWay.lastNode()) { 313 newWay.addNode(newWay.firstNode()); 314 } 315 s_oWay = new Way(newWay); 316 317 //cmds.add(new DeleteCommand(n1)); 318 return cmds; 319 } 320 321 /** 322 * Try connect node "node" to way of other building. 323 * 324 * Zkusi zjistit, zda node neni tak blizko nejake usecky existujici budovy, 325 * ze by mel byt zacnenen do teto usecky. Pokud ano, provede to. 326 * 327 * @param node Node to connect. 328 * @return List of Commands. 329 */ 330 private static void tryConnectNodeToAnyWay(Node node, Map<Way, Way> m) 331 throws IllegalStateException, IndexOutOfBoundsException { 332 333 //List<Command> cmds = new LinkedList<Command>(); 334 335 LatLon ll = node.getCoor(); 336 //BBox bbox = new BBox( 337 // ll.getX() - MIN_DISTANCE_TW, 338 // ll.getY() - MIN_DISTANCE_TW, 339 // ll.getX() + MIN_DISTANCE_TW, 340 // ll.getY() + MIN_DISTANCE_TW); 341 342 // node nebyl slouceny s jinym 343 // hledani pripadne blizke usecky, kam bod pridat 344 //List<Way> ways = Main.main.getCurrentDataSet().searchWays(bbox); 345 double minDist = Double.MAX_VALUE; 346 Way nearestWay = null; 347 int nearestNodeIndex = 0; 348 for (Way ww : s_oWays) { 349 System.out.println("Way: " + ww); 350 if (!ww.isUsable() || ww.containsNode(node) || !isSameTag(ww)) { 351 continue; 352 } 353 354 if (m.get(ww) != null) { 355 ww = m.get(ww); 356 } 357 358 for (Pair<Node, Node> np : ww.getNodePairs(false)) { 359 //double dist1 = TracerGeometry.distanceFromSegment(ll, np.a.getCoor(), np.b.getCoor()); 360 double dist = distanceFromSegment2(ll, np.a.getCoor(), np.b.getCoor()); 361 //System.out.println(" distance: " + dist1 + " " + dist); 362 363 if (dist < minDist) { 364 minDist = dist; 365 nearestWay = ww; 366 nearestNodeIndex = ww.getNodes().indexOf(np.a); 367 } 368 } 369 } 370 System.out.println("Nearest way: " + nearestWay + " distance: " + minDist); 371 if (minDist < s_dMinDistanceN2oW) { 372 Way newNWay = new Way(nearestWay); 373 374 newNWay.addNode(nearestNodeIndex + 1, node); 375 System.out.println("New way:" + newNWay); 376 System.out.println("+add WayOld.Node distance: " + minDist); 377 m.put(nearestWay, newNWay); 378 s_oWays.remove(newNWay); 379 s_oWays.add(nearestWay); 380 } 381 } 382 383 private static double distanceFromSegment2(LatLon c, LatLon a, LatLon b) { 384 double x; 385 double y; 386 387 StraightLine oStraightLine1 = new StraightLine( 388 new Point2D.Double(a.getX(), a.getY()), 389 new Point2D.Double(b.getX(), b.getY())); 390 StraightLine oStraightLine2 = new StraightLine( 391 new Point2D.Double(c.getX(), c.getY()), 392 new Point2D.Double(c.getX() + (a.getY()-b.getY()), c.getY() - (a.getX()-b.getX()))); 393 Point2D.Double oPoint = oStraightLine1.GetIntersectionPoint(oStraightLine2); 394 395 if ((oPoint.x > a.getX() && oPoint.x > b.getX()) || (oPoint.x < a.getX() && oPoint.x < b.getX()) || 396 (oPoint.y > a.getY() && oPoint.y > b.getY()) || (oPoint.y < a.getY() && oPoint.y < b.getY())) { 397 return 100000; 398 } 399 400 x = c.getX()-oPoint.getX(); 401 y = c.getY()-oPoint.getY(); 402 403 return Math.sqrt((x*x)+(y*y)); 404 } 405 406 /** 407 * Try split way by any existing building nodes. 408 * 409 * Zkusi zjistit zda nejake usecka z way by nemela prochazet nejakym existujicim bodem, 410 * ktery je ji velmi blizko. Pokud ano, tak puvodni usecku rozdeli na dve tak, aby 411 * prochazela takovym bodem. 412 * 413 * @param way Way to split. 414 * @return Modified way 415 */ 416 private static Way trySplitWayByAnyNodes(Way way) 417 throws IndexOutOfBoundsException, IllegalStateException { 418 419 // projdi kazdou novou usecku a zjisti, zda by nemela vest pres existujici body 420 int i = 0; 421 while (i < way.getNodesCount()) { 422 // usecka n1, n2 423 LatLon n1 = way.getNodes().get(i).getCoor(); 424 LatLon n2 = way.getNodes().get((i + 1) % way.getNodesCount()).getCoor(); 425 System.out.println(way.getNodes().get(i) + "-----" + way.getNodes().get((i + 1) % way.getNodesCount())); 426 double minDistanceSq = Double.MAX_VALUE; 427 // double maxAngle = MAX_ANGLE; 428 //List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(new BBox( 429 // Math.min(n1.getX(), n2.getX()) - minDistanceSq, 430 // Math.min(n1.getY(), n2.getY()) - minDistanceSq, 431 // Math.max(n1.getX(), n2.getX()) + minDistanceSq, 432 // Math.max(n1.getY(), n2.getY()) + minDistanceSq 433 //)); 434 435 Node nearestNode = null; 436 for (Node nod : s_oNodes) { 437 if (!nod.isUsable() || way.containsNode(nod) || !isInSameTag(nod)) { 438 continue; 439 } 440 LatLon nn = nod.getCoor(); 441 //double dist = TracerGeometry.distanceFromSegment(nn, n1, n2); 442 double dist = distanceFromSegment2(nn, n1, n2); 443 // double angle = TracerGeometry.angleOfLines(n1, nn, nn, n2); 444 //System.out.println("Angle: " + angle + " distance: " + dist + " Node: " + nod); 445 if (!n1.equalsEpsilon(nn, ILatLon.MAX_SERVER_PRECISION) 446 && !n2.equalsEpsilon(nn, ILatLon.MAX_SERVER_PRECISION) && dist < minDistanceSq) { // && Math.abs(angle) < maxAngle) { 447 minDistanceSq = dist; 448 // maxAngle = angle; 449 nearestNode = nod; 450 } 451 } 452 System.out.println("Nearest_: " + nearestNode + " distance: " + minDistanceSq); 453 if (nearestNode == null || minDistanceSq >= s_dMinDistanceN2tW) { 454 // tato usecka se nerozdeli 455 i++; 456 System.out.println(""); 457 continue; 458 } else { 459 // rozdeleni usecky 460 way.addNode(i + 1, nearestNode); 461 i++; 462 System.out.println("+add Way.Node distance: " + minDistanceSq); 463 System.out.println(""); 464 //i++; 465 continue; // i nezvetsuji, treba bude treba rozdelit usecku znovu 466 } 467 } 468 return way; 469 } 470 471 private static boolean isInSameTag(Node n) { 472 for (OsmPrimitive op : n.getReferrers()) { 473 if (op instanceof Way) { 474 if (isSameTag(op)) { 475 return true; 476 } 477 } 478 } 479 return false; 480 } 481 482 /** 483 * Determines if the specified primitive denotes a building. 484 * @param p The primitive to be tested 485 * @return True if building key is set and different from no,entrance 486 */ 487 protected static boolean isSameTag(OsmPrimitive p) { 488 String v = p.get(s_oParam.getTag()); 489 if (s_bCtrl || s_oParam.getTag().equals("")) { 490 return v == null || v.equals("no"); 491 } 492 if (s_oParam.getTag().equals("building")) { 493 return v != null && !v.equals("no") && !v.equals("entrance"); 494 } 495 return v != null && !v.equals("no"); 496 } 495 497 496 498 }
Note:
See TracChangeset
for help on using the changeset viewer.