Ticket #5560: patch.diff

File patch.diff, 8.1 KB (added by extropy, 11 years ago)
  • src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java

     
    193193                        initialN2en.getX() - en.getX(),
    194194                        initialN2en.getY() - en.getY()));
    195195            }
    196            
     196
    197197            // Signifies that nothing has happened yet
    198198            newN1en = null;
    199199            newN2en = null;
     
    305305
    306306                    //find if the new points overlap existing segments (in case of 90 degree angles)
    307307                    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);
    309310
    310                     if (nodeOverlapsSegment && !alwaysCreateNodes) {
     311                    if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
    311312                        //move existing node
    312313                        Node n1Old = selectedSegment.getFirstNode();
    313314                        cmds.add(new MoveCommand(n1Old, Main.proj.eastNorth2latlon(newN1en)));
     
    321322
    322323                    //find if the new points overlap existing segments (in case of 90 degree angles)
    323324                    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);
    325327
    326                     if (nodeOverlapsSegment && !alwaysCreateNodes) {
     328                    if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
    327329                        //move existing node
    328330                        Node n2Old = selectedSegment.getSecondNode();
    329331                        cmds.add(new MoveCommand(n2Old, Main.proj.eastNorth2latlon(newN2en)));
     
    361363        }
    362364    }
    363365
     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
    364382    /***
    365383     * This method calculates offset amount by witch to move the given segment perpendicularly for it to be in line with mouse position.
    366384     * @param segmentP1
     
    368386     * @param targetPos
    369387     * @return offset amount of P1 and P2.
    370388     */
    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()));
    378394
    379395        if (intersectionPoint == null)
    380396            return null;
    381397        else
    382398            //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());
    384401    }
    385402
    386403    /**
    387      * Finds the intersection of two lines of inifinite length
    388      * @return EastNorth null if no intersection was found, the Lon coordinates of the intersection otherwise
     404     * Finds the intersection of two lines of inifinite length.
     405     * @return EastNorth null if no intersection was found, the coordinates of the intersection otherwise
    389406     */
    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) {
    393408
    394409        // Convert line from (point, point) form to ax+by=c
    395410        double a1 = p2.getY() - p1.getY();
     
    401416        double c2 = p4.getX() * p3.getY() - p3.getX() * p4.getY();
    402417
    403418        // 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
    406422
    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);
    410424    }
    411425
     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) < 1e-13;
     438    }
     439
    412440    /**
    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.
    414447     */
    415     private static boolean pointsColinear(EastNorth p1, EastNorth p2, EastNorth p3) {
     448    private static EastNorth closestPointToSegment(EastNorth segmentP1, EastNorth segmentP2, EastNorth point) {
    416449
    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();
    421452
    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;
    428455
    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();
    434458
    435         //test with some treshold
    436         double difference = distance1 - distance2 - distance3;
     459        double offset = (pdx * ldx + pdy * ldy) / (ldx * ldx + ldy * ldy);
    437460
    438         return (Math.abs(difference) < 1e-15);
     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);
    439467
    440468    }
    441469
     470
    442471    /**
    443472     * Gets a node from selected way before given index.
    444473     * @param index  index of current node