Ticket #5560: patch.diff
File patch.diff, 8.1 KB (added by , 14 years ago) 


src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
193 193 initialN2en.getX()  en.getX(), 194 194 initialN2en.getY()  en.getY())); 195 195 } 196 196 197 197 // Signifies that nothing has happened yet 198 198 newN1en = null; 199 199 newN2en = null; … … 305 305 306 306 //find if the new points overlap existing segments (in case of 90 degree angles) 307 307 Node prevNode = getPreviousNode(selectedSegment.lowerIndex); 308 boolean nodeOverlapsSegment = prevNode != null && pointsColinear(prevNode.getEastNorth(), initialN1en, newN1en); 308 boolean nodeOverlapsSegment = prevNode != null && segmentsParralel(initialN1en, prevNode.getEastNorth(), initialN1en, newN1en); 309 boolean hasOtherWays = this.hasNodeOtherWays(selectedSegment.getFirstNode(), selectedSegment.way); 309 310 310 if (nodeOverlapsSegment && !alwaysCreateNodes ) {311 if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) { 311 312 //move existing node 312 313 Node n1Old = selectedSegment.getFirstNode(); 313 314 cmds.add(new MoveCommand(n1Old, Main.proj.eastNorth2latlon(newN1en))); … … 321 322 322 323 //find if the new points overlap existing segments (in case of 90 degree angles) 323 324 Node nextNode = getNextNode(selectedSegment.lowerIndex + 1); 324 nodeOverlapsSegment = nextNode != null && pointsColinear(nextNode.getEastNorth(), initialN2en, newN2en); 325 nodeOverlapsSegment = nextNode != null && segmentsParralel(initialN2en, nextNode.getEastNorth(), initialN2en, newN2en); 326 hasOtherWays = this.hasNodeOtherWays(selectedSegment.getFirstNode(), selectedSegment.way); 325 327 326 if (nodeOverlapsSegment && !alwaysCreateNodes ) {328 if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) { 327 329 //move existing node 328 330 Node n2Old = selectedSegment.getSecondNode(); 329 331 cmds.add(new MoveCommand(n2Old, Main.proj.eastNorth2latlon(newN2en))); … … 361 363 } 362 364 } 363 365 366 367 /** 368 * This method tests if a node has other ways apart from the given one. 369 * @param node 370 * @param myWay 371 * @return true of node belongs only to myWay, false if there are more ways. 372 */ 373 private boolean hasNodeOtherWays(Node node, Way myWay) { 374 for (OsmPrimitive p : node.getReferrers()) { 375 if (p instanceof Way && p.isUsable() && p!= myWay) 376 return true; 377 } 378 379 return false; 380 } 381 364 382 /*** 365 383 * This method calculates offset amount by witch to move the given segment perpendicularly for it to be in line with mouse position. 366 384 * @param segmentP1 … … 368 386 * @param targetPos 369 387 * @return offset amount of P1 and P2. 370 388 */ 371 private static EastNorth calculateSegmentOffset(EastNorth segmentP1, EastNorth segmentP2 ,EastNorth moveDirection , EastNorth targetPos) 372 { 373 EastNorth intersectionPoint = getLineLineIntersection( 374 segmentP1, 375 segmentP2, 376 targetPos, 377 new EastNorth(targetPos.getX() + moveDirection.getX(), targetPos.getY() + moveDirection.getY())); 389 private static EastNorth calculateSegmentOffset(EastNorth segmentP1, EastNorth segmentP2, EastNorth moveDirection, 390 EastNorth targetPos) { 391 EastNorth intersectionPoint = getLineLineIntersection(segmentP1, segmentP2, targetPos, new EastNorth(targetPos 392 .getX() 393 + moveDirection.getX(), targetPos.getY() + moveDirection.getY())); 378 394 379 395 if (intersectionPoint == null) 380 396 return null; 381 397 else 382 398 //return distance form base to target position 383 return new EastNorth(targetPos.getX()  intersectionPoint.getX(), targetPos.getY()  intersectionPoint.getY()); 399 return new EastNorth(targetPos.getX()  intersectionPoint.getX(), targetPos.getY() 400  intersectionPoint.getY()); 384 401 } 385 402 386 403 /** 387 * Finds the intersection of two lines of inifinite length 388 * @return EastNorth null if no intersection was found, the Loncoordinates of the intersection otherwise404 * Finds the intersection of two lines of inifinite length. 405 * @return EastNorth null if no intersection was found, the coordinates of the intersection otherwise 389 406 */ 390 static public EastNorth getLineLineIntersection( 391 EastNorth p1, EastNorth p2, 392 EastNorth p3, EastNorth p4) { 407 static public EastNorth getLineLineIntersection(EastNorth p1, EastNorth p2, EastNorth p3, EastNorth p4) { 393 408 394 409 // Convert line from (point, point) form to ax+by=c 395 410 double a1 = p2.getY()  p1.getY(); … … 401 416 double c2 = p4.getX() * p3.getY()  p3.getX() * p4.getY(); 402 417 403 418 // Solve the equations 404 double det = a1*b2  a2*b1; 405 if(det == 0) return null; // Lines are parallel 419 double det = a1 * b2  a2 * b1; 420 if (det == 0) 421 return null; // Lines are parallel 406 422 407 return new EastNorth( 408 (b1*c2  b2*c1)/det, 409 (a2*c1  a1*c2)/det); 423 return new EastNorth((b1 * c2  b2 * c1) / det, (a2 * c1  a1 * c2) / det); 410 424 } 411 425 426 private static boolean segmentsParralel(EastNorth p1, EastNorth p2, EastNorth p3, EastNorth p4) { 427 428 // Convert line from (point, point) form to ax+by=c 429 double a1 = p2.getY()  p1.getY(); 430 double b1 = p1.getX()  p2.getX(); 431 432 double a2 = p4.getY()  p3.getY(); 433 double b2 = p3.getX()  p4.getX(); 434 435 // Solve the equations 436 double det = a1 * b2  a2 * b1; 437 return Math.abs(det) < 1e13; 438 } 439 412 440 /** 413 * Returns true if all points are on the same line. 441 * Calcualtes closest point to a line segment. 442 * @param segmentP1 443 * @param segmentP2 444 * @param point 445 * @return segmentP1 if it is the closest point, segmentP2 if it is the closest point, 446 * a new point if closest point is between segmentP1 and segmentP2. 414 447 */ 415 private static boolean pointsColinear(EastNorth p1, EastNorth p2, EastNorth p3) {448 private static EastNorth closestPointToSegment(EastNorth segmentP1, EastNorth segmentP2, EastNorth point) { 416 449 417 //the simple dumb way of triangle side lengths. 418 double distance1 = p1.distance(p2); 419 double distance2 = p1.distance(p3); 420 double distance3 = p2.distance(p3); 450 double ldx = segmentP2.getX()  segmentP1.getX(); 451 double ldy = segmentP2.getY()  segmentP1.getY(); 421 452 422 //sort so that distance 1 is the greatest 423 if (distance1 < distance2) { 424 double temp = distance1; 425 distance1 = distance2; 426 distance2 = temp; 427 } 453 if (ldx == 0 && ldy == 0) //segment zero length 454 return segmentP1; 428 455 429 if (distance1 < distance3) { 430 double temp = distance1; 431 distance1 = distance3; 432 distance3 = temp; 433 } 456 double pdx = point.getX()  segmentP1.getX(); 457 double pdy = point.getY()  segmentP1.getY(); 434 458 435 //test with some treshold 436 double difference = distance1  distance2  distance3; 459 double offset = (pdx * ldx + pdy * ldy) / (ldx * ldx + ldy * ldy); 437 460 438 return (Math.abs(difference) < 1e15); 461 if (offset <= 0) 462 return segmentP1; 463 else if (offset >= 1) 464 return segmentP2; 465 else 466 return new EastNorth(segmentP1.getX() + ldx * offset, segmentP1.getY() + ldy * offset); 439 467 440 468 } 441 469 470 442 471 /** 443 472 * Gets a node from selected way before given index. 444 473 * @param index index of current node