Changeset 3631 in josm


Ignore:
Timestamp:
2010-10-24T01:00:47+02:00 (13 years ago)
Author:
bastiK
Message:

see #5560 (patch by extropy) - Extrude does not work with multiple adjacent buildings

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java

    r3557 r3631  
    5454
    5555    /**
    56      * If true, when extruding create new node even if segments prallel.
     56     * If true, when extruding create new node even if segments parallel.
    5757     */
    5858    private boolean alwaysCreateNodes = false;
     
    142142    /**
    143143     * If the left mouse button is pressed over a segment, switch
    144      * to either extrude or translate mode depending on whether ctrl is held.
     144     * to either extrude or translate mode depending on whether Ctrl is held.
    145145     */
    146146    @Override public void mousePressed(MouseEvent e) {
     
    194194                        initialN2en.getY() - en.getY()));
    195195            }
    196            
     196
    197197            // Signifies that nothing has happened yet
    198198            newN1en = null;
     
    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);
    309 
    310                     if (nodeOverlapsSegment && !alwaysCreateNodes) {
     308                    boolean nodeOverlapsSegment = prevNode != null && segmentsParralel(initialN1en, prevNode.getEastNorth(), initialN1en, newN1en);
     309                    boolean hasOtherWays = this.hasNodeOtherWays(selectedSegment.getFirstNode(), selectedSegment.way);
     310
     311                    if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
    311312                        //move existing node
    312313                        Node n1Old = selectedSegment.getFirstNode();
     
    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 
    326                     if (nodeOverlapsSegment && !alwaysCreateNodes) {
     325                    nodeOverlapsSegment = nextNode != null && segmentsParralel(initialN2en, nextNode.getEastNorth(), initialN2en, newN2en);
     326                    hasOtherWays = hasNodeOtherWays(selectedSegment.getFirstNode(), selectedSegment.way);
     327
     328                    if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
    327329                        //move existing node
    328330                        Node n2Old = selectedSegment.getSecondNode();
     
    362364    }
    363365
     366    /**
     367     * This method tests if a node has other ways apart from the given one.
     368     * @param node
     369     * @param myWay
     370     * @return true of node belongs only to myWay, false if there are more ways.
     371     */
     372    private boolean hasNodeOtherWays(Node node, Way myWay) {
     373        for (OsmPrimitive p : node.getReferrers()) {
     374            if (p instanceof Way && p.isUsable() && p != myWay)
     375                return true;
     376        }
     377        return false;
     378    }
     379
    364380    /***
    365381     * This method calculates offset amount by witch to move the given segment perpendicularly for it to be in line with mouse position.
     
    369385     * @return offset amount of P1 and P2.
    370386     */
    371     private static EastNorth calculateSegmentOffset(EastNorth segmentP1, EastNorth segmentP2 ,EastNorth moveDirection , EastNorth targetPos)
    372     {
    373         EastNorth intersectionPoint = getLineLineIntersection(
    374                 segmentP1,
    375                 segmentP2,
    376                 targetPos,
     387    private static EastNorth calculateSegmentOffset(EastNorth segmentP1, EastNorth segmentP2, EastNorth moveDirection,
     388            EastNorth targetPos) {
     389        EastNorth intersectionPoint = getLineLineIntersection(segmentP1, segmentP2, targetPos,
    377390                new EastNorth(targetPos.getX() + moveDirection.getX(), targetPos.getY() + moveDirection.getY()));
    378391
     
    381394        else
    382395            //return distance form base to target position
    383             return new EastNorth(targetPos.getX() - intersectionPoint.getX(), targetPos.getY() - intersectionPoint.getY());
    384     }
    385 
    386     /**
    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
    389      */
    390     static public EastNorth getLineLineIntersection(
    391             EastNorth p1, EastNorth p2,
    392             EastNorth p3, EastNorth p4) {
    393 
     396            return new EastNorth(targetPos.getX() - intersectionPoint.getX(),
     397                        targetPos.getY() - intersectionPoint.getY());
     398    }
     399
     400    /**
     401     * Finds the intersection of two lines of infinite length.
     402     * @return EastNorth null if no intersection was found, the coordinates of the intersection otherwise
     403     */
     404    public static EastNorth getLineLineIntersection(EastNorth p1, EastNorth p2, EastNorth p3, EastNorth p4) {
    394405        // Convert line from (point, point) form to ax+by=c
    395406        double a1 = p2.getY() - p1.getY();
     
    402413
    403414        // Solve the equations
    404         double det = a1*b2 - a2*b1;
    405         if(det == 0) return null; // Lines are parallel
    406 
    407         return new EastNorth(
    408                 (b1*c2 - b2*c1)/det,
    409                 (a2*c1 - a1*c2)/det);
    410     }
    411 
    412     /**
    413      * Returns true if all points are on the same line.
    414      */
    415     private static boolean pointsColinear(EastNorth p1, EastNorth p2, EastNorth p3) {
    416 
    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);
    421 
    422         //sort so that distance 1 is the greatest
    423         if (distance1 < distance2) {
    424             double temp = distance1;
    425             distance1 = distance2;
    426             distance2 = temp;
    427         }
    428 
    429         if (distance1 < distance3) {
    430             double temp = distance1;
    431             distance1 = distance3;
    432             distance3 = temp;
    433         }
    434 
    435         //test with some treshold
    436         double difference = distance1 - distance2 - distance3;
    437 
    438         return (Math.abs(difference) < 1e-15);
    439 
     415        double det = a1 * b2 - a2 * b1;
     416        if (det == 0)
     417            return null; // Lines are parallel
     418
     419        return new EastNorth((b1 * c2 - b2 * c1) / det, (a2 * c1 - a1 * c2) / det);
     420    }
     421
     422    private static boolean segmentsParralel(EastNorth p1, EastNorth p2, EastNorth p3, EastNorth p4) {
     423
     424        // Convert line from (point, point) form to ax+by=c
     425        double a1 = p2.getY() - p1.getY();
     426        double b1 = p1.getX() - p2.getX();
     427
     428        double a2 = p4.getY() - p3.getY();
     429        double b2 = p3.getX() - p4.getX();
     430
     431        // Solve the equations
     432        double det = a1 * b2 - a2 * b1;
     433        return Math.abs(det) < 1e-13;
    440434    }
    441435
Note: See TracChangeset for help on using the changeset viewer.