This is the implementation of my comment to bug #1313 [1]. When you move
nodes, they snap to other existing nodes, which is a comfortable thing
if you want to connect roads at existing nodes. Currently, when you do
this, you end up keeping both nodes at the same position and no real
connection between the roads.

This patch comes into action when you are done moving a single node. It
scans the document for other visible* nodes at the same position. If
there are any, it shows a message box asking whether the nodes shall be
merged. If you say yes, all nodes found at that exact position are
merged into the first node that was found that has already been there.
Usually this is one node and you're merging two nodes then. (But if
there have already been multiple nodes, it will be corrected silently.)
The merging is adapted from the existing Merge Nodes command and gets
its own undo item.

*) It only checks for visible nodes. So for the check to work, you need
to have the relevant layers enabled. I assume this is always the case as
you won't be editing the map blindly. OTOH it will ignore GPX nodes if
that layer is hidden. The snapping code also only takes visible nodes,
and so does my patch. (Code adapted from there.)

[1] http://trac.openstreetmap.org/ticket/1313

-- 
Yves Goergen "LonelyPixel" <[email protected]>
Visit my web laboratory at http://beta.unclassified.de
--- merkaartor\Interaction\MoveTrackPointInteraction.cpp.orig   Fri Jan 02 
23:21:05 2009
+++ merkaartor\Interaction\MoveTrackPointInteraction.cpp        Sun Jan 04 
18:06:46 2009
@@ -13,6 +13,7 @@
 #include <QtGui/QCursor>
 #include <QtGui/QMouseEvent>
 #include <QtGui/QPixmap>
+#include <QMessageBox>
 
 #include <vector>
 
@@ -75,7 +76,64 @@
                        else
                                theList->add(new 
MoveTrackPointCommand(Moving[i],OriginalPosition[i]+Diff, 
document()->getDirtyOrOriginLayer(Moving[i]->layer())));
                }
+               
                document()->addHistory(theList);
+
+               // If moving a single node (not a track node), see if it got 
dropped onto another node
+               if (Moving.size() == 1 && !Moving[0]->layer()->isTrack())
+               {
+                       Coord newPos = OriginalPosition[0] + Diff;
+                       std::vector<TrackPoint*> samePosPts;
+                       for (VisibleFeatureIterator it(document()); 
!it.isEnd(); ++it)
+                       {
+                               TrackPoint* visPt = 
dynamic_cast<TrackPoint*>(it.get());
+                               if (visPt)
+                               {
+                                       if (visPt == Moving[0])
+                                               continue;
+
+                                       if (visPt->position() == newPos)
+                                       {
+                                               samePosPts.push_back(visPt);
+                                       }
+                               }
+                       }
+                       // Ensure the node being moved is at the end of the 
list.
+                       // (This is not the node that all nodes will be merged 
into,
+                       // they are always merged into a node that already was 
at that position.)
+                       samePosPts.push_back(Moving[0]);
+
+                       if (samePosPts.size() > 1)   // Ignore the node we're 
moving, see if there are more
+                       {
+                               int ret = QMessageBox::question(view(),
+                                       MainWindow::tr("Nodes at the same 
position found."),
+                                       MainWindow::tr("Do you want to merge 
all nodes at the drop position?"),
+                                       QMessageBox::Yes | QMessageBox::No);
+                               if (ret == QMessageBox::Yes)
+                               {
+                                       // Merge all nodes from the same 
position
+
+                                       // from 
MainWindow::on_nodeMergeAction_triggered()
+                                       // Merge all nodes into the first node 
that has been found (not the node being moved)
+                                       MapFeature* F = samePosPts[0];
+                                       // Make a separate undo command list 
for this action
+                                       CommandList* theList2 = new 
CommandList(MainWindow::tr("Merge Nodes into %1").arg(F->id()), F);
+                                       
+                                       // from mergeNodes(theDocument, 
theList, theProperties);
+                                       std::vector<MapFeature*> alt;
+                                       TrackPoint* merged = samePosPts[0];
+                                       alt.push_back(merged);
+                                       for (unsigned int i = 1; i < 
samePosPts.size(); ++i) {
+                                               
MapFeature::mergeTags(document(), theList2, merged, samePosPts[i]);
+                                               theList2->add(new 
RemoveFeatureCommand(document(), samePosPts[i], alt));
+                                       }
+                                       
+                                       document()->addHistory(theList2);
+                                       view()->properties()->setSelection(F);
+                               }
+                       }
+               }
+               
                view()->invalidate(true, false);
        }
        Moving.clear();
_______________________________________________
Merkaartor mailing list
[email protected]
http://lists.openstreetmap.org/listinfo/merkaartor

Reply via email to