Ignore:
Timestamp:
2010-02-07T23:24:41+01:00 (15 years ago)
Author:
petrdlouhy
Message:

Connecting was moved to it's own class
Fix to undo

Location:
applications/editors/josm/plugins/tracer/src/org/openstreetmap/josm/plugins/tracer
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/tracer/src/org/openstreetmap/josm/plugins/tracer/TracerAction.java

    r19892 r19927  
    1717import java.util.Collection;
    1818import java.util.LinkedList;
    19 import java.util.List;
    2019import org.openstreetmap.josm.Main;
    2120import org.openstreetmap.josm.actions.mapmode.MapMode;
    2221import org.openstreetmap.josm.command.AddCommand;
    23 import org.openstreetmap.josm.command.ChangeCommand;
    2422import org.openstreetmap.josm.command.Command;
    25 import org.openstreetmap.josm.command.DeleteCommand;
    26 import org.openstreetmap.josm.command.MoveCommand;
    2723import org.openstreetmap.josm.command.SequenceCommand;
    2824import org.openstreetmap.josm.data.coor.LatLon;
     
    3531import org.openstreetmap.josm.tools.Shortcut;
    3632import org.xml.sax.SAXException;
    37 import org.openstreetmap.josm.data.osm.BBox;
    38 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    39 import org.openstreetmap.josm.tools.Pair;
    4033
    4134class TracerAction extends MapMode implements MouseListener {
     
    4740    private boolean shift;
    4841    protected TracerServer server = new TracerServer();
    49 
    50     final double MIN_DISTANCE = 0.000015; //Minimal distance, when nodes are merged
    51     final double MIN_DISTANCE_TW = 0.000015; //Minimal distance, when node is connected to other way
    52     final double MIN_DISTANCE_SQ = 0.000015; //Minimal distance, when other node is connected this way
    53     final double MAX_ANGLE = 30; //Minimal angle, when other node is connected this way
    5442
    5543    public TracerAction(MapFrame mapFrame) {
     
    10896    }
    10997
    110     private boolean isBuilding(Way w) {
    111         return (w.getKeys().get("building") == null ? false : w.getKeys().get("building").equals("yes"));
    112     }
    113 
    114     private boolean isInBuilding(Node n) {
    115         for (OsmPrimitive op : n.getReferrers()) {
    116             if (op instanceof Way) {
    117                 if (isBuilding((Way) op)) {
    118                     return true;
    119                 }
    120             }
    121         }
    122         return false;
    123     }
    124 
    125     /**
    126      * Try connect way to other buidings.
    127      * @param way Way to connect.
    128      * @return Commands.
    129      */
    130     private Command connectObjects(Way way) {
    131 
    132         List<Command> cmds = new LinkedList<Command>();
    133         Way newWay = new Way(way);
    134         for (int i = 0; i < way.getNodesCount() - 1; i++) {
    135             Node n = way.getNode(i);
    136             //System.out.println("-------");
    137             //System.out.println("Node: " + n);
    138             LatLon ll = n.getCoor();
    139             BBox bbox = new BBox(
    140                     ll.getX() - MIN_DISTANCE,
    141                     ll.getY() - MIN_DISTANCE,
    142                     ll.getX() + MIN_DISTANCE,
    143                     ll.getY() + MIN_DISTANCE);
    144 
    145             // bude se node slucovat s jinym?
    146             double minDistanceSq = MIN_DISTANCE;
    147             List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(bbox);
    148             Node nearestNode = null;
    149             for (Node nn : nodes) {
    150                 if (!nn.isUsable() || way.containsNode(nn) || newWay.containsNode(nn) || !isInBuilding(nn)) {
    151                     continue;
    152                 }
    153                 double dist = nn.getCoor().distance(ll);
    154                 if (dist < minDistanceSq) {
    155                     minDistanceSq = dist;
    156                     nearestNode = nn;
    157                 }
    158             }
    159 
    160             //System.out.println("Nearest: " + nearestNode);
    161             if (nearestNode == null) {
    162                 cmds.addAll(tryConnectNodeToAnyWay(n));
    163             } else {
    164                 cmds.addAll(mergeNodes(n, nearestNode, newWay));
    165             }
    166         }
    167 
    168         cmds.add(new ChangeCommand(way, trySplitWayByAnyNodes(newWay)));
    169 
    170         Command cmd = new SequenceCommand(tr("Merge objects nodes"), cmds);
    171         return cmd;
    172     }
    173 
    174     /**
    175      * Merges two nodes
    176      * @param n1 First node
    177      * @param n2 Second node
    178      * @param way Way containing first node
    179      * @return List of Commands.
    180      */
    181     private List<Command> mergeNodes(Node n1, Node n2, Way way){
    182         List<Command> cmds = new LinkedList<Command>();
    183         cmds.add(new MoveCommand(n2,
    184                  (n1.getEastNorth().getX() - n2.getEastNorth().getX())/2,
    185                  (n1.getEastNorth().getY() - n2.getEastNorth().getY())/2
    186                  ));
    187 
    188         int j = way.getNodes().indexOf(n1);
    189         way.addNode(j, n2);
    190         if (j == 0) {
    191             // first + last point
    192             way.addNode(way.getNodesCount(), n2);
    193         }
    194         way.removeNode(n1);
    195 
    196         cmds.add(new DeleteCommand(n1));
    197         return cmds;
    198     }
    199 
    200     /**
    201      * Try connect node "node" to way of other building.
    202      *
    203      * Zkusi zjistit, zda node neni tak blizko nejake usecky existujici budovy,
    204      * ze by mel byt zacnenen do teto usecky. Pokud ano, provede to.
    205      *
    206      * @param node Node to connect.
    207      * @throws IllegalStateException
    208      * @throws IndexOutOfBoundsException
    209      * @return List of Commands.
    210      */
    211     private List<Command> tryConnectNodeToAnyWay(Node node)
    212             throws IllegalStateException, IndexOutOfBoundsException {
    213        
    214         List<Command> cmds = new LinkedList<Command>();
    215 
    216         LatLon ll = node.getCoor();
    217         BBox bbox = new BBox(
    218                 ll.getX() - MIN_DISTANCE_TW,
    219                 ll.getY() - MIN_DISTANCE_TW,
    220                 ll.getX() + MIN_DISTANCE_TW,
    221                 ll.getY() + MIN_DISTANCE_TW);
    222 
    223         // node nebyl slouceny s jinym
    224         // hledani pripadne blizke usecky, kam bod pridat
    225         List<Way> ways = Main.main.getCurrentDataSet().searchWays(bbox);
    226         double minDist = Double.MAX_VALUE;
    227         Way nearestWay = null;
    228         int nearestNodeIndex = 0;
    229         for (Way ww : ways) {
    230             if (!ww.isUsable() || ww.containsNode(node) || !isBuilding(ww)) {
    231                 continue;
    232             }
    233             for (Pair<Node, Node> np : ww.getNodePairs(false)) {
    234                 double dist = TracerGeometry.distanceFromSegment(ll, np.a.getCoor(), np.b.getCoor());
    235                 if (dist < minDist) {
    236                     minDist = dist;
    237                     nearestWay = ww;
    238                     nearestNodeIndex = ww.getNodes().indexOf(np.a);
    239                 }
    240             }
    241         }
    242         //System.out.println("Nearest way: " + nearestWay + " distance: " + minDist);
    243         if (minDist < MIN_DISTANCE_TW) {
    244             Way newNWay = new Way(nearestWay);
    245             newNWay.addNode(nearestNodeIndex + 1, node);
    246             //System.out.println("New way:" + newNWay);
    247             Command c = new ChangeCommand(nearestWay, newNWay);
    248             c.executeCommand();
    249             cmds.add(c);
    250         }
    251         return cmds;
    252     }
    253 
    254     /**
    255      * Try split way by any existing buiding nodes.
    256      *
    257      * Zkusi zjistit zda nejake usecka z way by nemela prochazet nejakym existujicim bodem,
    258      * ktery je ji velmi blizko. Pokud ano, tak puvodni usecku rozdeli na dve tak, aby
    259      * prochazela takovym bodem.
    260      *
    261      * @param way Way to split.
    262      * @throws IndexOutOfBoundsException
    263      * @throws IllegalStateException
    264      * @return Modified way
    265      */
    266     private Way trySplitWayByAnyNodes(Way way)
    267             throws IndexOutOfBoundsException, IllegalStateException {
    268 
    269         // projdi kazdou novou usecku a zjisti, zda by nemela vest pres existujici body
    270         int i = 0;
    271         while (i < way.getNodesCount()) {
    272             // usecka n1, n2
    273             LatLon n1 = way.getNodes().get(i).getCoor();
    274             LatLon n2 = way.getNodes().get((i + 1) % way.getNodesCount()).getCoor();
    275             //System.out.println(way.getNodes().get(i) + "-----" + way.getNodes().get((i + 1) % way.getNodesCount()));
    276             double minDistanceSq = MIN_DISTANCE_SQ;
    277             double maxAngle = MAX_ANGLE;
    278             List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(new BBox(
    279                 Math.min(n1.getX(), n2.getX()) - minDistanceSq,
    280                 Math.min(n1.getY(), n2.getY()) - minDistanceSq,
    281                 Math.max(n1.getX(), n2.getX()) + minDistanceSq,
    282                 Math.max(n1.getY(), n2.getY()) + minDistanceSq
    283             ));
    284             Node nearestNode = null;
    285             for (Node nod : nodes) {
    286                 if (!nod.isUsable() || way.containsNode(nod) || !isInBuilding(nod)) {
    287                     continue;
    288                 }
    289                 LatLon nn = nod.getCoor();
    290                 double dist = TracerGeometry.distanceFromSegment(nn, n1, n2);
    291                 double angle = TracerGeometry.angleOfLines(n1, nn, nn, n2);
    292                 //System.out.println("Angle: " + angle + " distance: " + dist + " Node: " + nod);
    293                 if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq && Math.abs(angle) < maxAngle) {
    294                     maxAngle = angle;
    295                     nearestNode = nod;
    296                 }
    297             }
    298             //System.out.println("Nearest_: " + nearestNode);
    299             //System.out.println("");
    300             if (nearestNode == null) {
    301                 // tato usecka se nerozdeli
    302                 i++;
    303                 continue;
    304             } else {
    305                 // rozdeleni usecky
    306                 way.addNode(i + 1, nearestNode);
    307                 continue; // i nezvetsuji, treba bude treba rozdelit usecku znovu
    308             }
    309         }
    310         return way;
    311     }
    312 
    31398    private void tagBuilding(Way way) {
    31499        if(!alt) way.put("building", "yes");
     
    345130            // connect to other buildings
    346131            if (!ctrl) {
    347                 commands.add(connectObjects(way));
    348             }
     132                commands.add(ConnectWays.connect(way));
     133                }
    349134
    350135            if (!commands.isEmpty()) {
    351                 Main.main.undoRedo.add(new SequenceCommand(tr("Tracer building"), commands));
     136                   Main.main.undoRedo.add(new SequenceCommand(tr("Tracer building"), commands));
    352137
    353138                if (shift) {
Note: See TracChangeset for help on using the changeset viewer.