source: subversion/applications/editors/osm-editor/qt3/Components2.cpp @ 32040

Last change on this file since 32040 was 1158, checked in by nick, 14 years ago

moved current version to qt3 directory in preparation for qt4

File size: 16.1 KB
Line 
1/*
2 
3Copyright (C) 2005 Nick Whitelegg, Hogweed Software, nick@hogweed.org
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
18
19 */
20// 180306 updated for 0.3   
21#include "Components2.h"
22#include <iostream>
23#include <iomanip>
24#include <string>
25#include <sstream>
26
27
28using std::endl;
29using std::setw;
30using std::setfill;
31using std::setprecision;
32using std::cerr;
33
34using std::cout;
35
36namespace OpenStreetMap
37{
38
39
40void Components2::destroy()
41{
42    for(vector<Node*>::iterator i=nodes.begin(); i!=nodes.end(); i++)
43        delete *i;
44
45    for(vector<Segment*>::iterator i=segments.begin(); i!=segments.end(); i++)
46        delete *i;
47
48    for(vector<Way*>::iterator i=ways.begin(); i!=ways.end(); i++)
49        delete *i;
50}
51
52// 260306 distinguish trackpoints, they are only there for referencing the
53// GPS trace - the user has to create nodes.
54// Really, they should be put in a class of their own (on the TODO list)
55
56Node *Components2::getNearestNode(double lat, double lon,double limit)
57{
58    double mindist=limit, dist;
59    Node *nearest = NULL;
60    for(int count=0; count<nodes.size(); count++)
61    {
62        if((dist=OpenStreetMap::dist(lat,lon,
63                    nodes[count]->getLat(),nodes[count]->getLon()))<limit)
64        {
65            if(dist<mindist && nodes[count]->getType()!="trackpoint")
66            {
67                mindist=dist;
68                nearest = nodes[count];
69            }
70        }
71    }
72    return nearest;
73}
74
75int Components2::getNearestTrackPoint (double lat,double lon,double limit)
76{
77    double mindist=limit, dist;
78    int nearest = -1;
79    for(int count=0; count<trackpoints.size(); count++)
80    {
81        if((dist=OpenStreetMap::dist(lat,lon,
82                    trackpoints[count]->getLat(),
83                                        trackpoints[count]->getLon()))<limit)
84        {
85            if(dist<mindist)
86            {
87                mindist=dist;
88                nearest = count;
89            }
90        }
91    }
92    return nearest;
93}
94
95vector<Node*> Components2::getNearestNodes(double lat, double lon,double limit)
96{
97    vector<Node*> nearestNodes;     
98    double dist;
99    for(int count=0; count<nodes.size(); count++)
100    {
101        if((dist=OpenStreetMap::dist(lat,lon,
102                    nodes[count]->getLat(),nodes[count]->getLon()))<limit)
103        {
104                        if(nodes[count]->getType()=="node")
105                nearestNodes.push_back(nodes[count]);
106        }
107    }
108    return nearestNodes;
109}
110
111// find the segment which is common to two nodes
112Segment* Components2::getSeg(vector<Node*> &n1, vector<Node*> &n2)
113{
114    bool found;
115    for(int count=0; count<segments.size(); count++)
116    {
117        found = false;
118
119        for(int count2=0; count2<n1.size(); count2++)
120        {
121            if (segments[count]->contains(n1[count2]))
122            {
123                found=true;
124                break;
125            }
126        }
127
128        if(found)
129        {
130            for(int count2=0; count2<n2.size(); count2++)
131            {
132                if (segments[count]->contains(n2[count2]))
133                    return segments[count];
134            }
135        }
136    }
137    return NULL;
138}
139
140// get a vector of segments containing a node
141vector<Segment*> Components2::getSegs(Node * n)
142{
143    vector<Segment*> foundSegs;
144
145    for(int count=0; count<segments.size(); count++)
146    {
147        if(segments[count]->contains(n))
148            foundSegs.push_back(segments[count]);
149    }
150    return foundSegs;
151}
152
153// gets the new nodes as XML
154QByteArray Components2::getNewNodesXML()
155{
156    QByteArray xml;
157    QTextStream stream (xml, IO_WriteOnly);
158    stream<<"<osm version='0.3'>" << endl;
159    for(int count=0; count<nodes.size(); count++)
160    {
161        if(nodes[count]->getOSMID()<0)
162        {
163            nodes[count]->toOSM(stream);
164        }
165    }
166    stream<<"</osm>";
167    return xml;
168}
169
170// gets the new segments as XML
171QByteArray Components2::getNewSegmentsXML()
172{
173    QByteArray xml;
174    QTextStream stream (xml, IO_WriteOnly);
175    stream<<"<osm version='0.3'>" << endl;
176    for(int count=0; count<segments.size(); count++)
177    {
178        if(segments[count]->getOSMID()<0)
179        {
180            segments[count]->segToOSM(stream);
181        }
182    }
183    stream<<"</osm>" <<endl;
184    return xml;
185}
186
187// gets the new nodes as a vector
188vector<Node*> Components2::getNewNodes()
189{
190        vector<Node*> newNodes;
191    for(int count=0; count<nodes.size(); count++)
192    {
193        if(nodes[count]->getOSMID()<0)
194            newNodes.push_back(nodes[count]);
195    }
196        return newNodes;
197}
198
199// gets the new segments as a vector
200vector<Segment*>  Components2::getNewSegments()
201{
202        vector<Segment*> newSegments;
203    for(int count=0; count<segments.size(); count++)
204    {
205        if(segments[count]->getOSMID()<0)
206                        newSegments.push_back(segments[count]);
207    }
208        return newSegments;
209}
210
211// allocate new node IDs to new segments.
212// This is called after the new nodes have been created in OSM when we do
213// a batch upload of new nodes and segments.
214// This is hacky in the extreme but is a stopgap measure as there will be
215// a server routine to take a load of new nodes and segments and add them to
216// the database.
217
218// 130506 removed hacky crap for doing multiple nodes/segs at once - the
219// scheduler should now handle this (at least it has been so far....)
220
221// Merges these Components with another set
222bool Components2::merge(Components2 *comp)
223{
224    int segIdx = minSegID(), nodeIdx = minNodeID();
225    Node *curNode;
226    Segment *curSeg;
227        Way *curWay;
228        Area *curArea;
229        TrackPoint *curTrackPoint;
230        for(int count=0; count<comp->nNodes(); count++)
231    {
232        curNode = comp->getNode(count); 
233        if(curNode->getOSMID()<0)
234            curNode->setOSMID(--nodeIdx);
235        addNode(curNode);
236    }
237        for(int count=0; count<comp->nSegments(); count++)
238    {
239        curSeg = comp->getSegment(count);
240        if(curSeg->getOSMID()<0)
241            curSeg->setOSMID(--segIdx);
242        addSegment(curSeg);
243    }
244        for(int count=0; count<comp->nWays(); count++)
245    {
246        curWay = comp->getWay(count);
247        if(curWay->getOSMID()<0)
248            curWay->setOSMID(--segIdx);
249                curWay->setComponents(this); // yeuch - hacky
250        addWay(curWay);
251    }
252        for(int count=0; count<comp->nAreas(); count++)
253    {
254        curArea = comp->getArea(count);
255        if(curArea->getOSMID()<0)
256            curArea->setOSMID(--segIdx);
257                curArea->setComponents(this); // yeuch - hacky
258        addArea(curArea);
259    }
260        for(int count=0; count<comp->nTrackPoints(); count++)
261    {
262        curTrackPoint = comp->getTrackPoint(count);
263        trackpoints.push_back(curTrackPoint);
264    }
265
266    nextNodeId = nodeIdx-1;
267    nextSegId = segIdx-1;
268
269    return true;
270}
271
272void Components2::toOSM(QTextStream &strm, bool allUid)
273{
274    strm << "<osm version='0.3'>" << endl;
275    for(int count=0; count<nodes.size(); count++)
276        nodes[count]->toOSM(strm,allUid);
277    for(int count=0; count<segments.size(); count++)
278        segments[count]->segToOSM(strm,allUid);
279        cerr<<"size of ways=" << ways.size() << endl;
280    for(int count=0; count<ways.size(); count++)
281        ways[count]->wayToOSM(strm,allUid);
282    for(int count=0; count<areas.size(); count++)
283        areas[count]->wayToOSM(strm,allUid);
284    strm << "</osm>";
285}
286
287void Components2::removeTrackPoints()
288{
289    for(vector<Node*>::iterator i=nodes.begin(); i!=nodes.end(); i++)
290    {
291        cerr<<(*i)->getType() << endl;
292        if((*i)->getType()=="trackpoint")
293        {
294            delete *i;
295            nodes.erase(i);
296            i--;
297        }
298    }
299}
300
301// 'delete' a node
302// note it doesn't actually erase it from memory - just removes it from
303// the list
304bool Components2::deleteNode(Node *n)
305{
306    for(vector<Node*>::iterator i=nodes.begin(); i!=nodes.end(); i++)
307    {
308        if((*i)==n)
309        {
310            nodes.erase(i);
311            return true;
312        }
313    }
314    return false;
315}
316
317// 'delete' a segment
318// note it doesn't actually erase it from memory - just removes it from
319// the list
320bool Components2::deleteSegment(Segment *s)
321{
322    for(vector<Segment*>::iterator i=segments.begin(); i!=segments.end(); i++)
323    {
324        if((*i)==s)
325        {
326            segments.erase(i);
327            return true;
328        }
329    }
330    return false;
331}
332
333// 'delete' a way
334// note it doesn't actually erase it from memory - just removes it from
335// the list
336bool Components2::deleteWay(Way *w)
337{
338    for(vector<Way*>::iterator i=ways.begin(); i!=ways.end(); i++)
339    {
340        if((*i)==w)
341        {
342            ways.erase(i);
343                        for(int count=0; count<segments.size(); count++)
344                        {
345                                if(segments[count]->getWayID()==w->getOSMID())
346                                        segments[count]->setWayID(0);
347                        }
348            return true;
349        }
350    }
351    return false;
352}
353
354EarthPoint Components2::getAveragePoint()
355{
356    EarthPoint avg;
357    avg.x=avg.y=0.0;       
358
359    for(int count=0; count<nodes.size(); count++)
360    {
361        avg.y += nodes[count]->getLat();
362        avg.x += nodes[count]->getLon();
363    }
364
365    avg.y /= nodes.size();
366    avg.x /= nodes.size();
367
368    return avg;
369}
370EarthPoint Components2::getAverageTrackPoint()
371{
372    EarthPoint avg;
373    avg.x=avg.y=0.0;       
374
375    for(int count=0; count<trackpoints.size(); count++)
376    {
377        avg.y += trackpoints[count]->getLat();
378        avg.x += trackpoints[count]->getLon();
379    }
380
381    avg.y /= trackpoints.size();
382    avg.x /= trackpoints.size();
383
384    return avg;
385}
386
387Node *Components2::addOSMNode(int id,double lat, double lon,const QString& name,
388            const QString& type, const QString& timestamp)
389{
390    Node *newNode = new Node(id,lat,lon,name,type,timestamp);
391    addNode(newNode);
392    if(id-1<nextNodeId)
393        nextNodeId = id-1;
394    return newNode;
395}
396
397TrackPoint *Components2::addTrackPoint(double lat, double lon,
398                                const QString& timestamp)
399{
400    TrackPoint *newTP = new TrackPoint(lat,lon,timestamp);
401    trackpoints.push_back(newTP);
402    return newTP;
403}
404
405Segment * Components2::addOSMSegment (int id,Node *n1, Node *n2)
406{
407    n1->trackpointToNode();
408    n2->trackpointToNode();
409    Segment *seg = new Segment(id,n1,n2);
410        addSegment(seg);
411    if(id-1<nextSegId)
412        nextSegId = id-1;
413    return seg;
414}
415
416int Components2::minNodeID()
417{
418    int id=0;
419    for(int count=0; count<nodes.size(); count++)
420    {
421        if(nodes[count]->getOSMID() < id)
422            id = nodes[count]->getOSMID();
423    }
424    return id;
425}
426
427int Components2::minSegID()
428{
429    int id=0;
430    for(int count=0; count<segments.size(); count++)
431    {
432        if(segments[count]->getOSMID() < id)
433            id = segments[count]->getOSMID();
434    }
435    return id;
436}
437
438// splits a segment at a point defined by a node
439// NB does dynamic allocation - the pair must be freed somewhere!
440std::pair<Segment*,Segment*>*
441        Components2::breakSegment(Segment *s, Node *newNode)
442{
443        int wayID;
444        std::pair<Segment*,Segment*>* p = new std::pair<Segment*,Segment*>;
445        p->first = new Segment(s->firstNode(),newNode,"",s->getType());
446        p->second =     new Segment(newNode,s->secondNode(),"",s->getType());
447
448        segments.push_back(p->first);
449        segments.push_back(p->second);
450
451        // If the segment is in a way, remove it from the way and add the two
452        // new segments to the way at the appropriate position
453       
454        // 180506 no longer do this, do separately as it makes code which also
455        // uploads the changes to OSM easier
456
457        deleteSegment(s);
458
459        return p;
460}
461
462// Saves GPX
463// saves trackpoints, and any node not of type "node" or
464// "trackpoint" as a waypoint
465// intended to be used immediately after reading the data from the GPS
466
467void Components2::toGPX(QTextStream& stream)
468{
469        stream.precision(10); // 250306 in response to request
470
471        stream << "<gpx version=\"1.0\" creator=\"osmeditor2\" "
472                        << " xmlns=\"http://www.topografix.com/GPX/1/0\">"<<endl
473                        << "<trk>" << endl << "<trkseg>" << endl;
474
475        /*
476        for(int count=0; count<nodes.size(); count++)
477        {
478                if(nodes[count]->getType()=="trackpoint")
479                {
480                        stream << "<trkpt lat=\""
481                                        << nodes[count]->getLat()
482                                   << "\" lon=\""
483                                   << nodes[count]->getLon()
484                                   << "\">" << endl;
485
486                        QString timestamp = nodes[count]->getTimestamp();
487
488                        if(timestamp!="")
489                                stream << "<time>" << timestamp  << "</time> "<< endl;
490       
491                        stream << "</trkpt>" << endl;
492                }
493        }
494        */
495
496        for(int count=0; count<trackpoints.size(); count++)
497        {
498                        stream << "<trkpt lat=\""
499                                        << trackpoints[count]->getLat()
500                                   << "\" lon=\""
501                                   << trackpoints[count]->getLon()
502                                   << "\">" << endl;
503
504                        QString timestamp = trackpoints[count]->getTimestamp();
505
506                        if(timestamp!="")
507                                stream << "<time>" << timestamp  << "</time> "<< endl;
508       
509                        stream << "</trkpt>" << endl;
510        }
511
512        stream << "</trkseg>" << endl << "</trk>" << endl;
513        for(int count=0; count<nodes.size(); count++)
514        {
515                if(nodes[count]->getType()!="trackpoint" &&
516                        nodes[count]->getType()!="node")
517                {
518                        stream << "<wpt lat=\""
519                                        << nodes[count]->getLat()
520                                   << "\" lon=\""
521                                   << nodes[count]->getLon()
522                                   << "\">" << endl;
523
524                        if(nodes[count]->getName()!="")
525                                stream << "<name>" << nodes[count]->getName() << "</name> "
526                                                << endl;
527                        if(nodes[count]->getType()!="")
528                                stream << "<type>" << nodes[count]->getType() << "</type> "
529                                                << endl;
530       
531                        stream << "</wpt>" << endl;
532                }
533        }
534        stream << "</gpx>" << endl;
535}
536
537Way * Components2::getWayByID(int id)
538{
539        for(int count=0; count<ways.size(); count++)
540        {
541                if((ways[count]->getOSMID()==id) && id)
542                        return ways[count];
543        }
544        return NULL;
545}
546
547Segment * Components2::getSegmentByID(int id)
548{
549        for(int count=0; count<segments.size(); count++)
550        {
551                if((segments[count]->getOSMID()==id) && id)
552                        return segments[count];
553        }
554        return NULL;
555}
556
557Segment *Components2::getNearestSegment(double lat, double lon,double limit)
558{
559    double mindist=limit, dist, lat1,lon1,lat2,lon2;
560    Segment *nearest = NULL;
561    for(int count=0; count<segments.size(); count++)
562    {
563                lat1 = segments[count]->firstNode()->getLat();
564                lon1 = segments[count]->firstNode()->getLon();
565                lat2 = segments[count]->secondNode()->getLat();
566                lon2 = segments[count]->secondNode()->getLon();
567       
568                // Find distance from point to this segment
569        if((dist=OpenStreetMap::distp(lon,lat,lon1,lat1,lon2,lat2))<limit)
570        {
571            if(dist<mindist)
572            {
573                mindist=dist;
574                nearest = segments[count];
575            }
576        }
577    }
578    return nearest;
579}
580
581bool Components2::nodeExists(int id)
582{
583        if(id)
584        {
585                for(int count=0; count<nodes.size(); count++)
586                {
587                        if(nodes[count]->getOSMID()==id)
588                                return true;
589                }
590        }
591        return false;
592}
593
594bool Components2::segmentExists(int id)
595{
596        if(id)
597        {
598                for(int count=0; count<segments.size(); count++)
599                {
600                        if(segments[count]->getOSMID()==id)
601                                return true;
602                }
603        }
604        return false;
605}
606
607bool Components2::wayExists(int id)
608{
609        if(id)
610        {
611                for(int count=0; count<ways.size(); count++)
612                {
613                        if(ways[count]->getOSMID()==id)
614                                return true;
615                }
616        }
617        return false;
618}
619
620bool Components2::areaExists(int id)
621{
622        if(id)
623        {
624                for(int count=0; count<areas.size(); count++)
625                {
626                        if(areas[count]->getOSMID()==id)
627                                return true;
628                }
629        }
630        return false;
631}
632
633void Components2::deleteTrackPoints(int start, int end)
634{
635        if(start>=0 && end<trackpoints.size())
636        {
637        for(int count=start; count<=end; count++)
638        {
639                        vector<TrackPoint*>::iterator i=trackpoints.begin()+start;
640                        delete *i;
641                        trackpoints.erase(i);
642                }
643    }
644}
645
646}
Note: See TracBrowser for help on using the repository browser.