1 /***************************************************************************
2  *   Copyright (C) 2016 by pgRouting developers                            *
3  *   project@pgrouting.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 t &or 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                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 
21 
22 
23 #include "parser/OSMDocumentParserCallback.h"
24 
25 #include <math.h>
26 #include <string>
27 #include <cassert>
28 #include <iostream>
29 #include <sstream>
30 #include "osm_elements/OSMDocument.h"
31 #include "osm_elements/Relation.h"
32 #include "osm_elements/osm_tag.h"
33 #include "osm_elements/Way.h"
34 #include "osm_elements/Node.h"
35 #include "utilities/print_progress.h"
36 
37 
38 namespace osm2pgr {
39 
40 /*
41 <relation id ="147411" version="5" timestamp="2010-01-22T17:02:14Z" uid ="24299" user="james_hiebert" changeset="3684904">
42     <member type="way" ref="25584788" role=""/>
43     <member type="way" ref="35064036" role=""/>
44     <member type="way" ref="35064035" role=""/>
45     <member type="way" ref="35064037" role=""/>
46     <member type="way" ref="35064038" role=""/>
47     <member type="way" ref="35065746" role=""/>
48     <member type="way" ref="48690404" role=""/>
49     <member type="way" ref="24221632" role=""/>
50     <tag k="name" v="Mt. Douglas Park Local Connector"/>
51     <tag k="network" v="rcn"/>
52     <tag k="route" v="bicycle"/>
53     <tag k="type" v="route"/>
54   </relation>
55  */
56 
57 void
show_progress()58 OSMDocumentParserCallback::show_progress() {
59 #if 0
60     try {
61         if (m_line == 0) return;
62         assert(m_rDocument.lines());
63         if (m_rDocument.lines() == 0) return;
64         if (((++m_line) % (m_rDocument.lines() / 100)) == 0) {
65             print_progress(m_rDocument.lines(), m_line);
66         }
67     } catch(...) {
68         m_line = 1;
69     }
70 #endif
71 }
72 
73 
74 /**
75   Parser callback for OSMDocument files
76   */
77 void
StartElement(const char * name,const char ** atts)78 OSMDocumentParserCallback::StartElement(
79         const char *name,
80         const char** atts) {
81     show_progress();
82 
83     if (strcmp(name, "osm") == 0) {
84         m_section = 1;
85     }
86 
87     if ((m_section == 1 && (strcmp(name, "way") == 0))
88             || (m_section == 2 && (strcmp(name, "relation") == 0))) {
89         ++m_section;
90     }
91 
92 
93     if (m_section == 1) {
94         if (strcmp(name, "node") == 0) {
95             last_node = new Node(atts);
96         }
97         if (strcmp(name, "tag") == 0) {
98             auto tag = last_node->add_tag(Tag(atts));
99             m_rDocument.add_config(last_node, tag);
100         }
101         return;
102     }
103 
104     if (m_section == 2) {
105         if (strcmp(name, "way") == 0) {
106             last_way = new Way(atts);
107         }
108         if (strcmp(name, "tag") == 0) {
109             auto tag = last_way->add_tag(Tag(atts));
110             m_rDocument.add_config(last_way, tag);
111         }
112 
113         if (strcmp(name, "nd") == 0) {
114             m_rDocument.add_node(*last_way, atts);
115         }
116         return;
117     }
118 
119     if (m_section == 3) {
120         /*
121          *  START RELATIONS CODE
122          */
123         if (strcmp(name, "relation") == 0) {
124             last_relation = new Relation(atts);
125             return;
126         }
127 
128         if (strcmp(name, "member") == 0) {
129             /*
130                <member type="node" ref="721818679" role="label"/>
131                <member type="way" ref="173424370" role=""/>
132                <member type="way" ref="48435091" role="link"/>
133                */
134             auto way_id = last_relation->add_member(atts);
135             if (way_id == -1) return;
136             assert(!last_relation->way_refs().empty());
137             if (m_rDocument.has_way(way_id)) {
138                 Way* way_ptr = m_rDocument.FindWay(way_id);
139                 way_ptr->insert_tags(last_relation->tags());
140             } else {
141                 assert(!last_relation->way_refs().empty());
142                 last_relation->way_refs().pop_back();
143             }
144 
145             return;
146         }
147         if (strcmp(name, "tag") == 0) {
148             auto tag = last_relation->add_tag(Tag(atts));
149             m_rDocument.add_config(last_relation, tag);
150         }
151     }
152     if (strcmp(name, "osm") == 0) {
153     }
154 }
155 
EndElement(const char * name)156 void OSMDocumentParserCallback::EndElement(const char* name) {
157     if (strcmp(name, "osm") == 0) {
158         m_rDocument.endOfFile();
159         show_progress();
160         return;
161     }
162 
163     if (strcmp(name, "node") == 0) {
164         m_rDocument.AddNode(*last_node);
165         delete last_node;
166         return;
167     }
168     if (strcmp(name, "way") == 0) {
169         m_rDocument.AddWay(*last_way);
170         if (m_rDocument.config_has_tag(last_way->tag_config())) {
171 
172             auto maxspeed = m_rDocument.maxspeed(last_way->tag_config());
173             if (last_way->maxspeed_forward() <= 0) {
174                 last_way->maxspeed_forward(maxspeed);
175             }
176             if (last_way->maxspeed_backward() <= 0) {
177                 last_way->maxspeed_backward(maxspeed);
178             }
179         }
180         delete last_way;
181         return;
182     }
183 
184     if (strcmp(name, "relation") == 0) {
185         if (m_rDocument.config_has_tag(last_relation->tag_config())) {
186             for (auto it = last_relation->way_refs().begin();  it != last_relation->way_refs().end(); ++it) {
187                 auto way_id = *it;
188                 assert(m_rDocument.has_way(way_id));
189                 if (m_rDocument.has_way(way_id)) {
190                     Way* way_ptr = m_rDocument.FindWay(way_id);
191                     way_ptr->tag_config(last_relation->tag_config());
192                     auto newValue = m_rDocument.maxspeed(
193                             last_relation->tag_config());
194                     if (way_ptr->maxspeed_forward() <= 0) {
195                         way_ptr->maxspeed_forward(newValue);
196                     }
197                     if (way_ptr->maxspeed_backward() <= 0) {
198                         way_ptr->maxspeed_backward(newValue);
199                     }
200                 }
201             }
202             m_rDocument.AddRelation(*last_relation);
203         }
204         // TODO add all other relations
205         delete last_relation;
206         return;
207     }
208 }
209 
210 }  // end namespace osm2pgr
211