Ignore:
Timestamp:
2010-02-04T22:39:37+01:00 (14 years ago)
Author:
jabi
Message:

Refactoring

File:
1 edited

Legend:

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

    r19867 r19872  
    99import java.awt.Cursor;
    1010import java.awt.Point;
     11import java.awt.event.ActionEvent;
     12import java.awt.event.InputEvent;
    1113import java.awt.event.KeyEvent;
    1214import java.awt.event.MouseEvent;
     
    2123import org.openstreetmap.josm.command.ChangeCommand;
    2224import org.openstreetmap.josm.command.Command;
     25import org.openstreetmap.josm.command.DeleteCommand;
    2326import org.openstreetmap.josm.command.SequenceCommand;
    2427import org.openstreetmap.josm.data.coor.LatLon;
     
    3235import org.xml.sax.SAXException;
    3336import org.openstreetmap.josm.data.osm.BBox;
     37import org.openstreetmap.josm.data.osm.OsmPrimitive;
    3438
    3539class TracerAction extends MapMode implements MouseListener {
    3640
    37     protected TracerServer traceServer = new TracerServer();
     41    private static final long serialVersionUID = 1L;
    3842    protected boolean cancel;
    39     protected Collection<Command> commands = new LinkedList<Command>();
    40     protected Collection<Way> ways = new ArrayList<Way>();
     43    private boolean ctrl;
     44    private boolean alt;
     45    private boolean shift;
     46    protected TracerServer server = new TracerServer();
    4147
    4248    public TracerAction(MapFrame mapFrame) {
     
    6571
    6672    protected void traceAsync(Point clickPoint) {
    67 
    6873        cancel = false;
    69 
     74        /**
     75         * Positional data
     76         */
    7077        final LatLon pos = Main.map.mapView.getLatLon(clickPoint.x, clickPoint.y);
    7178
     
    8794                }
    8895            };
    89             Thread executeThread = new Thread(tracerTask);
    90             executeThread.start();
     96            Thread executeTraceThread = new Thread(tracerTask);
     97            executeTraceThread.start();
    9198        } catch (Exception e) {
    9299            e.printStackTrace();
     
    94101    }
    95102
     103    private boolean isBuilding(Way w) {
     104        return (w.getKeys().get("building") == null ? false : w.getKeys().get("building").equals("yes"));
     105    }
     106
     107    private boolean isInBuilding(Node n) {
     108        for (OsmPrimitive op : n.getReferrers()) {
     109            if (op instanceof Way) {
     110                if (isBuilding((Way) op)) {
     111                    return true;
     112                }
     113            }
     114        }
     115        return false;
     116    }
     117
     118    /**
     119     * Try connect way to other buidings.
     120     * @param way Way to connect.
     121     * @return Commands.
     122     */
     123    private Command connectObjects(Way way) {
     124        final double MIN_DISTANCE = 0.000015;
     125
     126        List<Command> cmds = new LinkedList<Command>();
     127        Way newWay = new Way(way);
     128        for (int i = 1; i < way.getNodesCount(); i++) {
     129            Node n = way.getNode(i);
     130            LatLon ll = n.getCoor();
     131            BBox bbox = new BBox(
     132                    ll.getX() - MIN_DISTANCE,
     133                    ll.getY() - MIN_DISTANCE,
     134                    ll.getX() + MIN_DISTANCE,
     135                    ll.getY() + MIN_DISTANCE);
     136
     137            // bude se node slucovat s jinym?
     138            double minDistanceSq = MIN_DISTANCE;
     139            List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(bbox);
     140            Node nearestNode = null;
     141            for (Node nn : nodes) {
     142                if (!nn.isUsable() || way.containsNode(nn) || newWay.containsNode(nn) || !isInBuilding(nn)) {
     143                    continue;
     144                }
     145                double dist = nn.getCoor().distance(ll);
     146                if (dist < minDistanceSq) {
     147                    minDistanceSq = dist;
     148                    nearestNode = nn;
     149                }
     150            }
     151
     152            //System.out.println("Nearest: " + nearestNode);
     153            //System.out.println("-------");
     154            if (nearestNode == null) {
     155                tryConnectNodeToAnyWay(way, newWay, n, cmds);
     156            } else {
     157                nearestNode.setCoor(ll.getCenter(nearestNode.getCoor()));
     158                int j = newWay.getNodes().indexOf(n);
     159                newWay.addNode(j, nearestNode);
     160                if (j == 0) {
     161                    // first + last point
     162                    newWay.addNode(newWay.getNodesCount(), nearestNode);
     163                }
     164                newWay.removeNode(n);
     165                cmds.add(new DeleteCommand(n));
     166            }
     167        }
     168        trySplitWayByAnyNodes(way, newWay);
     169
     170        cmds.add(new ChangeCommand(way, newWay));
     171
     172        Command cmd = new SequenceCommand(tr("Merge objects nodes"), cmds);
     173        return cmd;
     174    }
     175
     176    /**
     177     * Try connect node "node" from way "oldWay" to way of other building.
     178     *
     179     * Zkusi zjistit, zda node neni tak blizko nejake usecky existujici budovy,
     180     * ze by mel byt zacnenen do teto usecky. Pokud ano, provede to.
     181     *
     182     * @param oldWay Way which contains node "node".
     183     * @param newWay Modified way.
     184     * @param node Node to connect.
     185     * @param cmds Command list.
     186     * @throws IllegalStateException
     187     * @throws IndexOutOfBoundsException
     188     */
     189    private void tryConnectNodeToAnyWay(Way oldWay, Way newWay, Node node, List<Command> cmds)
     190            throws IllegalStateException, IndexOutOfBoundsException {
     191
     192        final double MIN_DISTANCE = 0.000015;
     193
     194        LatLon ll = node.getCoor();
     195        BBox bbox = new BBox(
     196                ll.getX() - MIN_DISTANCE,
     197                ll.getY() - MIN_DISTANCE,
     198                ll.getX() + MIN_DISTANCE,
     199                ll.getY() + MIN_DISTANCE);
     200
     201        // node nebyl slouceny s jinym
     202        // hledani pripadne blizke usecky, kam bod pridat
     203        List<Way> ways = Main.main.getCurrentDataSet().searchWays(bbox);
     204        double minDist = Double.MAX_VALUE;
     205        Way nearestWay = null;
     206        int nearestNodeIndex = 0;
     207        for (Way ww : ways) {
     208            if (!ww.isUsable() || ww == oldWay || ww == newWay || !isBuilding(ww)) {
     209                continue;
     210            }
     211            for (int nindex = 0; nindex < ww.getNodesCount(); nindex++) {
     212                Node n1 = ww.getNode(nindex);
     213                Node n2 = ww.getNode((nindex + 1) % ww.getNodesCount());
     214                double dist = TracerGeometry.distanceFromSegment(ll, n1.getCoor(), n2.getCoor());
     215                if (dist < minDist) {
     216                    minDist = dist;
     217                    nearestWay = ww;
     218                    nearestNodeIndex = nindex;
     219                }
     220            }
     221        }
     222        //System.out.println("Nearest way:" + nearestWay);
     223        if (minDist < MIN_DISTANCE) {
     224            Way newNWay = new Way(nearestWay);
     225            newNWay.addNode(nearestNodeIndex + 1, node);
     226            //System.out.println("New way:" + newNWay);
     227            cmds.add(new ChangeCommand(nearestWay, newNWay));
     228        }
     229    }
     230
     231    /**
     232     * Try split way by any existing buiding nodes.
     233     *
     234     * Zkusi zjistit zda nejake usecka z oldWay by nemela prochazet nejakym existujicim bodem,
     235     * ktery je ji velmi blizko. Pokud ano, tak puvodni usecku rozdeli na dve tak, aby
     236     * prochazela takovym bodem.
     237     *
     238     * @param oldWay Way to split.
     239     * @param newWay Modified way.
     240     * @throws IndexOutOfBoundsException
     241     * @throws IllegalStateException
     242     */
     243    private void trySplitWayByAnyNodes(Way oldWay, Way newWay)
     244            throws IndexOutOfBoundsException, IllegalStateException {
     245
     246        // projdi kazdou novou usecku a zjisti, zda by nemela vest pres existujici body
     247        int i = 0;
     248        while (i < newWay.getNodesCount()) {
     249            // usecka n1, n2
     250            LatLon n1 = newWay.getNodes().get(i).getCoor();
     251            LatLon n2 = newWay.getNodes().get((i + 1) % newWay.getNodesCount()).getCoor();
     252            //System.out.println(newWay.getNodes().get(i) + "-----" + newWay.getNodes().get((i + 1) % newWay.getNodesCount()));
     253            double minDistanceSq = 0.000015;
     254            double maxAngle = 15;
     255            List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(new BBox(Math.min(n1.getX(), n2.getX()) - minDistanceSq, Math.min(n1.getY(), n2.getY()) - minDistanceSq, Math.max(n1.getX(), n2.getX()) + minDistanceSq, Math.max(n1.getY(), n2.getY()) + minDistanceSq));
     256            Node nearestNode = null;
     257            for (Node nod : nodes) {
     258                if (!nod.isUsable() || oldWay.containsNode(nod) || newWay.containsNode(nod) || !isInBuilding(nod)) {
     259                    continue;
     260                }
     261                LatLon nn = nod.getCoor();
     262                double dist = TracerGeometry.distanceFromSegment(nn, n1, n2);
     263                double angle = TracerGeometry.angleOfLines(n1, nn, nn, n2);
     264                if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq && Math.abs(angle) < maxAngle) {
     265                    maxAngle = angle;
     266                    nearestNode = nod;
     267                }
     268            }
     269            //System.out.println("Nearest_: " + nearestNode);
     270            //System.out.println("");
     271            if (nearestNode == null) {
     272                // tato usecka se nerozdeli
     273                i++;
     274                continue;
     275            } else {
     276                // rozdeleni usecky
     277                newWay.addNode(i + 1, nearestNode);
     278                continue; // i nezvetsuji, treba bude treba rozdelit usecku znovu
     279            }
     280        }
     281    }
     282
     283    private void tagBuilding(Way way) {
     284        way.put("building", "yes");
     285        way.put("source", "cuzk:km");
     286    }
     287
    96288    private void traceSync(LatLon pos, ProgressMonitor progressMonitor) {
    97        
     289        Collection<Command> commands = new LinkedList<Command>();
     290
    98291        progressMonitor.beginTask(null, 3);
    99292        try {
    100             ArrayList<double[]> nodelist = new ArrayList<double[]>();
    101             nodelist = traceServer.trace(pos);
    102 
    103             if (nodelist.size() == 0) {
     293            ArrayList<LatLon> coordList = server.trace(pos);
     294
     295            if (coordList.size() == 0) {
    104296                return;
    105297            }
    106298
    107             /**
    108              * Turn the arraylist into osm nodes
    109              */
     299            // make nodes a way
    110300            Way way = new Way();
    111             Node n = null;
    112             Node fn = null;
    113 
    114             double eastOffset = 0;
    115             double northOffset = 0;
    116 
    117 
    118             int nodesinway = 0;
    119 
    120             for (int i = 0; i < nodelist.size(); i++) {
    121                 if (cancel) {
    122                     return;
    123                 }
    124 
    125                 try {
    126                     LatLon ll = new LatLon(nodelist.get(i)[0] + northOffset, nodelist.get(i)[1] + eastOffset);
    127 
    128                     double minDistanceSq = 0.00001;
    129                     BBox box = new BBox(
    130                             ll.getX() - minDistanceSq,
    131                             ll.getY() - minDistanceSq,
    132                             ll.getX() + minDistanceSq,
    133                             ll.getY() + minDistanceSq);
    134                     List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(box);
    135                     List<Way> nodeWays = Main.main.getCurrentDataSet().searchWays(box);
    136                     Node nearestNode = null;
    137                     for (Node nn : nodes) {
    138                         if (!nn.isUsable()) {
    139                             continue;
    140                         }
    141 
    142                         boolean buildingNode = false;
    143                         for (Way w : nodeWays) {
    144                             if (w.containsNode(nn) && w.hasKey("building")) {
    145                                 buildingNode = true;
    146                                 break;
    147                             }
    148                         }
    149                         if (!buildingNode) {
    150                             continue;
    151                         }
    152 
    153                         LatLon ll2 = nn.getCoor();
    154                         double dist = ll2.distance(ll);
    155                         if (dist < minDistanceSq) {
    156                             minDistanceSq = dist;
    157                             nearestNode = nn;
    158                         }
    159                     }
    160 
    161                     if (nearestNode == null) {
    162                         // hledani blizke usecky, kam bod pridat ... nebo vytvorit samostatny bod?
    163                         List<Way> ways = Main.main.getCurrentDataSet().searchWays(new BBox(
    164                                 ll.getX() - minDistanceSq,
    165                                 ll.getY() - minDistanceSq,
    166                                 ll.getX() + minDistanceSq,
    167                                 ll.getY() + minDistanceSq));
    168                         double minDist = Double.MAX_VALUE;
    169                         Way nearestWay = null;
    170                         int nearestNodeIndex = 0;
    171 
    172 
    173                         for (Way ww : ways) {
    174                             if (!ww.hasKey("building")) {
    175                                 continue;
    176                             }
    177                             for (int nindex = 0; nindex < ww.getNodesCount(); nindex++) {
    178                                 Node n1 = ww.getNode(nindex);
    179                                 Node n2 = ww.getNode((nindex + 1) % ww.getNodesCount());
    180 
    181                                 double dist = TracerGeometry.distanceFromSegment(ll, n1.getCoor(), n2.getCoor());
    182                                 if (dist < minDist) {
    183                                     minDist = dist;
    184                                     nearestWay = ww;
    185                                     nearestNodeIndex = nindex;
    186                                 }
    187                             }
    188                         }
    189 
    190                         if (minDist < 0.00001) {
    191                             n = new Node(ll);
    192                             commands.add(new AddCommand(n));
    193                             Way newWay = new Way(nearestWay);
    194                             newWay.addNode(nearestNodeIndex + 1, n);
    195                             commands.add(new ChangeCommand(nearestWay, newWay));
    196                         } else {
    197                             n = new Node(ll);
    198                             commands.add(new AddCommand(n));
    199                         }
    200                     } else {
    201                         n = nearestNode;
    202                     }
    203 
    204                     if (fn == null) {
    205                         fn = n;
    206                     }
    207 
    208                 } catch (Exception ex) {
    209                     ex.printStackTrace();
    210                 }
    211 
    212                 way.addNode(n);
    213                 nodesinway++;
    214             }
    215             /**/
    216             // projdi kazdou novou usecku a zjisti, zda by nemela vest pres existujici body
    217             int i = 0;
    218             while (i < nodelist.size()) {
    219                 if (cancel) {
    220                     return;
    221                 }
    222 
    223                 traceServer.log("i/" + i);
    224 
    225                 // usecka n1, n2
    226                 double d[] = nodelist.get(i);
    227                 LatLon n1 = new LatLon(d[0], d[1]);
    228                 d = nodelist.get((i + 1) % nodelist.size());
    229                 LatLon n2 = new LatLon(d[0], d[1]);
    230 
    231                 double minDistanceSq = 0.00001;
    232                 double maxAngle = 10;
    233                 BBox box = new BBox(
    234                         Math.min(n1.getX(), n2.getX()) - minDistanceSq,
    235                         Math.min(n1.getY(), n2.getY()) - minDistanceSq,
    236                         Math.max(n1.getX(), n2.getX()) + minDistanceSq,
    237                         Math.max(n1.getY(), n2.getY()) + minDistanceSq);
    238                 List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(box);
    239                 List<Way> nodeWays = Main.main.getCurrentDataSet().searchWays(box);
    240                 Node nearestNode = null;
    241                 for (Node nod : nodes) {
    242                     if (!nod.isUsable()) {
    243                         continue;
    244                     }
    245                     boolean buildingNode = false;
    246                     for (Way w : nodeWays) {
    247                         if (w.containsNode(nod) && w.hasKey("building")) {
    248                             buildingNode = true;
    249                             break;
    250                         }
    251                     }
    252                     if (!buildingNode) {
    253                         continue;
    254                     }
    255 
    256                     LatLon nn = nod.getCoor();
    257                     double dist = TracerGeometry.distanceFromSegment(nn, n1, n2);
    258                     double angle = TracerGeometry.angleOfLines(n1, nn, nn, n2);
    259 
    260                     if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq) {
    261                         traceServer.log("n1/" + n1.toDisplayString());
    262                         traceServer.log("nn/" + nn.toDisplayString());
    263                         traceServer.log("n2/" + n2.toDisplayString());
    264                         traceServer.log("angle/" + Math.abs(angle));
    265                     }
    266                     if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq && Math.abs(angle) < maxAngle) {
    267                         traceServer.log("ok");
    268                         maxAngle = angle;
    269                         nearestNode = nod;
    270                     }
    271                 }
    272 
    273                 if (nearestNode == null) {
    274                     // tato usecka se nerozdeli
    275                     i++;
    276                     continue;
    277                 } else {
    278                     // rozdeleni usecky
    279                     nodelist.add(i + 1, new double[]{nearestNode.getCoor().getY(), nearestNode.getCoor().getX()});
    280                     way.addNode(i + 1, nearestNode);
    281                     continue; // i nezvetsuji, treba bude treba rozdelit usecku znovu
    282                 }
    283 
    284             }
    285             /**/
    286             way.put("building", "yes");
    287             way.put("source", "cuzk:km");
    288 
    289             way.addNode(fn);
    290 
     301            Node firstNode = null;
     302            for (LatLon coord : coordList) {
     303                Node node = new Node(coord);
     304                if (firstNode == null) {
     305                    firstNode = node;
     306                }
     307                commands.add(new AddCommand(node));
     308                way.addNode(node);
     309            }
     310            way.addNode(firstNode);
     311
     312            tagBuilding(way);
    291313            commands.add(new AddCommand(way));
     314
     315            // connect to other buildings
     316            if (!ctrl) {
     317                commands.add(connectObjects(way));
     318            }
    292319
    293320            if (!commands.isEmpty()) {
    294321                Main.main.undoRedo.add(new SequenceCommand(tr("Tracer building"), commands));
    295                 Main.main.getCurrentDataSet().setSelected(ways);
     322
     323                if (shift) {
     324                    Main.main.getCurrentDataSet().addSelected(way);
     325                } else {
     326                    Main.main.getCurrentDataSet().setSelected(way);
     327                }
    296328            } else {
    297329                System.out.println("Failed");
    298330            }
    299331
    300             commands = new LinkedList<Command>();
    301             ways = new ArrayList<Way>();
    302332        } finally {
    303333            progressMonitor.finishTask();
     
    309339    }
    310340
     341    @Override
    311342    public void mouseClicked(MouseEvent e) {
    312343    }
    313344
     345    @Override
    314346    public void mouseEntered(MouseEvent e) {
    315347    }
    316348
     349    @Override
    317350    public void mouseExited(MouseEvent e) {
    318351    }
    319352
     353    @Override
    320354    public void mousePressed(MouseEvent e) {
    321355        if (!Main.map.mapView.isActiveLayerDrawable()) {
     
    323357        }
    324358
     359        updateKeyModifiers(e);
    325360        if (e.getButton() == MouseEvent.BUTTON1) {
    326361            traceAsync(e.getPoint());
     
    328363    }
    329364
     365    private void updateKeyModifiers(MouseEvent e) {
     366        ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
     367        alt = (e.getModifiers() & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0;
     368        shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
     369    }
     370
     371    @Override
    330372    public void mouseReleased(MouseEvent e) {
    331373    }
Note: See TracChangeset for help on using the changeset viewer.