source: subversion/applications/lib/libosm/Components.cpp @ 34693

Last change on this file since 34693 was 14949, checked in by nienhueser, 10 years ago

API version is now 0.6

File size: 9.1 KB
Line 
1/*
2
3 Copyright (C) 2005 Nick Whitelegg, Hogweed Software, nick@hogweed.org
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
18
19 */
20// 180306 updated for 0.3
21#include "Components.h"
22#include <iostream>
23#include <fstream>
24#include <iomanip>
25#include <string>
26#include <sstream>
27#include <shapefil.h>
28#include "Node.h"
29#include "Parser.h"
30#include "Way.h"
31#include <vector>
32#include <fstream>
33#include "llgr.h"
34#include "FeatureClassification.h"
35#include "FeaturesParser.h"
36
37#include "ccoord/LatLng.h"
38#include "ccoord/OSRef.h"
39
40using namespace std;
41
42namespace OSM
43{
44
45Components::Components() :
46        nodes(), ways(), nextNodeId(-1), nextSegmentId(-1), nextWayId(-1),
47                        destroyComponents(true)
48{
49        nodeIterator = nodes.begin();
50        wayIterator = ways.begin();
51}
52
53Components::~Components()
54{
55        if (destroyComponents)
56                destroy();
57}
58
59void Components::setDestroyComponents(bool b)
60{
61        destroyComponents = b;
62}
63
64void Components::destroy()
65{
66        for (map<int, Node*>::iterator i = nodes.begin(); i != nodes.end(); i++)
67                delete i->second;
68
69        for (map<int, Way*>::iterator i = ways.begin(); i != ways.end(); i++)
70                delete i->second;
71}
72
73int Components::addNode(Node *n)
74{
75        int realID = n->id() ? n->id() : nextNodeId--;
76        n->setId(realID);
77        nodes[realID] = n;
78        return realID;
79}
80
81int Components::addWay(Way *w)
82{
83        int realID = w->id() ? w->id() : nextWayId--;
84        w->setId(realID);
85        ways[realID] = w;
86        return realID;
87}
88
89Node *Components::getNode(int i) const
90{
91        map<int,Node*>::const_iterator iter = nodes.find(i);
92        if (iter != nodes.end())
93        {
94                return iter->second;
95        }
96
97        return NULL;
98}
99
100Way *Components::getWay(int i) const
101{
102        map<int,Way*>::const_iterator iter = ways.find(i);
103        if (iter != ways.end())
104        {
105                return iter->second;
106        }
107
108        return NULL;
109}
110
111Node *Components::nextNode()
112{
113        Node *n = (nodeIterator == nodes.end()) ? NULL : nodeIterator->second;
114        nodeIterator++;
115        return n;
116}
117
118Way *Components::nextWay()
119{
120        Way *w = (wayIterator == ways.end()) ? NULL : wayIterator->second;
121        wayIterator++;
122        return w;
123}
124
125void Components::rewindNodes()
126{
127        nodeIterator = nodes.begin();
128}
129void Components::rewindWays()
130{
131        wayIterator = ways.begin();
132}
133bool Components::hasMoreNodes() const
134{
135        return nodeIterator != nodes.end();
136}
137bool Components::hasMoreWays() const
138{
139        return wayIterator != ways.end();
140}
141
142vector<double> Components::getWayCoords(int id) const
143{
144        vector<double> coords;
145        Node *n1;
146        Way *w = getWay(id);
147        if (w)
148        {
149                for (int count = 0; count < w->nNodes(); count++)
150                {
151                        n1 = getNode(w->getNode(count));
152                        if (n1)
153                        {
154                                coords.push_back(n1->getLon());
155                                coords.push_back(n1->getLat());
156                        }
157                }
158        }
159        return coords;
160}
161
162// 310107 adds null node IDs too
163vector<int> Components::getWayNodes(int wayid) const
164{
165        vector<int> ids;
166        Way *w = getWay(wayid);
167        Node *n = 0;
168        if (w)
169        {
170                for (int count = 0; count < w->nNodes(); count++)
171                {
172                        n = getNode(w->getNode(count));
173                        if (n)// && getNode(s->firstNode()) && getNode(s->secondNode()))
174                        {
175                                ids.push_back(n->id());
176                        }
177                }
178        }
179        return ids;
180}
181
182// get all way tags
183// this could be used eg. to work out how many columns are needed in a shapefile
184set<string> Components::getWayTags(FeatureClassification *classification,
185                bool doArea) const
186{
187        Way *w;
188        set<string> tags;
189        vector<string> curTags;
190
191        std::map<int, Way*>::const_iterator iter = ways.begin();
192        for (; iter != ways.end(); ++iter)
193        {
194                if ((classification == NULL) || (doArea == true
195                                && classification->getFeatureClass(iter->second) == "area")
196                                || (doArea == false && classification->getFeatureClass(
197                                                iter->second) != "area"))
198                {
199                        curTags = iter->second->getTags();
200                        for (unsigned int count = 0; count < curTags.size(); ++count)
201                                tags.insert(curTags[count]);
202                }
203        }
204        return tags;
205}
206
207set<string> Components::getNodeTags() const
208{
209        set<string> tags;
210        vector<string> curTags;
211
212        map<int, Node*>::const_iterator iter = nodes.begin();
213        for (; iter != nodes.end(); ++iter)
214        {
215                curTags = iter->second->getTags();
216                for (unsigned int count = 0; count < curTags.size(); ++count)
217                {
218                        tags.insert(curTags[count]);
219                }
220        }
221        return tags;
222}
223
224int Components::getParentWayOfNode(int nodeid) const
225{
226        Node *n = getNode(nodeid);
227        if (n)
228        {
229                std::map<int, Way*>::const_iterator iter = ways.begin();
230                for (; iter != ways.end(); ++iter)
231                {
232                        for (int count = 0; count < iter->second->nNodes(); ++count)
233                        {
234                                if (iter->second->getNode(count) == nodeid)
235                                {
236                                        return iter->second->id();
237                                }
238                        }
239                }
240        }
241        return 0;
242}
243
244void Components::toXML(ostream &strm)
245{
246        strm << "<?xml version='1.0'?>" << endl << "<osm version='0.6'>" << endl;
247        rewindNodes();
248        while (hasMoreNodes())
249        {
250                Node *n = nextNode();
251                n->toXML(strm);
252        }
253        rewindWays();
254        while (hasMoreWays())
255        {
256                Way *w = nextWay();
257                w->toXML(strm);
258        }
259        strm << "</osm>" << endl;
260}
261
262void Components::toOSGB()
263{
264        rewindNodes();
265        while (hasMoreNodes())
266        {
267                Node *n = nextNode();
268                LatLng latLng(n->getLat(), n->getLon());
269                latLng.toOSGB36();
270                OSRef ref = latLng.toOSRef();
271                n->setCoords(ref.getNorthing(), ref.getEasting());
272        }
273}
274
275bool Components::makeShp(const string& nodes, const string& ways,
276                const string& areas, const string &featuresFile)
277{
278        ifstream in(featuresFile.c_str());
279        if (in.good())
280        {
281                FeatureClassification *featureClassification =
282                                FeaturesParser::parse(in);
283                in.close();
284                if (featureClassification && makeNodeShp(nodes))
285                {
286                        if (makeWayShp(ways, featureClassification))
287                        {
288                                if (makeWayShp(areas, featureClassification, true))
289                                {
290                                        return true;
291                                }
292                        }
293                }
294        }
295        return false;
296}
297
298bool Components::makeNodeShp(const string& shpname)
299{
300        SHPHandle shp = SHPCreate(shpname.c_str(), SHPT_POINT);
301        if (shp)
302        {
303                DBFHandle dbf = DBFCreate(shpname.c_str());
304                if (dbf)
305                {
306                        map<int, string> fields;
307                        set<string> nodeTags = getNodeTags();
308                        for (set<string>::iterator i = nodeTags.begin(); i
309                                        != nodeTags.end(); i++)
310                        {
311                                fields[DBFAddField(dbf, i->c_str(), FTString, 255, 0)] = *i;
312                        }
313
314                        double lon, lat;
315
316                        rewindNodes();
317                        while (hasMoreNodes())
318                        {
319                                Node *node = nextNode();
320
321                                // We're only interested in nodes with tags
322                                if (node && node->hasTags())
323                                {
324                                        lon = node->getLon();
325                                        lat = node->getLat();
326                                        SHPObject *object = SHPCreateSimpleObject(SHPT_POINT,1,
327                                                        &lon, &lat, NULL);
328
329                                        int objid = SHPWriteObject(shp, -1, object);
330
331                                        SHPDestroyObject(object);
332
333                                        for (map<int, string>::iterator j = fields.begin(); j
334                                                        != fields.end(); j++)
335                                        {
336                                                DBFWriteStringAttribute(dbf, objid, j->first,
337                                                                node->getTag(j->second).c_str());
338                                        }
339                                }
340                        }
341
342                        DBFClose(dbf);
343                }
344                else
345                {
346                        cerr << "could not open node dbf" << endl;
347                        return false;
348                }
349                SHPClose(shp);
350        }
351        else
352        {
353                cerr << "could not open node shp" << endl;
354                return false;
355        }
356
357        return true;
358}
359
360bool Components::makeWayShp(const string &shpname,
361                FeatureClassification *classification, bool doArea)
362{
363        int shpclass = (doArea == true) ? SHPT_POLYGON : SHPT_ARC;
364        // ARC means polyline!
365        SHPHandle shp = SHPCreate(shpname.c_str(), shpclass);
366        if (shp)
367        {
368                DBFHandle dbf = DBFCreate(shpname.c_str());
369                if (dbf)
370                {
371                        map<int, string> fields;
372                        set<string> wayTags = getWayTags(classification, doArea);
373                        for (set<string>::iterator i = wayTags.begin(); i != wayTags.end(); i++)
374                        {
375                                fields[DBFAddField(dbf, i->c_str(), FTString, 255, 0)] = *i;
376                        }
377
378                        map<int, Way*>::iterator i = ways.begin();
379                        //rewindWays();
380                        vector<double> wayCoords, longs, lats;
381
382                        while (i != ways.end())
383                        //while(hasMoreWays())
384                        {
385                                //Way *way = nextWay();
386                                Way *way = i->second;
387                                if (way)
388                                {
389                                        wayCoords = getWayCoords(way->id());
390                                        if (wayCoords.size() && ((doArea == true
391                                                        && classification->getFeatureClass(way) == "area")
392                                                        || (doArea == false
393                                                                        && classification->getFeatureClass(way)
394                                                                                        != "area")))
395                                        {
396                                                longs.clear();
397                                                lats.clear();
398                                                for (unsigned int count = 0; count < wayCoords.size(); count
399                                                                += 2)
400                                                        longs.push_back(wayCoords[count]);
401                                                for (unsigned int count = 1; count < wayCoords.size(); count
402                                                                += 2)
403                                                        lats.push_back(wayCoords[count]);
404
405                                                SHPObject *object = SHPCreateSimpleObject(shpclass,
406                                                                wayCoords.size() / 2, &(longs[0]), &(lats[0]),
407                                                                NULL);
408
409                                                int objid = SHPWriteObject(shp, -1, object);
410
411                                                SHPDestroyObject(object);
412
413                                                for (map<int, string>::iterator j = fields.begin(); j
414                                                                != fields.end(); j++)
415                                                {
416                                                        DBFWriteStringAttribute(dbf, objid, j->first,
417                                                                        way->getTag(j->second).c_str());
418                                                }
419                                        }
420                                }
421                                i++;
422                        }
423
424                        DBFClose(dbf);
425                }
426                else
427                {
428                        cerr << "could not open way dbf" << endl;
429                        return false;
430                }
431                SHPClose(shp);
432        }
433        else
434        {
435                cerr << "could not open way shp" << endl;
436                return false;
437        }
438
439        return true;
440}
441
442}
Note: See TracBrowser for help on using the repository browser.