1
#include "Maps/FeatureManipulations.h"
2
#include "Command/DocumentCommands.h"
3
#include "Command/FeatureCommands.h"
4
#include "Command/RoadCommands.h"
5
#include "Command/RelationCommands.h"
6
#include "Command/TrackPointCommands.h"
7
#include "Maps/MapDocument.h"
9
#include "Maps/Relation.h"
10
#include "Maps/TrackPoint.h"
11
#include "PropertiesDock.h"
13
#include <QtCore/QString>
18
#include <ggl/ggl.hpp>
19
#include <ggl/geometries/cartesian2d.hpp>
20
#include <ggl/algorithms/intersection.hpp>
23
bool canJoin(Road* R1, Road* R2)
25
if ( (R1->size() == 0) || (R2->size() == 0) )
27
MapFeature* Start1 = R1->get(0);
28
MapFeature* End1 = R1->get(R1->size()-1);
29
MapFeature* Start2 = R2->get(0);
30
MapFeature* End2 = R2->get(R2->size()-1);
31
return (Start1 == Start2) ||
37
bool canBreak(Road* R1, Road* R2)
39
if ( (R1->size() == 0) || (R2->size() == 0) )
41
for (int i=0; i<R1->size(); i++)
42
for (int j=0; j<R2->size(); j++)
43
if (R1->get(i) == R2->get(j))
48
bool canJoinRoads(PropertiesDock* theDock)
51
for (int i=0; i<theDock->size(); ++i)
52
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
55
for (int i=0; i<Input.size(); ++i)
56
for (int j=i+1; j<Input.size(); ++j)
57
if (canJoin(Input[i],Input[j]))
62
bool canBreakRoads(PropertiesDock* theDock)
65
for (int i=0; i<theDock->size(); ++i)
66
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
68
for (int i=0; i<Input.size(); ++i)
69
for (int j=i+1; j<Input.size(); ++j)
70
if (canBreak(Input[i],Input[j]))
75
bool canDetachNodes(PropertiesDock* theDock)
77
QList<Road*> Roads, Result;
78
QList<TrackPoint*> Points;
79
for (int i=0; i<theDock->size(); ++i)
80
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
82
else if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(theDock->selection(i)))
85
if (Roads.size() > 1 && Points.size() > 1)
88
if (Roads.size() == 0 && Points.size()) {
89
for (int i=0; i<Points.size(); ++i) {
90
Road * R = Road::GetSingleParentRoad(Points[i]);
97
if (Roads.size() && Points.size() == 1)
100
if (Roads.size() == 1 && Points.size())
106
void reversePoints(MapDocument* theDocument, CommandList* theList, Road* R)
108
QList<TrackPoint*> Pts;
109
for (int i=R->size(); i; --i)
111
TrackPoint* Pt = R->getNode(i-1);
114
for (int i=0; i<Pts.size(); ++i)
115
theList->add(new RoadRemoveTrackPointCommand(R,Pts[i],theDocument->getDirtyOrOriginLayer(R->layer())));
116
for (int i=0; i<Pts.size(); ++i)
117
theList->add(new RoadAddTrackPointCommand(R,Pts[i],theDocument->getDirtyOrOriginLayer(R->layer())));
120
static void appendPoints(MapDocument* theDocument, CommandList* L, Road* Dest, Road* Src)
122
L->add(new RoadRemoveTrackPointCommand(Src,(int)0,theDocument->getDirtyOrOriginLayer(Src->layer())));
125
TrackPoint* Pt = Src->getNode(0);
126
L->add(new RoadRemoveTrackPointCommand(Src,(int)0,theDocument->getDirtyOrOriginLayer(Src->layer())));
127
L->add(new RoadAddTrackPointCommand(Dest,Pt,theDocument->getDirtyOrOriginLayer(Src->layer())));
131
static Road* join(MapDocument* theDocument, CommandList* L, Road* R1, Road* R2)
133
QList<MapFeature*> Alternatives;
136
MapFeature::mergeTags(theDocument,L,R2,R1);
137
L->add(new RemoveFeatureCommand(theDocument,R1,Alternatives));
142
MapFeature::mergeTags(theDocument,L,R1,R2);
143
L->add(new RemoveFeatureCommand(theDocument,R2,Alternatives));
146
MapFeature* Start1 = R1->get(0);
147
MapFeature* End1 = R1->get(R1->size()-1);
148
MapFeature* Start2 = R2->get(0);
149
MapFeature* End2 = R2->get(R2->size()-1);
150
if ( (Start1 == Start2) || (Start1 == End2) )
151
reversePoints(theDocument,L,R1);
152
if ( (End1 == End2) || (Start1 == End2) )
153
reversePoints(theDocument,L,R2);
154
appendPoints(theDocument,L,R1,R2);
155
MapFeature::mergeTags(theDocument,L,R1,R2);
156
L->add(new RemoveFeatureCommand(theDocument,R2,Alternatives));
160
void joinRoads(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
163
for (int i=0; i<theDock->size(); ++i)
164
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
165
if (!(R->area() > 0.0))
167
while (Input.size() > 1)
170
for (int i=0; i<Input.size(); ++i)
171
for (int j=i+1; j<Input.size(); ++j)
172
if (canJoin(Input[i],Input[j]))
174
Road* R = join(theDocument, theList,Input[i],Input[j]);
175
Input.erase(Input.begin()+j);
183
theDock->setSelection(Input);
186
static void splitRoad(MapDocument* theDocument, CommandList* theList, Road* In, const QList<TrackPoint*>& Points, QList<Road*>& Result)
189
if (In->isClosed()) { // Special case: If area, rotate the area so that the start node is the first point of splitting
191
QList<TrackPoint*> Target;
192
for (int i=0; i < Points.size(); i++)
193
if ((pos = In->find(Points[i])) != In->size()) {
194
for (int j=pos+1; j<In->size(); ++j)
195
Target.push_back(In->getNode(j));
196
for (int j=1; j<= pos; ++j)
197
Target.push_back(In->getNode(j));
200
if (pos == In->size())
203
if (Points.size() == 1) // Special case: For a 1 point area splitting, de-close the road, i.e. duplicate the selected node
205
TrackPoint* N = new TrackPoint(*(In->getNode(pos)));
206
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(In->layer()),N,true));
209
} else // otherwise, just close the modified area
210
Target.prepend(In->getNode(pos));
212
// Now, reconstruct the road/area
214
theList->add(new RoadRemoveTrackPointCommand(In,(int)0,theDocument->getDirtyOrOriginLayer(In->layer())));
216
for (int i=0; i<Target.size(); ++i)
217
theList->add(new RoadAddTrackPointCommand(In,Target[i],theDocument->getDirtyOrOriginLayer(In->layer())));
219
if (Points.size() == 1) { // For 1-point, we are done
220
Result.push_back(In);
225
Road* FirstPart = In;
226
Result.push_back(FirstPart);
227
for (int i=1; (i+1)<FirstPart->size(); ++i)
229
if (std::find(Points.begin(),Points.end(),FirstPart->get(i)) != Points.end())
231
Road* NextPart = new Road;
232
copyTags(NextPart,FirstPart);
233
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(In->layer()),NextPart,true));
234
theList->add(new RoadAddTrackPointCommand(NextPart, FirstPart->getNode(i), theDocument->getDirtyOrOriginLayer(In->layer())));
235
for (int j=0; j < In->sizeParents(); j++) {
236
Relation* L = CAST_RELATION(In->getParent(j));
237
theList->add(new RelationAddFeatureCommand(L, L->getRole(L->find(In)), NextPart, theDocument->getDirtyOrOriginLayer(In->layer())));
239
while ( (i+1) < FirstPart->size() )
241
theList->add(new RoadAddTrackPointCommand(NextPart, FirstPart->getNode(i+1), theDocument->getDirtyOrOriginLayer(In->layer())));
242
theList->add(new RoadRemoveTrackPointCommand(FirstPart,i+1,theDocument->getDirtyOrOriginLayer(In->layer())));
244
Result.push_back(NextPart);
245
FirstPart = NextPart;
251
void splitRoads(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
253
QList<Road*> Roads, Result;
254
QList<TrackPoint*> Points;
255
for (int i=0; i<theDock->size(); ++i)
256
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
258
else if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(theDock->selection(i)))
259
Points.push_back(Pt);
261
if (Roads.size() == 0 && Points.size() == 1)
263
Road * R = Road::GetSingleParentRoadInner(Points[0]);
268
for (int i=0; i<Roads.size(); ++i)
269
splitRoad(theDocument, theList,Roads[i],Points, Result);
270
theDock->setSelection(Result);
273
static void breakRoad(MapDocument* theDocument, CommandList* theList, Road* R, TrackPoint* Pt)
275
for (int i=0; i<R->size(); ++i)
278
TrackPoint* New = new TrackPoint(*Pt);
280
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(R->layer()),New,true));
281
theList->add(new RoadRemoveTrackPointCommand(R,i,theDocument->getDirtyOrOriginLayer(R->layer())));
282
theList->add(new RoadAddTrackPointCommand(R,New,i,theDocument->getDirtyOrOriginLayer(R->layer())));
284
if (!Pt->sizeParents())
285
theList->add(new RemoveFeatureCommand(theDocument,Pt));
288
void breakRoads(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
290
QList<Road*> Roads, Result;
291
QList<TrackPoint*> Points;
292
for (int i=0; i<theDock->size(); ++i)
293
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
295
else if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(theDock->selection(i)))
296
Points.push_back(Pt);
298
if (Roads.size() == 0 && Points.size() == 1)
300
for (int i=0; i<Points[0]->sizeParents() ; ++i) {
301
Road * R = dynamic_cast<Road*>(Points[0]->getParent(i));
307
if (Roads.size() == 1 && Points.size() ) {
308
splitRoad(theDocument, theList,Roads[0],Points, Result);
309
if (Roads[0]->area() > 0.0) {
310
for (int i=0; i<Points.size(); ++i)
311
breakRoad(theDocument, theList, Roads[0],Points[i]);
317
for (int i=0; i<Roads.size(); ++i)
318
for (int j=0; j<Roads[i]->size(); ++j)
319
for (int k=i+1; k<Roads.size(); ++k)
320
breakRoad(theDocument, theList, Roads[k],dynamic_cast<TrackPoint*>(Roads[i]->get(j)));
323
bool canCreateJunction(PropertiesDock* theDock)
325
return createJunction(NULL, NULL, theDock, false);
328
int createJunction(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock, bool doIt)
332
//TODO test that the junction do not already exists!
333
typedef ggl::point_2d P;
335
QList<Road*> Roads, Result;
336
for (int i=0; i<theDock->size(); ++i)
337
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
340
if (Roads.size() < 2)
346
for (int i=0; i<R1->size()-1; ++i) {
347
P a(R1->getNode(i)->position().lon(), R1->getNode(i)->position().lat());
348
P b(R1->getNode(i+1)->position().lon(), R1->getNode(i+1)->position().lat());
349
ggl::segment<P> s1(a, b);
351
for (int j=0; j<R2->size()-1; ++j) {
352
P c(R2->getNode(j)->position().lon(), R2->getNode(j)->position().lat());
353
P d(R2->getNode(j+1)->position().lon(), R2->getNode(j+1)->position().lat());
354
ggl::segment<P> s2(c, d);
356
std::vector<ggl::point_2d> intersected;
357
// ggl::intersection < ggl::point_2d, ggl::segment, ggl::segment, std::back_insert_iterator< std::vector<ggl::point_2d> > >
358
// (s1, s2, std::back_inserter(intersected));
359
ggl::intersection<ggl::point_2d>(s1, s2, std::back_inserter(intersected));
361
if (intersected.size()) {
364
TrackPoint* pt = new TrackPoint(Coord(qRound(intersected[0].y()), qRound(intersected[0].x())));
365
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(R1->layer()),pt,true));
366
theList->add(new RoadAddTrackPointCommand(R1,pt,i+1,theDocument->getDirtyOrOriginLayer(R1->layer())));
367
theList->add(new RoadAddTrackPointCommand(R2,pt,j+1,theDocument->getDirtyOrOriginLayer(R2->layer())));
377
// QList<Road*> Roads, Result;
378
// for (int i=0; i<theDock->size(); ++i)
379
// if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
380
// Roads.push_back(R);
382
// if (Roads.size() < 2)
385
// Road* R1 = Roads[0];
386
// Road* R2 = Roads[1];
388
// std::vector<ggl::point_2d> intersected;
389
// ggl::intersection <std::vector<ggl::point_2d>, std::vector<TrackPointPtr>, std::vector<TrackPointPtr>, std::back_insert_iterator <std::vector<ggl::point_2d> > >
390
// (R1->getNodes(), R2->getNodes(), std::back_inserter(intersected));
393
// return intersected.size();
395
// for (int i=0; i<intersected.size()-1; ++i) {
396
// TrackPoint* pt = new TrackPoint(Coord(qRound(intersected[i].y()), qRound(intersected[i].x())));
397
// theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(R1->layer()),pt,true));
398
// theList->add(new RoadAddTrackPointCommand(R1,pt,i+1,theDocument->getDirtyOrOriginLayer(R1->layer())));
399
// theList->add(new RoadAddTrackPointCommand(R2,pt,j+1,theDocument->getDirtyOrOriginLayer(R2->layer())));
402
// return intersected.size();
405
#define STREET_NUMBERS_LENGTH 1500.0
406
#define STREET_NUMBERS_ANGLE 30.0
408
void createStreetNumbers(MapDocument* theDocument, CommandList* theList, Road* theRoad, bool Left)
410
QString streetName = theRoad->tagValue("name", "");
415
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),R,true));
416
theList->add(new SetTagCommand(R, "addr:interpolation", ""));
417
theList->add(new SetTagCommand(R, "addr:street", streetName));
420
for (int j=0; j < theRoad->size(); j++) {
422
l2 = QLineF(theRoad->getNode(j)->position().toPointF(), theRoad->getNode(j+1)->position().toPointF());
424
l.setAngle(l2.angle() + 180.);
427
if (j == theRoad->size()-1) {
428
l = QLineF(theRoad->getNode(j)->position().toPointF(), theRoad->getNode(j-1)->position().toPointF());
430
l2.setAngle(l.angle() + 180.);
432
l = QLineF(theRoad->getNode(j)->position().toPointF(), theRoad->getNode(j-1)->position().toPointF());
433
l2 = QLineF(theRoad->getNode(j)->position().toPointF(), theRoad->getNode(j+1)->position().toPointF());
435
nv = l.normalVector().unitVector();
437
double theAngle = (l.angle() - l2.angle());
438
if (theAngle < 0.0) theAngle = 360. + theAngle;
440
nv.setAngle(l2.angle() + theAngle);
441
nv.setLength(STREET_NUMBERS_LENGTH/sin(angToRad(theAngle)));
443
nv.setAngle(nv.angle() + 180.0);
445
QLineF lto(prevPoint, nv.p2());
446
lto.setLength(lto.length()+STREET_NUMBERS_LENGTH);
449
bool intersectedTo = false;
450
for (int k=0; k < theRoad->getNode(j)->sizeParents(); ++k) {
451
Road* I = CAST_WAY(theRoad->getNode(j)->getParent(k));
452
if (!I || I == theRoad)
455
for (int m=0; m < I->size()-1; ++m) {
456
QLineF l3 = QLineF(I->getNode(m)->position().toPointF(), I->getNode(m+1)->position().toPointF());
457
QPointF theIntersection;
458
if (lto.intersect(l3, &theIntersection) == QLineF::BoundedIntersection) {
459
intersectedTo = true;
460
QLineF lt = QLineF(prevPoint, theIntersection);
461
if (lt.length() < lto.length())
468
QLineF lfrom = QLineF(nv.p2(), prevPoint);
469
lfrom.setLength(lfrom.length()*2.);
472
bool intersectedFrom = false;
473
for (int k=0; k < theRoad->getNode(j-1)->sizeParents(); ++k) {
474
Road* I = CAST_WAY(theRoad->getNode(j-1)->getParent(k));
475
if (!I || I == theRoad)
478
for (int m=0; m < I->size()-1; ++m) {
479
QLineF l3 = QLineF(I->getNode(m)->position().toPointF(), I->getNode(m+1)->position().toPointF());
480
QPointF theIntersection;
481
if (lfrom.intersect(l3, &theIntersection) == QLineF::BoundedIntersection) {
482
intersectedFrom = true;
483
QLineF lt = QLineF(nv.p2(), theIntersection);
484
if (lt.length() < lfrom.length())
489
if (intersectedFrom) {
490
lfrom.setLength(lfrom.length() - STREET_NUMBERS_LENGTH);
494
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),R,true));
495
theList->add(new SetTagCommand(R, "addr:interpolation", ""));
496
theList->add(new SetTagCommand(R, "addr:street", streetName));
498
N = new TrackPoint(Coord(pfrom));
499
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),N,true));
500
theList->add(new RoadAddTrackPointCommand(R, N, theDocument->getDirtyOrOriginLayer(R->layer())));
501
theList->add(new SetTagCommand(N, "addr:housenumber", ""));
509
lto.setLength(lto.length() - STREET_NUMBERS_LENGTH);
512
N = new TrackPoint(Coord(pto));
513
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),N,true));
514
theList->add(new RoadAddTrackPointCommand(R, N, theDocument->getDirtyOrOriginLayer(R->layer())));
515
theList->add(new SetTagCommand(N, "addr:housenumber", ""));
518
if (theAngle < 85. || theAngle > 95. || j== 0 || j == theRoad->size()-1) {
519
N = new TrackPoint(Coord(nv.p2()));
520
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),N,true));
521
theList->add(new RoadAddTrackPointCommand(R, N, theDocument->getDirtyOrOriginLayer(R->layer())));
522
theList->add(new SetTagCommand(N, "addr:housenumber", ""));
531
void addStreetNumbers(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
534
for (int i=0; i<theDock->size(); ++i)
535
if (Road* R = CAST_WAY(theDock->selection(i)))
541
QList<Road*>::const_iterator it = Roads.constBegin();
542
for (;it != Roads.constEnd(); ++it) {
543
if((*it)->size() < 2)
546
createStreetNumbers(theDocument, theList, (*it), false);
547
createStreetNumbers(theDocument, theList, (*it), true);
550
if (Roads.size() == 1)
551
theList->setFeature(Roads.at(0));
554
void alignNodes(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
556
if (theDock->size() < 3) //thre must be at least 3 nodes to align something
559
//We build a list of selected nodes
560
QList<TrackPoint*> Nodes;
561
for (int i=0; i<theDock->size(); ++i)
562
if (TrackPoint* N = dynamic_cast<TrackPoint*>(theDock->selection(i)))
565
//we check that we have at least 3 nodes and the first two can give a line
568
if(Nodes[0]->position() == Nodes[1]->position())
571
//we do the alignement
573
const Coord p1(Nodes[0]->position());
574
const Coord p2(Nodes[1]->position()-p1);
575
for (int i=2; i<Nodes.size(); ++i) {
576
pos=Nodes[i]->position()-p1;
577
rotate(pos,-angle(p2));
579
rotate(pos,angle(p2));
581
theList->add(new MoveTrackPointCommand( Nodes[i], pos, theDocument->getDirtyOrOriginLayer(Nodes[i]->layer()) ));
585
void mergeNodes(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
587
if (theDock->size() <= 1)
589
QList<TrackPoint*> Nodes;
590
QList<MapFeature*> alt;
591
for (int i=0; i<theDock->size(); ++i)
592
if (TrackPoint* N = dynamic_cast<TrackPoint*>(theDock->selection(i)))
594
TrackPoint* merged = Nodes[0];
595
alt.push_back(merged);
596
for (int i=1; i<Nodes.size(); ++i) {
597
MapFeature::mergeTags(theDocument, theList, merged, Nodes[i]);
598
theList->add(new RemoveFeatureCommand(theDocument, Nodes[i], alt));
602
void detachNode(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
604
QList<Road*> Roads, Result;
605
QList<TrackPoint*> Points;
606
for (int i=0; i<theDock->size(); ++i)
607
if (Road* R = dynamic_cast<Road*>(theDock->selection(i)))
609
else if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(theDock->selection(i)))
610
Points.push_back(Pt);
612
if (Roads.size() > 1 && Points.size() > 1)
615
if (Roads.size() == 0 && Points.size())
617
for (int i=0; i<Points.size(); ++i) {
618
Road * R = Road::GetSingleParentRoad(Points[i]);
620
theList->add(new RoadRemoveTrackPointCommand(R, Points[i],
621
theDocument->getDirtyOrOriginLayer(R)));
625
if (Roads.size() > 1 && Points.size() == 1)
627
for (int i=0; i<Roads.size(); ++i) {
628
if (Roads[i]->find(Points[0]) < Roads[i]->size())
629
theList->add(new RoadRemoveTrackPointCommand(Roads[i], Points[0],
630
theDocument->getDirtyOrOriginLayer(Roads[i])));
634
if (Roads.size() == 1 && Points.size())
636
for (int i=0; i<Points.size(); ++i) {
637
if (Roads[0]->find(Points[i]) < Roads[0]->size())
638
theList->add(new RoadRemoveTrackPointCommand(Roads[0], Points[i],
639
theDocument->getDirtyOrOriginLayer(Roads[0])));
644
void commitFeatures(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
646
QList<MapFeature*> alt;
647
QList<MapFeature*> Features;
649
for (int i=0; i<theDock->size(); ++i)
650
if (!theDock->selection(i)->isDirty())
651
Features.push_back(theDock->selection(i));
652
for (int i=0; i<Features.size(); ++i) {
653
if (TrackPoint* N = dynamic_cast<TrackPoint *>(Features[i])) {
654
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),N,true));
656
if (Road* R = dynamic_cast<Road *>(Features[i])) {
657
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),R,true));
658
for (int j=0; j < R->size(); ++j) {
659
if (!Features.contains(R->get(j))) {
660
theList->add(new AddFeatureCommand(theDocument->getDirtyOrOriginLayer(),R->get(j),true));
667
void addRelationMember(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
669
Relation* theRelation = NULL;
670
QList<MapFeature*> Features;
671
for (int i=0; i<theDock->size(); ++i)
672
if ((theDock->selection(i)->getClass() == "Relation") && !theRelation)
673
theRelation = dynamic_cast<Relation*>(theDock->selection(i));
675
Features.push_back(theDock->selection(i));
677
if (!(theRelation && Features.size())) return;
679
for (int i=0; i<Features.size(); ++i) {
680
theList->add(new RelationAddFeatureCommand(theRelation, "", Features[i], theDocument->getDirtyOrOriginLayer(theRelation->layer())));
684
void removeRelationMember(MapDocument* theDocument, CommandList* theList, PropertiesDock* theDock)
686
Relation* theRelation = NULL;
687
QList<MapFeature*> Features;
688
for (int i=0; i<theDock->size(); ++i)
689
if ((theDock->selection(i)->getClass() == "Relation") && !theRelation)
690
theRelation = dynamic_cast<Relation*>(theDock->selection(i));
692
Features.push_back(theDock->selection(i));
694
if (!theRelation && Features.size() == 1)
695
theRelation = MapFeature::GetSingleParentRelation(Features[0]);
696
if (!(theRelation && Features.size())) return;
699
for (int i=0; i<Features.size(); ++i) {
700
if ((idx = theRelation->find(Features[i])) != theRelation->size())
701
theList->add(new RelationRemoveFeatureCommand(theRelation, idx, theDocument->getDirtyOrOriginLayer(theRelation->layer())));