2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #define _FILE_OFFSET_BITS 64
22 #define _LARGEFILE_SOURCE
23 #define _LARGEFILE64_SOURCE
39 #ifdef HAVE_POSTGRESQL
43 #define BUFFER_SIZE 1280
45 #define GENERATE_INDEX
48 #define debug_tile(x) 0
50 #define debug_tile(x) (!strcmp(x,"bcdbd") || !strcmp(x,"bcdbd") || !strcmp(x,"bcdbda") || !strcmp(x,"bcdbdb") || !strcmp(x,"bcdbdba") || !strcmp(x,"bcdbdbb") || !strcmp(x,"bcdbdbba") || !strcmp(x,"bcdbdbaa") || !strcmp(x,"bcdbdbacaa") || !strcmp(x,"bcdbdbacab") || !strcmp(x,"bcdbdbacaba") || !strcmp(x,"bcdbdbacabaa") || !strcmp(x,"bcdbdbacabab") || !strcmp(x,"bcdbdbacababb") || !strcmp(x,"bcdbdbacababba") || !strcmp(x,"bcdbdbacababbb") || !strcmp(x,"bcdbdbacababbd") || !strcmp(x,"bcdbdbacababaa") || !strcmp(x,"bcdbdbacababab") || !strcmp(x,"bcdbdbacababac") || !strcmp(x,"bcdbdbacababad") || !strcmp(x,"bcdbdbacabaaa") || !strcmp(x,"bcdbdbacabaaba") || !strcmp(x,"bcdbdbacabaabb") || !strcmp(x,"bcdbdbacabaabc") || !strcmp(x,"bcdbdbacabaabd") || !strcmp(x,"bcdbdbacabaaaa") || !strcmp(x,"bcdbdbacabaaab") || !strcmp(x,"bcdbdbacabaaac") || !strcmp(x,"bcdbdbacabaaad") || 0)
54 static GHashTable *dedupe_ways_hash;
56 static int attr_debug_level=1;
57 static int nodeid,wayid;
58 static int report,phase;
59 static int ignore_unkown = 0, coverage=0;
61 static char *attrmap={
63 "n amenity=hospital poi_hospital\n"
64 "n amenity=atm poi_bank\n"
65 "n amenity=bank poi_bank\n"
66 "n amenity=pub poi_bar\n"
67 "n amenity=cafe poi_cafe\n"
68 "n amenity=bus_station poi_bus_station\n"
69 "n amenity=parking poi_car_parking\n"
70 "n amenity=cinema poi_cinema\n"
71 "n amenity=fire_station poi_firebrigade\n"
72 "n amenity=fuel poi_fuel\n"
73 "n amenity=courthouse poi_justice\n"
74 "n amenity=library poi_library\n"
75 "n amenity=pharmacy poi_pharmacy\n"
76 "n amenity=place_of_worship,religion=christian poi_church\n"
77 "n amenity=police poi_police\n"
78 "n amenity=post_office poi_post\n"
79 "n amenity=post_box poi_post\n"
80 "n amenity=public_building poi_public_office\n"
81 "n amenity=restaurant poi_restaurant\n"
82 "n amenity=fast_food poi_fastfood\n"
83 "n amenity=toilets poi_restroom\n"
84 "n amenity=school poi_school\n"
85 "n amenity=university poi_school\n"
86 "n amenity=college poi_school\n"
87 "n amenity=telephone poi_telephone\n"
88 "n amenity=theatre poi_theater\n"
89 "n amenity=townhall poi_townhall\n"
90 "n highway=bus_stop poi_bus_stop\n"
91 "n highway=mini_roundabout mini_roundabout\n"
92 "n highway=motorway_junction highway_exit\n"
93 "n highway=traffic_signals traffic_signals\n"
94 "n highway=turning_circle turning_circle\n"
95 "n leisure=slipway poi_boat_ramp\n"
96 "n leisure=fishing poi_fish\n"
97 "n sport=golf poi_golf\n"
98 "n leisure=golf_course poi_golf\n"
99 "n leisure=marina poi_marine\n"
100 "n leisure=sports_centre poi_sport\n"
101 "n leisure=stadium poi_stadium\n"
102 "n shop=supermarket poi_shopping\n"
103 "n shop=convenience poi_shop_grocery\n"
104 "n tourism=attraction poi_attraction\n"
105 "n tourism=camp_site poi_camp_rv\n"
106 "n tourism=caravan_site poi_camp_rv\n"
107 "n tourism=hotel poi_hotel\n"
108 "n tourism=motel poi_hotel\n"
109 "n tourism=guest_house poi_hotel\n"
110 "n tourism=hostel poi_hotel\n"
111 "n tourism=information poi_information\n"
112 "n tourism=museum poi_museum_history\n"
113 "n tourism=picnic_site poi_picnic\n"
114 "n tourism=theme_park poi_resort\n"
115 "n tourism=zoo poi_zoo\n"
116 "n amenity=grave_yard poi_cemetery\n"
117 "n landuse=cemetery poi_cemetery\n"
118 "n military=airfield poi_military\n"
119 "n military=bunker poi_military\n"
120 "n military=barracks poi_military\n"
121 "n military=range poi_military\n"
122 "n military=danger_area poi_danger_area\n"
123 "n sport=swimming poi_swimming\n"
124 "n sport=skiing poi_skiing\n"
125 "n aeroway=aerodrome poi_airport\n"
126 "n aeroway=airport poi_airport\n"
127 "n aeroway=terminal poi_airport\n"
128 "n aeroway=helipad poi_heliport\n"
129 "n man_made=tower poi_tower\n"
130 "n natural=bay poi_bay\n"
131 "n natural=peak poi_peak\n"
132 "n place=suburb district_label\n"
133 "n place=city town_label_2e5\n"
134 "n place=town town_label_2e4\n"
135 "n place=village town_label_2e3\n"
136 "n place=hamlet town_label_2e2\n"
137 "n place=locality town_label_2e0\n"
138 "n railway=halt poi_rail_halt\n"
139 "n railway=level_crossing poi_level_crossing\n"
140 "n railway=station poi_rail_station\n"
141 "n railway=tram_stop poi_rail_tram_stop\n"
142 "n amenity=park_bench poi_bench\n"
143 "n amenity=bench poi_bench\n"
144 "n amenity=biergarten poi_biergarten\n"
145 "n historic=boundary_stone poi_boundary_stone\n"
146 "n historic=castle poi_castle\n"
147 "n historic=ruins poi_ruins\n"
148 "n Annehmlichkeit=Hochsitz poi_hunting_stand\n"
149 "n amenity=hunting_stand poi_hunting_stand\n"
150 "n historic=memorial poi_memorial\n"
151 "n historic=monument poi_monument\n"
152 "n amenity=shelter poi_shelter\n"
153 "n amenity=fountain poi_fountain\n"
154 "n amenity=drinking_water poi_potable_water\n"
155 "n amenity=toilets poi_toilets\n"
156 "n tourism=viewpoint poi_viewpoint\n"
157 "w *=* street_unkn\n"
158 "w contour_ext=elevation_major height_line_1\n"
159 "w contour_ext=elevation_medium height_line_2\n"
160 "w contour_ext=elevation_minor height_line_3\n"
161 "w amenity=place_of_worship poly_building\n"
162 "w building=* poly_building\n"
163 "w aeroway=aerodrome poly_airport\n"
164 "w aeroway=apron poly_apron\n"
165 "w aeroway=runway aeroway_runway\n"
166 "w aeroway=taxiway aeroway_taxiway\n"
167 "w aeroway=terminal poly_terminal\n"
168 "w highway=bridleway bridleway\n"
169 "w highway=path,horse=designated bridleway\n"
170 "w highway=cycleway cycleway\n"
171 "w highway=cyclepath cycleway\n"
172 "w highway=path,bicycle=designated cycleway\n"
173 "w highway=footway footway\n"
174 "w piste:type=nordic piste_nordic\n"
175 "w highway=footway,piste:type=nordic footway_and_piste_nordic\n"
176 "w route=ski piste_nordic\n"
177 "w piste:type=downhill,piste:difficulty=novice piste_downhill_novice\n"
178 "w piste:type=downhill,piste:difficulty=easy piste_downhill_easy\n"
179 "w piste:type=downhill,piste:difficulty=intermediate piste_downhill_intermediate\n"
180 "w piste:type=downhill,piste:difficulty=advanced piste_downhill_advanced\n"
181 "w piste:type=downhill,piste:difficulty=expert piste_downhill_expert\n"
182 "w piste:type=downhill,piste:difficulty=freeride piste_downhill_freeride\n"
183 "w highway=path,foot=designated footway\n"
184 "w highway=steps steps\n"
185 "w highway=path path\n"
186 "w highway=path,sac_scale=hiking hiking\n"
187 "w highway=path,sac_scale=mountain_hiking hiking_mountain\n"
188 "w highway=path,sac_scale=demanding_mountain_hiking hiking_mountain_demanding\n"
189 "w highway=path,sac_scale=alpine_hiking hiking_alpine\n"
190 "w highway=path,sac_scale=demanding_alpine_hiking hiking_alpine_demanding\n"
191 "w highway=path,sac_scale=difficult_alpine_hiking hiking_alpine_difficult\n"
192 "w highway=unsurfaced track_gravelled\n"
193 "w highway=track track_gravelled\n"
194 "w highway=track,tracktype=grade1 track_paved\n"
195 "w highway=track,surface=paved track_paved\n"
196 "w highway=track,tracktype=grade2 track_gravelled\n"
197 "w highway=track,surface=gravel track_gravelled\n"
198 "w highway=track,tracktype=grade3 track_unpaved\n"
199 "w highway=track,surface=unpaved track_unpaved\n"
200 "w highway=track,tracktype=grade4 track_ground\n"
201 "w highway=track,surface=ground track_ground\n"
202 "w highway=track,tracktype=grade5 track_grass\n"
203 "w highway=track,surface=grass track_grass\n"
204 "w highway=parking_lane street_parking_lane\n"
205 "w highway=service,service=parking_aisle street_parking_lane\n"
206 "w highway=service street_service\n"
207 "w highway=service,area=1 poly_service\n"
208 "w highway=construction street_construction\n"
209 "w highway=pedestrian street_pedestrian\n"
210 "w highway=pedestrian,area=1 poly_pedestrian\n"
211 "w highway=plaza poly_plaza\n"
212 "w landuse=plaza poly_plaza\n"
213 "w highway=residential street_1_city\n"
214 "w highway=residential,area=1 poly_street_1\n"
215 "w highway=living_street living_street\n"
216 "w highway=unclassified street_1_city\n"
217 "w highway=unclassified,area=1 poly_street_1\n"
218 "w highway=road street_1_city\n"
219 "w highway=minor street_1_land\n"
220 "w highway=tertiary street_2_city\n"
221 "w highway=tertiary,area=1 poly_street_2\n"
222 "w highway=tertiary_link ramp\n"
223 "w highway=secondary street_3_city\n"
224 "w highway=secondary,area=1 poly_street_3\n"
225 "w highway=secondary_link ramp\n"
226 "w highway=primary street_4_city\n"
227 "w highway=primary_link ramp\n"
228 "w highway=trunk street_4_city\n"
229 "w highway=trunk_link ramp\n"
230 "w highway=motorway highway_city\n"
231 "w highway=motorway_link ramp\n"
232 "w historic=town gate poly_building\n"
233 "w cycleway=track cycleway\n"
234 "w amenity=parking poly_car_parking\n"
235 "w landuse=allotments poly_allotments\n"
236 "w landuse=cemetery poly_cemetery\n"
237 "w amenity=grave_yard poly_cemetery\n"
238 "w landuse=forest poly_wood\n"
239 "w landuse=industrial poly_industry\n"
240 "w landuse=residential poly_town\n"
241 "w landuse=residential,area=1 poly_town\n"
242 "w landuse=farmyard poly_town\n"
243 "w amenity=college poly_college\n"
244 "w amenity=university poly_university\n"
245 "w tourism=camp_site poly_camp_site\n"
246 "w tourism=caravan_site poly_caravan_site\n"
247 "w tourism=picnic_site poly_picnic_site\n"
248 "w tourism=theme_park poly_theme_park\n"
249 "w tourism=attraction poly_attraction\n"
250 "w tourism=zoo poly_zoo\n"
251 "w tourism=artwork poly_artwork\n"
252 "w historic=archaeological_site poly_archaeological_site\n"
253 "w historic=ruins poly_ruins\n"
254 "w historic=battlefield poly_battlefield\n"
255 "w landuse=quarry poly_quarry\n"
256 "w landuse=landfill poly_landfill\n"
257 "w landuse=retail poly_retail\n"
258 "w landuse=commercial poly_commercial\n"
259 "w landuse=brownfield poly_brownfield\n"
260 "w landuse=greenfield poly_greenfield\n"
261 "w landuse=construction poly_construction\n"
262 "w landuse=railway poly_railway\n"
263 "w natural=glacier poly_glacier\n"
264 "w natural=scree poly_scree\n"
265 "w natural=scrub poly_scrub\n"
266 "w natural=fell poly_fell\n"
267 "w natural=heath poly_heath\n"
268 "w natural=marsh poly_marsh\n"
269 "w natural=mud poly_mud\n"
270 "w natural=beach poly_beach\n"
271 "w natural=land poly_land\n"
272 "w landuse=basin poly_basin\n"
273 "w landuse=reservoir poly_reservoir\n"
274 "w landuse=farm poly_farm\n"
275 "w landuse=farmland poly_farm\n"
276 "w landuse=vineyard poly_farm\n"
277 "w leisure=park poly_park\n"
278 "w landuse=village_green poly_village_green\n"
279 "w landuse=recreation_ground poly_recreation_ground\n"
280 "w natural=wood poly_wood\n"
281 "w natural=water poly_water\n"
282 "w natural=coastline water_line\n"
283 "w place=suburb poly_town\n"
284 "w place=town poly_town\n"
285 "w landuse=military poly_military\n"
286 "w military=airfield poly_airfield\n"
287 "w military=barracks poly_barracks\n"
288 "w military=danger_area poly_danger_area\n"
289 "w military=range poly_range\n"
290 "w military=naval_base poly_naval_base\n"
291 "w power=line powerline\n"
292 "w railway=rail rail\n"
293 "w railway=narrow_gauge rail_narrow_gauge\n"
294 "w railway=light_rail rail_light\n"
295 "w railway=subway rail_subway\n"
296 "w railway=tram rail_tram\n"
297 "w railway=monorail rail_mono\n"
298 "w railway=preserved rail_preserved\n"
299 "w railway=disused rail_disused\n"
300 "w railway=abandoned rail_abandoned\n"
301 "w aerialway=cable_car lift_cable_car\n"
302 "w aerialway=chair_lift lift_chair\n"
303 "w aerialway=drag_lift lift_drag\n"
304 "w leisure=golf_course poly_golf_course\n"
305 "w sport=* poly_sport\n"
306 "w leisure=sports_centre poly_sport\n"
307 "w leisure=stadium poly_sports_stadium\n"
308 "w leisure=track poly_sports_track\n"
309 "w leisure=pitch poly_sports_pitch\n"
310 "w leisure=water_park poly_water_park\n"
311 "w leisure=marina poly_marina\n"
312 "w leisure=fishing poly_fishing\n"
313 "w leisure=garden poly_garden\n"
314 "w leisure=common poly_common\n"
315 "w leisure=playground poly_playground\n"
316 "w leisure=nature_reserve poly_nature_reserve\n"
317 "w waterway=canal water_canal\n"
318 "w waterway=river water_river\n"
319 "w waterway=stream water_stream\n"
320 "w waterway=drain water_drain\n"
321 "w waterway=riverbank poly_water\n"
322 "w boundary=administrative border_country\n"
323 "w boundary=civil border_civil\n"
324 "w boundary=political border_political\n"
325 "w boundary=national_park border_national_park\n"
326 "w route=ferry ferry\n"
327 "w highway=bus_guideway bus_guideway\n"
333 } coord_buffer[65536];
335 #define IS_REF(c) ((c).x >= (1 << 30))
336 #define REF(c) ((c).y)
337 #define SET_REF(c,ref) do { (c).x = 1 << 30; (c).y = ref ; } while(0)
343 static void bbox_extend(struct coord *c, struct rect *r);
345 #ifdef GENERATE_INDEX
347 static GHashTable *aux_tile_hash;
348 GList *aux_tile_list;
350 struct country_table {
357 } country_table[] = {
358 { 40,"Austria,�sterreich,AUT"},
360 {208,"Denmark,Danmark,DK"},
361 {246,"Finland,Suomi"},
362 {250,"France,R�publique fran�aise,FR"},
363 {276,"Germany,Deutschland,Bundesrepublik Deutschland"},
364 {380,"Italy,Italia"},
365 {528,"Nederland,The Netherlands,Niederlande,NL"},
366 {578,"Norway,Norge,Noreg,NO"},
367 {724,"Spain,Espana,Espana,Reino de Espana"},
368 {752,"Sweden,Sverige,Konungariket Sverige,SE"},
370 {826,"United Kingdom,UK"},
374 static GHashTable *country_table_hash;
377 struct attr_mapping {
379 int attr_present_idx_count;
380 int attr_present_idx[0];
383 static struct attr_mapping **attr_mapping_node;
384 static int attr_mapping_node_count;
385 static struct attr_mapping **attr_mapping_way;
386 static int attr_mapping_way_count;
388 static char *attr_present;
389 static int attr_present_count;
390 static GHashTable *attr_hash;
393 static GHashTable *strings_hash = NULL;
396 static char* string_hash_lookup( const char* key )
398 char* key_ptr = NULL;
400 if ( strings_hash == NULL ) {
401 strings_hash = g_hash_table_new(g_str_hash, g_str_equal);
404 if ( ( key_ptr = g_hash_table_lookup(strings_hash, key )) == NULL ) {
405 key_ptr = g_strdup( key );
406 g_hash_table_insert(strings_hash, key_ptr, (gpointer)key_ptr );
413 build_attrmap_line(char *line)
415 char *t=NULL,*kvl=NULL,*i=NULL,*p,*kv;
416 struct attr_mapping ***attr_mapping_curr,*attr_mapping=g_malloc0(sizeof(struct attr_mapping));
417 int idx,attr_mapping_count=0,*attr_mapping_curr_count;
434 attr_mapping_curr=&attr_mapping_way;
435 attr_mapping_curr_count=&attr_mapping_way_count;
439 attr_mapping_curr=&attr_mapping_node;
440 attr_mapping_curr_count=&attr_mapping_node_count;
442 attr_mapping->type=item_from_name(i);
443 while ((kv=strtok(kvl, ","))) {
445 if (!(idx=(int)g_hash_table_lookup(attr_hash, kv))) {
446 idx=attr_present_count++;
447 g_hash_table_insert(attr_hash, kv, (gpointer) idx);
449 attr_mapping=g_realloc(attr_mapping, sizeof(struct attr_mapping)+(attr_mapping_count+1)*sizeof(int));
450 attr_mapping->attr_present_idx[attr_mapping_count++]=idx;
451 attr_mapping->attr_present_idx_count=attr_mapping_count;
453 *attr_mapping_curr=g_realloc(*attr_mapping_curr, sizeof(**attr_mapping_curr)*(*attr_mapping_curr_count+1));
454 (*attr_mapping_curr)[(*attr_mapping_curr_count)++]=attr_mapping;
458 build_attrmap(char *map)
461 attr_hash=g_hash_table_new(g_str_hash, g_str_equal);
462 attr_present_count=1;
468 build_attrmap_line(map);
471 attr_present=g_malloc0(sizeof(*attr_present)*attr_present_count);
474 #ifdef GENERATE_INDEX
476 build_countrytable(void)
479 char *names,*str,*tok;
480 country_table_hash=g_hash_table_new(g_str_hash, g_str_equal);
481 for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
482 names=g_strdup(country_table[i].names);
484 while ((tok=strtok(str, ","))) {
486 g_hash_table_insert(country_table_hash, tok, (gpointer)&country_table[i]);
494 static int processed_nodes, processed_nodes_out, processed_ways, processed_relations, processed_tiles;
495 static int in_way, in_node, in_relation;
501 signal(SIGALRM, sig_alrm);
504 fprintf(stderr,"PROGRESS%d: Processed %d nodes (%d out) %d ways %d relations %d tiles\n", phase, processed_nodes, processed_nodes_out, processed_ways, processed_relations, processed_tiles);
518 struct attr_bin label_attr = {
521 char label_attr_buffer[BUFFER_SIZE];
523 struct attr_bin town_name_attr = {
527 struct attr_bin street_name_attr = {
531 struct attr_bin street_name_systematic_attr = {
532 0, attr_street_name_systematic
534 char street_name_systematic_attr_buffer[BUFFER_SIZE];
536 struct attr_bin debug_attr = {
539 char debug_attr_buffer[BUFFER_SIZE];
541 struct attr_bin flags_attr = {
544 int flags_attr_value;
546 char is_in_buffer[BUFFER_SIZE];
549 static void write_zipmember(FILE *out, FILE *dir_out, char *name, int filelen, char *data, int data_size, int compression_level);
552 pad_text_attr(struct attr_bin *a, char *buffer)
555 if (buffer && buffer[0]) {
565 xml_get_attribute(char *xml, char *attribute, char *buffer, int buffer_size)
567 int len=strlen(attribute);
568 char *pos,*i,s,attr[len+2];
569 strcpy(attr, attribute);
570 strcpy(attr+len, "=");
571 pos=strstr(xml, attr);
581 if (i - pos > buffer_size) {
582 fprintf(stderr,"Buffer overflow %d vs %d\n", i-pos, buffer_size);
585 strncpy(buffer, pos, i-pos);
590 static int node_is_tagged;
593 add_tag(char *k, char *v)
595 GHashTable *value_hash;
598 char buffer[BUFFER_SIZE*2+2];
599 if (! strcmp(k,"ele"))
601 if (! strcmp(k,"time"))
603 if (! strcmp(k,"created_by"))
605 if (! strncmp(k,"tiger:",6) || !strcmp(k,"AND_nodes"))
607 if (! strcmp(k,"converted_by") || ! strcmp(k,"source"))
609 if (! strncmp(k,"osmarender:",11) || !strncmp(k,"svg:",4))
611 if (! strcmp(k,"layer"))
613 if (! strcasecmp(v,"true") || ! strcasecmp(v,"yes"))
615 if (! strcmp(k,"oneway")) {
616 if (!strcmp(v,"1")) {
617 flags_attr_value=AF_ONEWAY;
620 if (! strcmp(v,"-1")) {
621 flags_attr_value=AF_ONEWAYREV;
629 if (! strcmp(k,"junction")) {
630 if (! strcmp(v,"roundabout")) {
631 flags_attr_value=AF_ONEWAY;
635 if (! strcmp(k,"maxspeed")) {
638 if (! strcmp(k,"bicycle")) {
641 if (! strcmp(k,"foot")) {
644 if (! strcmp(k,"note"))
646 if (! strcmp(k,"name")) {
647 strcpy(label_attr_buffer, v);
648 pad_text_attr(&label_attr, label_attr_buffer);
651 if (! strcmp(k,"ref")) {
653 strcpy(street_name_systematic_attr_buffer, v);
654 pad_text_attr(&street_name_systematic_attr, street_name_systematic_attr_buffer);
658 if (! strcmp(k,"is_in")) {
659 strcpy(is_in_buffer, v);
662 if (! strcmp(k,"gnis:ST_alpha")) {
663 /* assume a gnis tag means it is part of the USA:
664 http://en.wikipedia.org/wiki/Geographic_Names_Information_System
665 many US towns do not have is_in tags
667 strcpy(is_in_buffer, "USA");
670 if (! strcmp(k,"lanes")) {
673 if (attr_debug_level >= level) {
674 int bytes_left = sizeof( debug_attr_buffer ) - strlen(debug_attr_buffer) - 1;
675 if ( bytes_left > 0 )
677 snprintf(debug_attr_buffer+strlen(debug_attr_buffer), bytes_left, " %s=%s", k, v);
678 debug_attr_buffer[ sizeof( debug_attr_buffer ) - 1 ] = '\0';
687 strcpy(buffer,"*=*");
688 if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
691 sprintf(buffer,"%s=*", k);
692 if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
695 sprintf(buffer,"*=%s", v);
696 if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
699 sprintf(buffer,"%s=%s", k, v);
700 if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
716 decode_entities(char *buffer)
721 while ((pos=strchr(pos, '&'))) {
723 for (i = 0 ; i < sizeof(entities)/sizeof(struct entity); i++) {
724 len=strlen(entities[i].entity);
725 if (!strncmp(pos, entities[i].entity, len)) {
727 memmove(pos+1, pos+len, strlen(pos+len)+1);
739 char k_buffer[BUFFER_SIZE];
740 char v_buffer[BUFFER_SIZE];
741 if (!xml_get_attribute(p, "k", k_buffer, BUFFER_SIZE))
743 if (!xml_get_attribute(p, "v", v_buffer, BUFFER_SIZE))
745 decode_entities(v_buffer);
746 add_tag(k_buffer, v_buffer);
758 static struct tile_head {
766 struct tile_head *next;
782 static struct buffer node_buffer = {
787 static char** th_get_subtile( const struct tile_head* th, int idx )
789 char* subtile_ptr = NULL;
790 subtile_ptr = (char*)th + sizeof( struct tile_head ) + idx * sizeof( char *);
791 return (char**)subtile_ptr;
795 extend_buffer(struct buffer *b)
797 b->malloced+=b->malloced_step;
798 b->base=realloc(b->base, b->malloced);
799 if (b->base == NULL) {
800 fprintf(stderr,"realloc of %d bytes failed\n",b->malloced);
807 GHashTable *node_hash;
810 node_buffer_to_hash(void)
812 int i,count=node_buffer.size/sizeof(struct node_item);
813 struct node_item *ni=(struct node_item *)node_buffer.base;
814 for (i = 0 ; i < count ; i++)
815 g_hash_table_insert(node_hash, (gpointer)(ni[i].id), (gpointer)i);
818 static struct node_item *ni;
821 add_node(int id, double lat, double lon)
823 if (node_buffer.size + sizeof(struct node_item) > node_buffer.malloced)
824 extend_buffer(&node_buffer);
827 item.type=type_point_unkn;
829 town_name_attr.len=0;
831 is_in_buffer[0]='\0';
832 sprintf(debug_attr_buffer,"nodeid=%d", nodeid);
833 ni=(struct node_item *)(node_buffer.base+node_buffer.size);
839 ni->c.x=lon*6371000.0*M_PI/180;
840 ni->c.y=log(tan(M_PI_4+lat*M_PI/360))*6371000.0;
841 node_buffer.size+=sizeof(struct node_item);
843 if (ni->id > nodeid_last) {
846 fprintf(stderr,"INFO: Nodes out of sequence (new %d vs old %d), adding hash\n", ni->id, nodeid_last);
847 node_hash=g_hash_table_new(NULL, NULL);
848 node_buffer_to_hash();
851 if (!g_hash_table_lookup(node_hash, (gpointer)(ni->id)))
852 g_hash_table_insert(node_hash, (gpointer)(ni->id), (gpointer)(ni-(struct node_item *)node_buffer.base));
854 node_buffer.size-=sizeof(struct node_item);
863 char id_buffer[BUFFER_SIZE];
864 char lat_buffer[BUFFER_SIZE];
865 char lon_buffer[BUFFER_SIZE];
866 if (!xml_get_attribute(p, "id", id_buffer, BUFFER_SIZE))
868 if (!xml_get_attribute(p, "lat", lat_buffer, BUFFER_SIZE))
870 if (!xml_get_attribute(p, "lon", lon_buffer, BUFFER_SIZE))
872 add_node(atoi(id_buffer), atof(lat_buffer), atof(lon_buffer));
877 static struct node_item *
878 node_item_get(int id)
880 struct node_item *ni=(struct node_item *)(node_buffer.base);
881 int count=node_buffer.size/sizeof(struct node_item);
882 int interval=count/4;
886 i=(int)(g_hash_table_lookup(node_hash, (gpointer)id));
889 while (ni[p].id != id) {
891 fprintf(stderr,"p=%d count=%d interval=%d id=%d ni[p].id=%d\n", p, count, interval, id, ni[p].id);
926 struct node_item *ni=node_item_get(id);
928 fprintf(stderr,"WARNING: node id %d not found\n", id);
940 item.type=type_street_unkn;
942 street_name_attr.len=0;
943 street_name_systematic_attr.len=0;
946 sprintf(debug_attr_buffer,"wayid=%d", wayid);
952 char id_buffer[BUFFER_SIZE];
953 if (!xml_get_attribute(p, "id", id_buffer, BUFFER_SIZE))
955 add_way(atoi(id_buffer));
960 parse_relation(char *p)
962 debug_attr_buffer[0]='\0';
967 item_buffer_set_type(char *buffer, enum item_type type)
969 struct item_bin *ib=(struct item_bin *) buffer;
976 item_buffer_add_coord(char *buffer, struct coord *c, int count)
978 struct item_bin *ib=(struct item_bin *) buffer;
979 struct coord *c2=(struct coord *)(ib+1);
981 memcpy(c2, c, count*sizeof(struct coord));
987 item_buffer_add_attr(char *buffer, struct attr *attr)
989 struct item_bin *ib=(struct item_bin *) buffer;
990 struct attr_bin *ab=(struct attr_bin *)((int *)ib+ib->len+1);
991 if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
993 strcpy((char *)(ab+1),attr->u.str);
994 pad_text_attr(ab, (char *)(ab+1));
1000 item_buffer_write(char *buffer, FILE *out)
1002 struct item_bin *ib=(struct item_bin *) buffer;
1003 fwrite(buffer, (ib->len+1)*4, 1, out);
1007 write_attr(FILE *out, struct attr_bin *attr, void *buffer)
1010 fwrite(attr, sizeof(*attr), 1, out);
1011 fwrite(buffer, (attr->len-1)*4, 1, out);
1016 attr_longest_match(struct attr_mapping **mapping, int mapping_count, enum item_type *types, int types_count)
1018 int i,j,longest=0,ret=0,sum,val;
1019 struct attr_mapping *curr;
1020 for (i = 0 ; i < mapping_count ; i++) {
1023 for (j = 0 ; j < curr->attr_present_idx_count ; j++) {
1024 val=attr_present[curr->attr_present_idx[j]];
1032 if (sum > longest) {
1036 if (sum > 0 && sum == longest && ret < types_count)
1037 types[ret++]=curr->type;
1039 memset(attr_present, 0, sizeof(*attr_present)*attr_present_count);
1047 enum item_type types[5];
1051 if (dedupe_ways_hash) {
1052 if (g_hash_table_lookup(dedupe_ways_hash, (gpointer)wayid))
1054 g_hash_table_insert(dedupe_ways_hash, (gpointer)wayid, (gpointer)1);
1056 count=attr_longest_match(attr_mapping_way, attr_mapping_way_count, types, sizeof(types)/sizeof(enum item_type));
1057 pad_text_attr(&debug_attr, debug_attr_buffer);
1059 alen+=label_attr.len+1;
1060 if (street_name_systematic_attr.len)
1061 alen+=street_name_systematic_attr.len+1;
1063 alen+=debug_attr.len+1;
1065 alen+=flags_attr.len+1;
1069 item.type=type_street_unkn;
1070 if (coverage && item_is_street(item))
1071 item.type=type_coverage;
1072 item.clen=coord_count*2;
1073 item.len=item.clen+2+alen;
1074 fwrite(&item, sizeof(item), 1, out);
1075 fwrite(coord_buffer, coord_count*sizeof(struct coord), 1, out);
1076 if (item_is_street(item)) {
1077 street_name_attr.len=label_attr.len;
1078 write_attr(out, &street_name_attr, label_attr_buffer);
1080 write_attr(out, &label_attr, label_attr_buffer);
1081 write_attr(out, &street_name_systematic_attr, street_name_systematic_attr_buffer);
1082 write_attr(out, &debug_attr, debug_attr_buffer);
1083 write_attr(out, &flags_attr, &flags_attr_value);
1089 int alen=0,conflict=0,count;
1090 enum item_type types[5];
1091 struct country_table *result=NULL, *lookup;
1092 if (!out || ! node_is_tagged || ! nodeid)
1094 count=attr_longest_match(attr_mapping_node, attr_mapping_node_count, types, sizeof(types)/sizeof(enum item_type));
1095 pad_text_attr(&debug_attr, debug_attr_buffer);
1097 alen+=label_attr.len+1;
1099 alen+=debug_attr.len+1;
1103 item.type=type_point_unkn;
1105 item.len=item.clen+2+alen;
1106 fwrite(&item, sizeof(item), 1, out);
1107 fwrite(&ni->c, 1*sizeof(struct coord), 1, out);
1108 if (item_is_town(item)) {
1109 town_name_attr.len=label_attr.len;
1110 write_attr(out, &town_name_attr, label_attr_buffer);
1112 write_attr(out, &label_attr, label_attr_buffer);
1113 write_attr(out, &debug_attr, debug_attr_buffer);
1114 #ifdef GENERATE_INDEX
1115 if (item_is_town(item) && town_name_attr.len) {
1116 char *tok,*buf=is_in_buffer;
1117 while ((tok=strtok(buf, ","))) {
1120 lookup=g_hash_table_lookup(country_table_hash,tok);
1122 if (result && result->countryid != lookup->countryid) {
1123 fprintf(stderr,"conflict for %s %s country %d vs %d\n", label_attr_buffer, debug_attr_buffer, lookup->countryid, result->countryid);
1130 if (result && !conflict) {
1131 if (!result->file) {
1132 char *name=g_strdup_printf("country_%d.bin.unsorted", result->countryid);
1133 result->file=fopen(name,"w");
1138 item.len=item.clen+2+label_attr.len+1;
1139 fwrite(&item, sizeof(item), 1, result->file);
1140 fwrite(&ni->c, 1*sizeof(struct coord), 1, result->file);
1141 write_attr(result->file, &town_name_attr, label_attr_buffer);
1143 result->size+=(item.clen+3+label_attr.len+1)*4;
1149 processed_nodes_out++;
1153 sort_countries_compare(const void *p1, const void *p2)
1155 struct item_bin *ib1=*((struct item_bin **)p1),*ib2=*((struct item_bin **)p2);
1156 struct attr_bin *attr1,*attr2;
1158 assert(ib1->clen==2);
1159 assert(ib2->clen==2);
1160 attr1=(struct attr_bin *)((int *)(ib1+1)+ib1->clen);
1161 attr2=(struct attr_bin *)((int *)(ib2+1)+ib1->clen);
1162 assert(attr1->type == attr_town_name);
1163 assert(attr2->type == attr_town_name);
1164 s1=(char *)(attr1+1);
1165 s2=(char *)(attr2+1);
1166 return strcmp(s1, s2);
1168 fprintf(stderr,"sort_countries_compare p1=%p p2=%p %s %s\n",p1,p2,s1,s2);
1173 #ifdef GENERATE_INDEX
1175 sort_countries(void)
1178 struct country_table *co;
1180 struct item_bin *ib;
1182 char *p,*buffer,**idx,*name;
1183 for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
1184 co=&country_table[i];
1190 buffer=malloc(co->size);
1191 assert(buffer != NULL);
1192 idx=malloc(co->count*sizeof(void *));
1193 assert(idx != NULL);
1194 name=g_strdup_printf("country_%d.bin.unsorted", co->countryid);
1197 fread(buffer, co->size, 1, f);
1202 for (j = 0 ; j < co->count ; j++) {
1204 p+=(*((int *)p)+1)*4;
1206 qsort(idx, co->count, sizeof(void *), sort_countries_compare);
1207 name=g_strdup_printf("country_%d.bin", co->countryid);
1209 for (j = 0 ; j < co->count ; j++) {
1210 ib=(struct item_bin *)(idx[j]);
1211 c=(struct coord *)(ib+1);
1212 fwrite(ib, (ib->len+1)*4, 1, f);
1214 bbox_extend(c, &co->r);
1226 add_nd(char *p, int ref)
1229 struct node_item *ni;
1230 ni=node_item_get(ref);
1233 coord_buffer[coord_count++]=ni->c;
1235 SET_REF(coord_buffer[coord_count], ref);
1241 if (len > 0 && p[len-1]=='\n')
1243 fprintf(stderr,"WARNING: way %d: node %d not found (%s)\n",wayid,ref,p);
1245 if (coord_count > 65536) {
1246 fprintf(stderr,"ERROR: Overflow\n");
1254 char ref_buffer[BUFFER_SIZE];
1255 if (!xml_get_attribute(p, "ref", ref_buffer, BUFFER_SIZE))
1257 add_nd(p, atoi(ref_buffer));
1263 save_buffer(char *filename, struct buffer *b)
1266 f=fopen(filename,"wb+");
1267 fwrite(b->base, b->size, 1, f);
1272 load_buffer(char *filename, struct buffer *b)
1278 f=fopen(filename,"rb");
1279 fseek(f, 0, SEEK_END);
1280 b->size=b->malloced=ftell(f);
1281 fprintf(stderr,"reading %d bytes from %s\n", b->size, filename);
1282 fseek(f, 0, SEEK_SET);
1283 b->base=malloc(b->size);
1284 assert(b->base != NULL);
1285 fread(b->base, b->size, 1, f);
1290 phase1(FILE *in, FILE *out_ways, FILE *out_nodes)
1296 while (fgets(buffer, size, in)) {
1297 p=strchr(buffer,'<');
1299 fprintf(stderr,"WARNING: wrong line %s\n", buffer);
1302 if (!strncmp(p, "<?xml ",6)) {
1303 } else if (!strncmp(p, "<osm ",5)) {
1304 } else if (!strncmp(p, "<bound ",7)) {
1305 } else if (!strncmp(p, "<node ",6)) {
1307 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1310 } else if (!strncmp(p, "<tag ",5)) {
1312 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1313 } else if (!strncmp(p, "<way ",5)) {
1316 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1318 } else if (!strncmp(p, "<nd ",4)) {
1320 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1321 } else if (!strncmp(p, "<relation ",10)) {
1323 if (!parse_relation(p))
1324 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1325 processed_relations++;
1326 } else if (!strncmp(p, "<member ",8)) {
1327 } else if (!strncmp(p, "</node>",7)) {
1329 end_node(out_nodes);
1330 } else if (!strncmp(p, "</way>",6)) {
1333 } else if (!strncmp(p, "</relation>",11)) {
1335 } else if (!strncmp(p, "</osm>",6)) {
1337 fprintf(stderr,"WARNING: unknown tag in %s\n", buffer);
1345 #ifdef HAVE_POSTGRESQL
1347 phase1_db(char *dbstr, FILE *out_ways, FILE *out_nodes)
1350 PGresult *res,*node,*way,*tag;
1351 int count,tagged,i,j,k;
1352 long min, max, id, tag_id, node_id;
1356 conn=PQconnectdb(dbstr);
1358 fprintf(stderr,"Failed to connect to database with '%s'\n",dbstr);
1361 res=PQexec(conn, "begin");
1363 fprintf(stderr, "Cannot begin transaction: %s\n", PQerrorMessage(conn));
1367 res=PQexec(conn, "set transaction isolation level serializable");
1369 fprintf(stderr, "Cannot set isolation level: %s\n", PQerrorMessage(conn));
1373 res=PQexec(conn, "declare node cursor for select id,x(coordinate),y(coordinate) from node order by id");
1375 fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1379 res=PQexec(conn, "declare way cursor for select id from way order by id");
1381 fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1385 res=PQexec(conn, "declare relation cursor for select id from relation order by id");
1387 fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1392 node=PQexec(conn, "fetch 100000 from node");
1394 fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1398 count=PQntuples(node);
1401 min=atol(PQgetvalue(node, 0, 0));
1402 max=atol(PQgetvalue(node, count-1, 0));
1403 sprintf(query,"select node_id,name,value from node_tag where node_id >= %ld and node_id <= %ld order by node_id", min, max);
1404 tag=PQexec(conn, query);
1406 fprintf(stderr, "Cannot query node_tag: %s\n", PQerrorMessage(conn));
1410 for (i = 0 ; i < count ; i++) {
1411 id=atol(PQgetvalue(node, i, 0));
1412 add_node(id, atof(PQgetvalue(node, i, 1)), atof(PQgetvalue(node, i, 2)));
1416 while (j < PQntuples(tag)) {
1417 tag_id=atol(PQgetvalue(tag, j, 0));
1419 add_tag(PQgetvalue(tag, j, 1), PQgetvalue(tag, j, 2));
1429 end_node(out_nodes);
1436 way=PQexec(conn, "fetch 100000 from way");
1438 fprintf(stderr, "Cannot setup cursor for ways: %s\n", PQerrorMessage(conn));
1442 count=PQntuples(way);
1445 min=atol(PQgetvalue(way, 0, 0));
1446 max=atol(PQgetvalue(way, count-1, 0));
1447 sprintf(query,"select way_id,node_id from way_node where way_id >= %ld and way_id <= %ld order by way_id,sequence_id", min, max);
1448 node=PQexec(conn, query);
1450 fprintf(stderr, "Cannot query way_node: %s\n", PQerrorMessage(conn));
1453 sprintf(query,"select way_id,name,value from way_tag where way_id >= %ld and way_id <= %ld order by way_id", min, max);
1454 tag=PQexec(conn, query);
1456 fprintf(stderr, "Cannot query way_tag: %s\n", PQerrorMessage(conn));
1461 for (i = 0 ; i < count ; i++) {
1462 id=atol(PQgetvalue(way, i, 0));
1467 while (k < PQntuples(node)) {
1468 node_id=atol(PQgetvalue(node, k, 0));
1469 if (node_id == id) {
1470 add_nd("",atol(PQgetvalue(node, k, 1)));
1479 while (j < PQntuples(tag)) {
1480 tag_id=atol(PQgetvalue(tag, j, 0));
1482 add_tag(PQgetvalue(tag, j, 1), PQgetvalue(tag, j, 2));
1500 res=PQexec(conn, "commit");
1502 fprintf(stderr, "Cannot commit transaction: %s\n", PQerrorMessage(conn));
1512 static char buffer[200000];
1515 phase1_map(struct map *map, FILE *out_ways, FILE *out_nodes)
1517 struct map_rect *mr=map_rect_new(map, NULL);
1519 int count,max=16384;
1520 struct coord ca[max];
1525 while ((item = map_rect_get_item(mr))) {
1526 count=item_coord_get(item, ca, item->type < type_line ? 1: max);
1527 item_buffer_set_type(buffer, item->type);
1528 item_buffer_add_coord(buffer, ca, count);
1529 while (item_attr_get(item, attr_any, &attr)) {
1530 item_buffer_add_attr(buffer, &attr);
1532 if (item->type >= type_line)
1533 item_buffer_write(buffer, out_ways);
1535 item_buffer_write(buffer, out_nodes);
1537 map_rect_destroy(mr);
1543 static struct item_bin *
1546 struct item_bin *ib=(struct item_bin *) buffer;
1548 r=fread(ib, sizeof(*ib), 1, in);
1552 assert((ib->len+1)*4 < sizeof(buffer));
1553 s=(ib->len+1)*4-sizeof(*ib);
1554 r=fread(ib+1, s, 1, in);
1562 bbox_extend(struct coord *c, struct rect *r)
1575 bbox(struct coord *c, int count, struct rect *r)
1588 contains_bbox(int xl, int yl, int xh, int yh, struct rect *r)
1590 if (r->h.x < xl || r->h.x > xh) {
1593 if (r->l.x > xh || r->l.x < xl) {
1596 if (r->h.y < yl || r->h.y > yh) {
1599 if (r->l.y > yh || r->l.y < yl) {
1605 struct rect world_bbox = {
1606 { -20000000, -20000000},
1607 { 20000000, 20000000},
1611 tile(struct rect *r, char *ret, int max)
1620 for (i = 0 ; i < max ; i++) {
1627 if ( contains_bbox(x0,y0,x2,y2,r)) {
1631 } else if (contains_bbox(x2,y0,x4,y2,r)) {
1635 } else if (contains_bbox(x0,y2,x2,y4,r)) {
1639 } else if (contains_bbox(x2,y2,x4,y4,r)) {
1649 tile_bbox(char *tile, struct rect *r)
1654 c.x=(r->l.x+r->h.x)/2;
1655 c.y=(r->l.y+r->h.y)/2;
1678 GHashTable *tile_hash;
1679 GHashTable *tile_hash2;
1682 tile_extend(char *tile, struct item_bin *ib, GList **tiles_list)
1684 struct tile_head *th=NULL;
1685 if (debug_tile(tile))
1686 fprintf(stderr,"Tile:Writing %d bytes to '%s' (%p,%p)\n", (ib->len+1)*4, tile, g_hash_table_lookup(tile_hash, tile), tile_hash2 ? g_hash_table_lookup(tile_hash2, tile) : NULL);
1688 th=g_hash_table_lookup(tile_hash2, tile);
1690 th=g_hash_table_lookup(tile_hash, tile);
1692 th=malloc(sizeof(struct tile_head)+ sizeof( char* ) );
1694 // strcpy(th->subtiles, tile);
1697 th->total_size_used=0;
1700 th->name=string_hash_lookup(tile);
1701 *th_get_subtile( th, 0 ) = th->name;
1704 g_hash_table_insert(tile_hash2, string_hash_lookup( th->name ), th);
1706 *tiles_list=g_list_append(*tiles_list, string_hash_lookup( th->name ) );
1708 if (debug_tile(tile))
1709 fprintf(stderr,"new '%s'\n", tile);
1711 th->total_size+=ib->len*4+4;
1712 if (debug_tile(tile))
1713 fprintf(stderr,"New total size of %s(%p):%d\n", th->name, th, th->total_size);
1714 g_hash_table_insert(tile_hash, string_hash_lookup( th->name ), th);
1718 tile_data_size(char *tile)
1720 struct tile_head *th;
1721 th=g_hash_table_lookup(tile_hash, tile);
1724 return th->total_size;
1728 merge_tile(char *base, char *sub)
1730 struct tile_head *thb, *ths;
1731 thb=g_hash_table_lookup(tile_hash, base);
1732 ths=g_hash_table_lookup(tile_hash, sub);
1735 if (debug_tile(base) || debug_tile(sub))
1736 fprintf(stderr,"merging '%s'(%p) (%d) with '%s'(%p) (%d)\n", base, thb, thb ? thb->total_size : 0, sub, ths, ths->total_size);
1739 g_hash_table_remove(tile_hash, sub);
1740 thb->name=string_hash_lookup(base);
1741 g_hash_table_insert(tile_hash, string_hash_lookup( thb->name ), thb);
1744 thb=realloc(thb, sizeof(struct tile_head)+( ths->num_subtiles+thb->num_subtiles ) * sizeof( char*) );
1745 assert(thb != NULL);
1746 memcpy( th_get_subtile( thb, thb->num_subtiles ), th_get_subtile( ths, 0 ), ths->num_subtiles * sizeof( char*) );
1747 thb->num_subtiles+=ths->num_subtiles;
1748 thb->total_size+=ths->total_size;
1749 g_hash_table_insert(tile_hash, string_hash_lookup( thb->name ), thb);
1750 g_hash_table_remove(tile_hash, sub);
1758 get_tiles_list_func(char *key, struct tile_head *th, GList **list)
1760 *list=g_list_prepend(*list, key);
1764 get_tiles_list(void)
1767 g_hash_table_foreach(tile_hash, (GHFunc)get_tiles_list_func, &ret);
1773 write_tile(char *key, struct tile_head *th, gpointer dummy)
1777 fprintf(stderr,"DEBUG: Writing %s\n", key);
1778 strcpy(buffer,"tiles/");
1781 strcat(buffer,".bin");
1783 f=fopen(buffer, "wb+");
1785 fwrite(th->data, th->size, 1, f);
1793 write_item(char *tile, struct item_bin *ib)
1795 struct tile_head *th;
1798 th=g_hash_table_lookup(tile_hash2, tile);
1800 th=g_hash_table_lookup(tile_hash, tile);
1802 if (th->process != 0 && th->process != 1) {
1803 fprintf(stderr,"error with tile '%s' of length %d\n", tile, strlen(tile));
1808 if (debug_tile(tile))
1809 fprintf(stderr,"Data:Writing %d bytes to '%s' (%p,%p)\n", (ib->len+1)*4, tile, g_hash_table_lookup(tile_hash, tile), tile_hash2 ? g_hash_table_lookup(tile_hash2, tile) : NULL);
1811 if (th->total_size_used+size > th->total_size) {
1812 fprintf(stderr,"Overflow in tile %s (used %d max %d item %d)\n", tile, th->total_size_used, th->total_size, size);
1816 memcpy(th->zip_data+th->total_size_used, ib, size);
1817 th->total_size_used+=size;
1819 fprintf(stderr,"no tile hash found for %s\n", tile);
1825 write_item_part(FILE *out, struct item_bin *orig, int first, int last)
1827 struct item_bin new;
1828 struct coord *c=(struct coord *)(orig+1);
1829 char *attr=(char *)(c+orig->clen/2);
1830 int attr_len=orig->len-orig->clen-2;
1832 new.type=orig->type;
1833 new.clen=(last-first+1)*2;
1834 new.len=new.clen+attr_len+2;
1836 fprintf(stderr,"first %d last %d type 0x%x len %d clen %d attr_len %d\n", first, last, new.type, new.len, new.clen, attr_len);
1838 fwrite(&new, sizeof(new), 1, out);
1839 fwrite(c+first, new.clen*4, 1, out);
1840 fwrite(attr, attr_len*4, 1, out);
1844 phase2(FILE *in, FILE *out)
1847 int i,ccount,last,ndref;
1848 struct item_bin *ib;
1849 struct node_item *ni;
1851 processed_nodes=processed_nodes_out=processed_ways=processed_relations=processed_tiles=0;
1853 while ((ib=read_item(in))) {
1855 fprintf(stderr,"type 0x%x len %d clen %d\n", ib->type, ib->len, ib->clen);
1858 c=(struct coord *)(ib+1);
1860 for (i = 0 ; i < ccount ; i++) {
1863 ni=node_item_get(ndref);
1865 fprintf(stderr,"ni=%p\n", ni);
1868 if (ni->ref_way > 1 && i != 0 && i != ccount-1 && item_is_street(*ib)) {
1869 write_item_part(out, ib, last, i);
1874 write_item_part(out, ib, last, ccount-1);
1882 phase34_process_file(int phase, FILE *in)
1884 struct item_bin *ib;
1889 while ((ib=read_item(in))) {
1890 if (ib->type < 0x80000000)
1894 bbox((struct coord *)(ib+1), ib->clen/2, &r);
1897 if (ib->type == type_street_n_lanes || ib->type == type_highway_city || ib->type == type_highway_land || ib->type == type_ramp)
1899 if (ib->type == type_street_3_city || ib->type == type_street_4_city || ib->type == type_street_3_land || ib->type == type_street_4_land)
1902 tile(&r, buffer, max);
1904 fprintf(stderr,"%s\n", buffer);
1907 tile_extend(buffer, ib, NULL);
1909 write_item(buffer, ib);
1914 struct item_bin item;
1916 struct attr_bin attr_order;
1919 struct attr_bin attr_zipfile_ref;
1924 index_submap_add(int phase, struct tile_head *th, GList **tiles_list)
1926 struct index_item ii;
1927 int len=strlen(th->name);
1928 char index_tile[len+1];
1930 ii.min=(len > 4) ? len-4 : 0;
1932 strcpy(index_tile, th->name);
1938 tile_bbox(th->name, &ii.r);
1940 ii.item.len=sizeof(ii)/4-1;
1941 ii.item.type=type_submap;
1944 ii.attr_order.len=2;
1945 ii.attr_order.type=attr_order;
1947 ii.attr_zipfile_ref.len=2;
1948 ii.attr_zipfile_ref.type=attr_zipfile_ref;
1949 ii.zipfile_ref=th->zipnum;
1952 tile_extend(index_tile, (struct item_bin *)&ii, tiles_list);
1954 write_item(index_tile, (struct item_bin *)&ii);
1956 unsigned int *c=(unsigned int *)ⅈ
1958 for (i = 0 ; i < sizeof(ii)/4 ; i++) {
1959 fprintf(stderr,"%08x ", c[i]);
1961 fprintf(stderr,"\n");
1966 add_tile_hash(struct tile_head *th)
1968 int idx,len,maxnamelen=0;
1972 g_hash_table_insert(tile_hash2, string_hash_lookup( th->name ), th);
1974 for( idx = 0; idx < th->num_subtiles; idx++ ) {
1976 data = th_get_subtile( th, idx );
1978 if (debug_tile(data) || debug_tile(th->name)) {
1979 fprintf(stderr,"Parent for '%s' is '%s'\n", *data, th->name);
1982 g_hash_table_insert(tile_hash2, *data, th);
1984 len = strlen( *data );
1986 if (len > maxnamelen) {
1995 create_tile_hash(void)
1997 struct tile_head *th;
1998 int len,maxnamelen=0;
2000 tile_hash2=g_hash_table_new(g_str_hash, g_str_equal);
2003 len=add_tile_hash(th);
2004 if (len > maxnamelen)
2012 create_tile_hash_list(GList *list)
2015 struct tile_head *th;
2017 tile_hash2=g_hash_table_new(g_str_hash, g_str_equal);
2019 fprintf(stderr,"list=%p\n", list);
2020 next=g_list_first(list);
2022 th=g_hash_table_lookup(tile_hash, next->data);
2024 fprintf(stderr,"No tile found for '%s'\n", (char *)(next->data));
2027 next=g_list_next(next);
2032 destroy_tile_hash(void)
2034 g_hash_table_destroy(tile_hash2);
2040 static void write_countrydir(int phase, int maxnamelen);
2043 write_tilesdir(int phase, int maxlen, FILE *out)
2046 GList *tiles_list,*next;
2048 struct tile_head *th,**last=NULL;
2051 tiles_list=get_tiles_list();
2053 create_tile_hash_list(tiles_list);
2054 next=g_list_first(tiles_list);
2055 last=&tile_head_root;
2058 if (strlen(next->data) > maxlen)
2059 maxlen=strlen(next->data);
2060 next=g_list_next(next);
2066 fprintf(stderr,"PROGRESS: collecting tiles with len=%d\n", len);
2068 #ifdef GENERATE_INDEX
2070 write_countrydir(phase, maxlen);
2072 next=g_list_first(tiles_list);
2074 if (strlen(next->data) == len) {
2075 th=g_hash_table_lookup(tile_hash, next->data);
2081 fprintf(out,"%s:%d",(char *)next->data,th->total_size);
2083 for ( idx = 0; idx< th->num_subtiles; idx++ ){
2084 data= th_get_subtile( th, idx );
2085 fprintf(out,":%s", *data);
2091 index_submap_add(phase, th, &tiles_list);
2095 next=g_list_next(next);
2104 struct tile_head *th;
2105 char basetile[1024];
2107 GList *tiles_list_sorted,*last;
2108 int i,i_min,len,size_all,size[5],size_min,work_done;
2112 tiles_list_sorted=get_tiles_list();
2113 fprintf(stderr,"PROGRESS: sorting %d tiles\n", g_list_length(tiles_list_sorted));
2114 tiles_list_sorted=g_list_sort(tiles_list_sorted, (GCompareFunc)strcmp);
2115 fprintf(stderr,"PROGRESS: sorting %d tiles done\n", g_list_length(tiles_list_sorted));
2116 last=g_list_last(tiles_list_sorted);
2119 th=g_hash_table_lookup(tile_hash, last->data);
2120 zip_size+=th->total_size;
2121 last=g_list_previous(last);
2123 fprintf(stderr,"DEBUG: size=%Ld\n", zip_size);
2124 last=g_list_last(tiles_list_sorted);
2128 len=strlen(last->data);
2130 strcpy(basetile,last->data);
2131 basetile[len-1]='\0';
2132 strcpy(subtile,last->data);
2133 for (i = 0 ; i < 4 ; i++) {
2134 subtile[len-1]='a'+i;
2135 size[i]=tile_data_size(subtile);
2137 size[4]=tile_data_size(basetile);
2138 size_all=size[0]+size[1]+size[2]+size[3]+size[4];
2139 if (size_all < 65536 && size_all > 0 && size_all != size[4]) {
2140 for (i = 0 ; i < 4 ; i++) {
2141 subtile[len-1]='a'+i;
2142 work_done+=merge_tile(basetile, subtile);
2148 for (i = 0 ; i < 4 ; i++) {
2149 if (size[i] && size[i] < size_min) {
2156 if (size[4]+size_min >= 65536)
2158 subtile[len-1]='a'+i_min;
2159 work_done+=merge_tile(basetile, subtile);
2160 size[4]+=size[i_min];
2165 last=g_list_previous(last);
2167 g_list_free(tiles_list_sorted);
2168 fprintf(stderr,"PROGRESS: merged %d tiles\n", work_done);
2169 } while (work_done);
2172 struct country_index_item {
2173 struct item_bin item;
2174 struct attr_bin attr_country_id;
2176 struct attr_bin attr_zipfile_ref;
2181 index_country_add(int phase, int country_id, int zipnum)
2183 struct country_index_item ii;
2184 char *index_tile="";
2186 ii.item.len=sizeof(ii)/4-1;
2187 ii.item.type=type_countryindex;
2190 ii.attr_country_id.len=2;
2191 ii.attr_country_id.type=attr_country_id;
2192 ii.country_id=country_id;
2194 ii.attr_zipfile_ref.len=2;
2195 ii.attr_zipfile_ref.type=attr_zipfile_ref;
2196 ii.zipfile_ref=zipnum;
2199 tile_extend(index_tile, (struct item_bin *)&ii, NULL);
2201 write_item(index_tile, (struct item_bin *)&ii);
2204 #ifdef GENERATE_INDEX
2212 add_aux_tile(int phase, char *name, char *filename, int size)
2214 struct aux_tile *at;
2216 at=g_new0(struct aux_tile, 1);
2217 at->name=g_strdup(name);
2218 at->filename=g_strdup(filename);
2220 aux_tile_list=g_list_append(aux_tile_list, at);
2226 write_aux_tiles(FILE *out, FILE *dir_out, int compression_level, int namelen)
2228 GList *l=aux_tile_list;
2229 struct aux_tile *at;
2236 buffer=malloc(at->size);
2237 assert(buffer != NULL);
2238 f=fopen(at->filename,"r");
2240 fread(buffer, at->size, 1, f);
2242 write_zipmember(out, dir_out, at->name, namelen, buffer, at->size, compression_level);
2250 write_countrydir(int phase, int maxnamelen)
2255 char searchtile[32];
2257 struct country_table *co;
2258 for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
2259 co=&country_table[i];
2262 tile(&co->r, tilename, max);
2263 sprintf(searchtile,"%ss%d", tilename, 0);
2264 sprintf(filename,"country_%d.bin", co->countryid);
2265 zipnum=add_aux_tile(phase, searchtile, filename, co->size);
2266 index_country_add(phase,co->countryid,zipnum);
2272 remove_countryfiles(void)
2276 struct country_table *co;
2278 for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
2279 co=&country_table[i];
2281 sprintf(filename,"country_%d.bin", co->countryid);
2289 phase34(int phase, int maxnamelen, FILE *ways_in, FILE *nodes_in, FILE *tilesdir_out)
2292 processed_nodes=processed_nodes_out=processed_ways=processed_relations=processed_tiles=0;
2296 tile_hash=g_hash_table_new(g_str_hash, g_str_equal);
2298 phase34_process_file(phase, ways_in);
2300 phase34_process_file(phase, nodes_in);
2301 fprintf(stderr,"read %d bytes\n", bytes_read);
2306 write_tilesdir(phase, maxnamelen, tilesdir_out);
2313 dump_coord(struct coord *c)
2315 printf("0x%x 0x%x",c->x, c->y);
2321 struct item_bin *ib;
2329 while ((ib=read_item(in))) {
2330 c=(struct coord *)(ib+1);
2331 if (ib->type < type_line) {
2335 attr_start=(int *)(ib+1)+ib->clen;
2336 attr_end=(int *)ib+ib->len+1;
2337 printf("type=%s", item_to_name(ib->type));
2338 while (attr_start < attr_end) {
2339 a=(struct attr_bin *)(attr_start);
2340 attr_start+=a->len+1;
2342 attr_data_set(&attr, (a+1));
2343 str=attr_to_text(&attr, NULL, 1);
2344 printf(" %s=\"%s\"", attr_to_name(a->type), str);
2347 printf(" debug=\"length=%d\"", ib->len);
2349 if (ib->type >= type_line) {
2350 for (i = 0 ; i < ib->clen/2 ; i++) {
2360 phase3(FILE *ways_in, FILE *nodes_in, FILE *tilesdir_out)
2362 return phase34(3, 0, ways_in, nodes_in, tilesdir_out);
2365 static long long zipoffset;
2366 static int zipdir_size;
2369 compress2_int(Byte *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
2374 stream.next_in = (Bytef*)source;
2375 stream.avail_in = (uInt)sourceLen;
2376 stream.next_out = dest;
2377 stream.avail_out = (uInt)*destLen;
2378 if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
2380 stream.zalloc = (alloc_func)0;
2381 stream.zfree = (free_func)0;
2382 stream.opaque = (voidpf)0;
2384 err = deflateInit2(&stream, level, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY);
2385 if (err != Z_OK) return err;
2387 err = deflate(&stream, Z_FINISH);
2388 if (err != Z_STREAM_END) {
2389 deflateEnd(&stream);
2390 return err == Z_OK ? Z_BUF_ERROR : err;
2392 *destLen = stream.total_out;
2394 err = deflateEnd(&stream);
2399 write_zipmember(FILE *out, FILE *dir_out, char *name, int filelen, char *data, int data_size, int compression_level)
2401 struct zip_lfh lfh = {
2414 struct zip_cd cd = {
2435 char filename[filelen+1];
2436 int error,crc,len,comp_size=data_size;
2437 uLongf destlen=data_size+data_size/500+12;
2438 char compbuffer[destlen];
2440 crc=crc32(0, NULL, 0);
2441 crc=crc32(crc, (unsigned char *)data, data_size);
2443 if (compression_level) {
2444 error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, compression_level);
2445 if (error == Z_OK) {
2446 if (destlen < data_size) {
2451 fprintf(stderr,"compress2 returned %d\n", error);
2456 lfh.zipsize=comp_size;
2457 lfh.zipuncmp=data_size;
2458 lfh.zipmthd=compression_level ? 8:0;
2460 cd.zipcsiz=comp_size;
2461 cd.zipcunc=data_size;
2462 cd.zipcmthd=compression_level ? 8:0;
2463 strcpy(filename, name);
2464 len=strlen(filename);
2465 while (len < filelen) {
2466 filename[len++]='_';
2468 filename[filelen]='\0';
2469 fwrite(&lfh, sizeof(lfh), 1, out);
2470 fwrite(filename, filelen, 1, out);
2471 fwrite(data, comp_size, 1, out);
2472 zipoffset+=sizeof(lfh)+filelen+comp_size;
2473 fwrite(&cd, sizeof(cd), 1, dir_out);
2474 fwrite(filename, filelen, 1, dir_out);
2475 zipdir_size+=sizeof(cd)+filelen;
2479 process_slice(FILE *ways_in, FILE *nodes_in, int size, int maxnamelen, FILE *out, FILE *dir_out, int compression_level)
2481 struct tile_head *th;
2482 char *slice_data,*zip_data;
2485 slice_data=malloc(size);
2486 assert(slice_data != NULL);
2487 zip_data=slice_data;
2491 th->zip_data=zip_data;
2492 zip_data+=th->total_size;
2497 fseek(ways_in, 0, SEEK_SET);
2499 fseek(nodes_in, 0, SEEK_SET);
2500 phase34(4, maxnamelen, ways_in, nodes_in, NULL);
2505 #ifdef GENERATE_INDEX
2506 if (! strlen(th->name))
2507 zipfiles+=write_aux_tiles(out, dir_out, compression_level, maxnamelen);
2509 if (th->total_size != th->total_size_used) {
2510 fprintf(stderr,"Size error '%s': %d vs %d\n", th->name, th->total_size, th->total_size_used);
2513 if (strlen(th->name))
2514 write_zipmember(out, dir_out, th->name, maxnamelen, th->zip_data, th->total_size, compression_level);
2516 write_zipmember(out, dir_out, "index", sizeof("index")-1, th->zip_data, th->total_size, compression_level);
2529 cat(FILE *in, FILE *out)
2533 while ((size=fread(buffer, 1, 4096, in)))
2534 fwrite(buffer, 1, size, out);
2538 phase4(FILE *ways_in, FILE *nodes_in, FILE *out, FILE *dir_out, int compression_level)
2540 int slice_size=1024*1024*1024;
2541 int maxnamelen,size,slices;
2543 struct tile_head *th,*th2;
2544 struct zip_eoc eoc = {
2555 maxnamelen=create_tile_hash();
2560 fprintf(stderr, "Maximum slice size %d\n", slice_size);
2562 if (size + th->total_size > slice_size) {
2563 fprintf(stderr,"Slice %d is of size %d\n", slices, size);
2567 size+=th->total_size;
2571 fprintf(stderr,"Slice %d is of size %d\n", slices, size);
2582 while (th && size+th->total_size < slice_size) {
2583 size+=th->total_size;
2587 zipfiles+=process_slice(ways_in, nodes_in, size, maxnamelen, out, dir_out, compression_level);
2590 fseek(dir_out, 0, SEEK_SET);
2592 eoc.zipenum=zipfiles;
2593 eoc.zipecenn=zipfiles;
2594 eoc.zipecsz=zipdir_size;
2595 eoc.zipeofst=zipoffset;
2596 fwrite(&eoc, sizeof(eoc), 1, out);
2605 /* DEVELOPPERS : don't forget to update the manpage if you modify theses options */
2607 fprintf(f,"osm2navit - parse osm textfile and converts to NavIt binfile format\n\n");
2608 fprintf(f,"Usage :\n");
2609 fprintf(f,"bzcat planet.osm.bz2 | osm2navit mymap.bin\n");
2610 fprintf(f,"Available switches:\n");
2611 fprintf(f,"-h (--help) : this screen\n");
2612 fprintf(f,"-N (--nodes-only) : process only nodes\n");
2613 fprintf(f,"-W (--ways-only) : process only ways\n");
2614 fprintf(f,"-a (--attr-debug-level) : control which data is included in the debug attribute\n");
2615 fprintf(f,"-c (--dump-coordinates) : dump coordinates after phase 1\n");
2616 #ifdef HAVE_POSTGRESQL
2617 fprintf(f,"-d (--db) : get osm data out of a postgresql database with osm simple scheme and given connect string\n");
2619 fprintf(f,"-e (--end) : end at specified phase\n");
2620 fprintf(f,"-k (--keep-tmpfiles) : do not delete tmp files after processing. useful to reuse them\n\n");
2621 fprintf(f,"-o (--coverage) : map every street to item overage\n");
2622 fprintf(f,"-s (--start) : start at specified phase\n");
2623 fprintf(f,"-i (--input-file) : specify the input file name (OSM), overrules default stdin\n");
2624 fprintf(f,"-w (--dedupe-ways) : ensure no duplicate ways or nodes. useful when using several input files\n");
2625 fprintf(f,"-z (--compression-level) : set the compression level\n");
2630 process_binfile(FILE *in, FILE *out)
2632 struct item_bin *ib;
2633 while ((ib=read_item(in))) {
2634 fwrite(ib, (ib->len+1)*4, 1, out);
2638 int main(int argc, char **argv)
2640 FILE *ways=NULL,*ways_split=NULL,*nodes=NULL,*tilesdir,*zipdir,*res;
2641 char *map=g_strdup(attrmap);
2642 int i,c,start=1,end=4,dump_coordinates=0;
2643 int keep_tmpfiles=0;
2644 int process_nodes=1, process_ways=1;
2646 int compression_level=9;
2648 int compression_level=0;
2652 char *result,*dbstr=NULL;
2653 FILE* input_file = stdin;
2654 struct plugins *plugins=NULL;
2655 struct attr **attrs;
2656 struct map *map_handle=NULL;
2660 int this_option_optind = optind ? optind : 1;
2662 int option_index = 0;
2663 static struct option long_options[] = {
2664 {"attr-debug-level", 1, 0, 'a'},
2665 {"binfile", 0, 0, 'b'},
2666 {"compression-level", 1, 0, 'z'},
2667 {"coverage", 0, 0, 'o'},
2668 #ifdef HAVE_POSTGRESQL
2671 {"dedupe-ways", 0, 0, 'w'},
2672 {"dump", 0, 0, 'D'},
2673 {"dump-coordinates", 0, 0, 'c'},
2675 {"help", 0, 0, 'h'},
2676 {"keep-tmpfiles", 0, 0, 'k'},
2677 {"nodes-only", 0, 0, 'N'},
2679 {"plugin", 1, 0, 'p'},
2680 {"start", 1, 0, 's'},
2681 {"input-file", 1, 0, 'i'},
2682 {"ignore-unknown", 0, 0, 'n'},
2683 {"ways-only", 0, 0, 'W'},
2686 c = getopt_long (argc, argv, "DNWa:bc"
2687 #ifdef HAVE_POSTGRESQL
2690 "e:hi:knm:p:s:w", long_options, &option_index);
2704 attr_debug_level=atoi(optarg);
2712 #ifdef HAVE_POSTGRESQL
2724 attrs=(struct attr*[]){
2725 &(struct attr){attr_type,{"textfile"}},
2726 &(struct attr){attr_data,{"bookmark.txt"}},
2728 map_handle=map_new(attrs);
2729 fprintf(stderr,"optarg=%s\n", optarg);
2732 fprintf(stderr,"I will IGNORE unknown types\n");
2736 fprintf(stderr,"I will KEEP tmp files\n");
2744 plugins=plugins_new();
2745 fprintf(stderr,"optarg=%s\n",optarg);
2746 attrs=(struct attr*[]){&(struct attr){attr_path,{optarg}},NULL};
2747 plugins_add_path(plugins, attrs);
2753 dedupe_ways_hash=g_hash_table_new(NULL, NULL);
2756 input_file = fopen( optarg, "r" );
2757 if ( input_file == NULL )
2759 fprintf( stderr, "\nInput file (%s) not found\n", optarg );
2765 compression_level=atoi(optarg);
2772 fprintf(stderr,"c=%d\n", c);
2776 if (optind != argc-(output == 1 ? 0:1))
2779 plugins_init(plugins);
2780 result=argv[optind];
2782 #ifdef GENERATE_INDEX
2783 build_countrytable();
2790 ways=fopen("ways.tmp","wb+");
2792 nodes=fopen("nodes.tmp","wb+");
2794 fprintf(stderr,"PROGRESS: Phase 1: collecting data\n");
2795 #ifdef HAVE_POSTGRESQL
2797 phase1_db(dbstr,ways,nodes);
2801 phase1_map(map_handle,ways,nodes);
2802 map_destroy(map_handle);
2805 phase1(input_file,ways,nodes);
2810 #ifdef GENERATE_INDEX
2811 fprintf(stderr,"PROGRESS: Phase 1: sorting countries\n");
2815 if (end == 1 || dump_coordinates)
2816 save_buffer("coords.tmp",&node_buffer);
2820 load_buffer("coords.tmp",&node_buffer);
2823 ways=fopen("ways.tmp","rb");
2824 ways_split=fopen("ways_split.tmp","wb+");
2826 fprintf(stderr,"PROGRESS: Phase 2: finding intersections\n");
2827 phase2(ways,ways_split);
2833 fprintf(stderr,"PROGRESS: Skipping Phase 2\n");
2835 free(node_buffer.base);
2836 node_buffer.base=NULL;
2837 node_buffer.malloced=0;
2842 ways_split=fopen("ways_split.tmp","wb+");
2843 process_binfile(stdin, ways_split);
2847 fprintf(stderr,"PROGRESS: Phase 3: dumping\n");
2848 if (process_nodes) {
2849 nodes=fopen("nodes.tmp","rb");
2856 ways_split=fopen("ways_split.tmp","rb");
2866 fprintf(stderr,"PROGRESS: Phase 3: generating tiles\n");
2868 ways_split=fopen("ways_split.tmp","rb");
2870 nodes=fopen("nodes.tmp","rb");
2871 tilesdir=fopen("tilesdir.tmp","wb+");
2872 phase3(ways_split,nodes,tilesdir);
2883 fprintf(stderr,"PROGRESS: Phase 4: assembling map\n");
2885 ways_split=fopen("ways_split.tmp","rb");
2887 nodes=fopen("nodes.tmp","rb");
2888 res=fopen(result,"wb+");
2889 zipdir=fopen("zipdir.tmp","wb+");
2890 phase4(ways_split,nodes,res,zipdir,compression_level);
2897 if(!keep_tmpfiles) {
2898 remove("nodes.tmp");
2899 remove("ways_split.tmp");
2900 remove("tilesdir.tmp");
2901 remove("zipdir.tmp");
2902 #ifdef GENERATE_INDEX
2903 remove_countryfiles();