1 /***************************************
2  Extract data from Routino.
3 
4  Part of the Routino routing software.
5  ******************/ /******************
6  This file Copyright 2008-2015, 2017 Andrew M. Bishop
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU Affero General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU Affero General Public License for more details.
17 
18  You should have received a copy of the GNU Affero General Public License
19  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  ***************************************/
21 
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "types.h"
28 #include "nodes.h"
29 #include "segments.h"
30 #include "ways.h"
31 #include "relations.h"
32 #include "errorlog.h"
33 
34 #include "typesx.h"
35 
36 #include "visualiser.h"
37 
38 
39 /* Limit types */
40 
41 #define SPEED_LIMIT  1
42 #define WEIGHT_LIMIT 2
43 #define HEIGHT_LIMIT 3
44 #define WIDTH_LIMIT  4
45 #define LENGTH_LIMIT 5
46 
47 /* Local types */
48 
49 typedef void (*callback_t)(index_t node,double latitude,double longitude);
50 
51 /* Local variables (intialised by entry-point function before later use) */
52 
53 static Nodes     *OSMNodes;
54 static Segments  *OSMSegments;
55 static Ways      *OSMWays;
56 static Relations *OSMRelations;
57 
58 static double LatMin;
59 static double LatMax;
60 static double LonMin;
61 static double LonMax;
62 
63 static int limit_type=0;
64 static Highway highways=Highway_None;
65 static Transports transports=Transports_None;
66 static Properties properties=Properties_None;
67 static highway_t waytype=0;
68 
69 /* Local functions */
70 
71 static void find_all_nodes(Nodes *nodes,callback_t callback);
72 
73 static void output_junctions(index_t node,double latitude,double longitude);
74 static void output_super(index_t node,double latitude,double longitude);
75 static void output_waytype(index_t node,double latitude,double longitude);
76 static void output_highway(index_t node,double latitude,double longitude);
77 static void output_transport(index_t node,double latitude,double longitude);
78 static void output_barrier(index_t node,double latitude,double longitude);
79 static void output_turnrestriction(index_t node,double latitude,double longitude);
80 static void output_limits(index_t node,double latitude,double longitude);
81 static void output_property(index_t node,double latitude,double longitude);
82 
83 
84 /*++++++++++++++++++++++++++++++++++++++
85   Output the data for junctions (--data=junctions).
86 
87   Nodes *nodes The set of nodes to use.
88 
89   Segments *segments The set of segments to use.
90 
91   Ways *ways The set of ways to use.
92 
93   Relations *relations The set of relations to use.
94 
95   double latmin The minimum latitude.
96 
97   double latmax The maximum latitude.
98 
99   double lonmin The minimum longitude.
100 
101   double lonmax The maximum longitude.
102   ++++++++++++++++++++++++++++++++++++++*/
103 
OutputJunctions(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)104 void OutputJunctions(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
105 {
106  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
107 
108  OSMNodes=nodes;
109  OSMSegments=segments;
110  OSMWays=ways;
111  OSMRelations=relations;
112 
113  LatMin=latmin;
114  LatMax=latmax;
115  LonMin=lonmin;
116  LonMax=lonmax;
117 
118  /* Iterate through the nodes and process them */
119 
120  find_all_nodes(nodes,(callback_t)output_junctions);
121 }
122 
123 
124 /*++++++++++++++++++++++++++++++++++++++
125   Process a single node and output all those that are junctions (called as a callback).
126 
127   index_t node The node to output.
128 
129   double latitude The latitude of the node.
130 
131   double longitude The longitude of the node.
132   ++++++++++++++++++++++++++++++++++++++*/
133 
output_junctions(index_t node,double latitude,double longitude)134 static void output_junctions(index_t node,double latitude,double longitude)
135 {
136  Node *nodep=LookupNode(OSMNodes,node,1);
137  Segment *segmentp;
138  Way *firstwayp;
139  int count=0,difference=0;
140 
141  segmentp=FirstSegment(OSMSegments,nodep,1);
142  firstwayp=LookupWay(OSMWays,segmentp->way,1);
143 
144  do
145    {
146     Way *wayp=LookupWay(OSMWays,segmentp->way,2);
147 
148     if(IsNormalSegment(segmentp))
149        count++;
150 
151     if(WaysCompare(firstwayp,wayp))
152        difference=1;
153 
154     segmentp=NextSegment(OSMSegments,segmentp,node);
155    }
156  while(segmentp);
157 
158  if(count!=2 || difference)
159     printf("node%"Pindex_t" %.6f %.6f %d\n",node,radians_to_degrees(latitude),radians_to_degrees(longitude),count);
160 }
161 
162 
163 /*++++++++++++++++++++++++++++++++++++++
164   Output the data for super-nodes and super-segments (--data=super).
165 
166   Nodes *nodes The set of nodes to use.
167 
168   Segments *segments The set of segments to use.
169 
170   Ways *ways The set of ways to use.
171 
172   Relations *relations The set of relations to use.
173 
174   double latmin The minimum latitude.
175 
176   double latmax The maximum latitude.
177 
178   double lonmin The minimum longitude.
179 
180   double lonmax The maximum longitude.
181   ++++++++++++++++++++++++++++++++++++++*/
182 
OutputSuper(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)183 void OutputSuper(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
184 {
185  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
186 
187  OSMNodes=nodes;
188  OSMSegments=segments;
189  OSMWays=ways;
190  OSMRelations=relations;
191 
192  LatMin=latmin;
193  LatMax=latmax;
194  LonMin=lonmin;
195  LonMax=lonmax;
196 
197  /* Iterate through the nodes and process them */
198 
199  find_all_nodes(nodes,(callback_t)output_super);
200 }
201 
202 
203 /*++++++++++++++++++++++++++++++++++++++
204   Process a single node and output all that are super-nodes and all connected super-segments (called as a callback).
205 
206   index_t node The node to output.
207 
208   double latitude The latitude of the node.
209 
210   double longitude The longitude of the node.
211   ++++++++++++++++++++++++++++++++++++++*/
212 
output_super(index_t node,double latitude,double longitude)213 static void output_super(index_t node,double latitude,double longitude)
214 {
215  Node *nodep=LookupNode(OSMNodes,node,1);
216  Segment *segmentp;
217 
218  if(!IsSuperNode(nodep))
219     return;
220 
221  printf("node%"Pindex_t" %.6f %.6f\n",node,radians_to_degrees(latitude),radians_to_degrees(longitude));
222 
223  segmentp=FirstSegment(OSMSegments,nodep,1);
224 
225  do
226    {
227     if(IsSuperSegment(segmentp))
228       {
229        index_t othernode=OtherNode(segmentp,node);
230        double lat,lon;
231 
232        GetLatLong(OSMNodes,othernode,NULL,&lat,&lon);
233 
234        if(node>othernode || (lat<LatMin || lat>LatMax || lon<LonMin || lon>LonMax))
235           printf("segment%"Pindex_t" %.6f %.6f\n",IndexSegment(OSMSegments,segmentp),radians_to_degrees(lat),radians_to_degrees(lon));
236       }
237 
238     segmentp=NextSegment(OSMSegments,segmentp,node);
239    }
240  while(segmentp);
241 }
242 
243 
244 /*++++++++++++++++++++++++++++++++++++++
245   Output the data for segments of special highway types (--data=waytype-oneway etc).
246 
247   Nodes *nodes The set of nodes to use.
248 
249   Segments *segments The set of segments to use.
250 
251   Ways *ways The set of ways to use.
252 
253   Relations *relations The set of relations to use.
254 
255   double latmin The minimum latitude.
256 
257   double latmax The maximum latitude.
258 
259   double lonmin The minimum longitude.
260 
261   double lonmax The maximum longitude.
262 
263   highway_t mask A bit mask that must match the highway type.
264   ++++++++++++++++++++++++++++++++++++++*/
265 
OutputWaytype(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax,highway_t mask)266 void OutputWaytype(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax,highway_t mask)
267 {
268  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
269 
270  OSMNodes=nodes;
271  OSMSegments=segments;
272  OSMWays=ways;
273  OSMRelations=relations;
274 
275  LatMin=latmin;
276  LatMax=latmax;
277  LonMin=lonmin;
278  LonMax=lonmax;
279 
280  /* Iterate through the nodes and process them */
281 
282  waytype=mask;
283 
284  find_all_nodes(nodes,(callback_t)output_waytype);
285 }
286 
287 
288 /*++++++++++++++++++++++++++++++++++++++
289   Process a single node and output all connected segments of a particular special highway type (called as a callback).
290 
291   index_t node The node to output.
292 
293   double latitude The latitude of the node.
294 
295   double longitude The longitude of the node.
296   ++++++++++++++++++++++++++++++++++++++*/
297 
output_waytype(index_t node,double latitude,double longitude)298 static void output_waytype(index_t node,double latitude,double longitude)
299 {
300  Node *nodep=LookupNode(OSMNodes,node,1);
301  Segment *segmentp;
302 
303  segmentp=FirstSegment(OSMSegments,nodep,1);
304 
305  do
306    {
307     if(IsNormalSegment(segmentp))
308       {
309        Way *wayp=LookupWay(OSMWays,segmentp->way,1);
310 
311        if(wayp->type&waytype)
312          {
313           index_t othernode=OtherNode(segmentp,node);
314           double lat,lon;
315 
316           GetLatLong(OSMNodes,othernode,NULL,&lat,&lon);
317 
318           if(node>othernode || (lat<LatMin || lat>LatMax || lon<LonMin || lon>LonMax))
319             {
320              if(IsOnewayFrom(segmentp,node))
321                 printf("segment%"Pindex_t" %.6f %.6f %.6f %.6f\n",IndexSegment(OSMSegments,segmentp),radians_to_degrees(latitude),radians_to_degrees(longitude),radians_to_degrees(lat),radians_to_degrees(lon));
322              else if(IsOnewayFrom(segmentp,othernode))
323                 printf("segment%"Pindex_t" %.6f %.6f %.6f %.6f\n",IndexSegment(OSMSegments,segmentp),radians_to_degrees(lat),radians_to_degrees(lon),radians_to_degrees(latitude),radians_to_degrees(longitude));
324             }
325          }
326       }
327 
328     segmentp=NextSegment(OSMSegments,segmentp,node);
329    }
330  while(segmentp);
331 }
332 
333 
334 /*++++++++++++++++++++++++++++++++++++++
335   Output the data for segments of a particular highway type (--data=highway-primary etc).
336 
337   Nodes *nodes The set of nodes to use.
338 
339   Segments *segments The set of segments to use.
340 
341   Ways *ways The set of ways to use.
342 
343   Relations *relations The set of relations to use.
344 
345   double latmin The minimum latitude.
346 
347   double latmax The maximum latitude.
348 
349   double lonmin The minimum longitude.
350 
351   double lonmax The maximum longitude.
352 
353   Highway highway The type of highway.
354   ++++++++++++++++++++++++++++++++++++++*/
355 
OutputHighway(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax,Highway highway)356 void OutputHighway(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax,Highway highway)
357 {
358  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
359 
360  OSMNodes=nodes;
361  OSMSegments=segments;
362  OSMWays=ways;
363  OSMRelations=relations;
364 
365  LatMin=latmin;
366  LatMax=latmax;
367  LonMin=lonmin;
368  LonMax=lonmax;
369 
370  /* Iterate through the nodes and process them */
371 
372  highways=highway;
373 
374  find_all_nodes(nodes,(callback_t)output_highway);
375 }
376 
377 
378 /*++++++++++++++++++++++++++++++++++++++
379   Process a single node and output all connected segments that are of a particular highway type (called as a callback).
380 
381   index_t node The node to output.
382 
383   double latitude The latitude of the node.
384 
385   double longitude The longitude of the node.
386   ++++++++++++++++++++++++++++++++++++++*/
387 
output_highway(index_t node,double latitude,double longitude)388 static void output_highway(index_t node,double latitude,double longitude)
389 {
390  Node *nodep=LookupNode(OSMNodes,node,1);
391  Segment *segmentp;
392 
393  segmentp=FirstSegment(OSMSegments,nodep,1);
394 
395  do
396    {
397     if(IsNormalSegment(segmentp))
398       {
399        Way *wayp=LookupWay(OSMWays,segmentp->way,1);
400 
401        if(HIGHWAY(wayp->type)==highways)
402          {
403           index_t othernode=OtherNode(segmentp,node);
404           double lat,lon;
405 
406           GetLatLong(OSMNodes,othernode,NULL,&lat,&lon);
407 
408           if(node>othernode || (lat<LatMin || lat>LatMax || lon<LonMin || lon>LonMax))
409              printf("segment%"Pindex_t" %.6f %.6f %.6f %.6f\n",IndexSegment(OSMSegments,segmentp),radians_to_degrees(latitude),radians_to_degrees(longitude),radians_to_degrees(lat),radians_to_degrees(lon));
410          }
411       }
412 
413     segmentp=NextSegment(OSMSegments,segmentp,node);
414    }
415  while(segmentp);
416 }
417 
418 
419 /*++++++++++++++++++++++++++++++++++++++
420   Output the data for segments allowed for a particular type of traffic (--data=transport-motorcar etc).
421 
422   Nodes *nodes The set of nodes to use.
423 
424   Segments *segments The set of segments to use.
425 
426   Ways *ways The set of ways to use.
427 
428   Relations *relations The set of relations to use.
429 
430   double latmin The minimum latitude.
431 
432   double latmax The maximum latitude.
433 
434   double lonmin The minimum longitude.
435 
436   double lonmax The maximum longitude.
437 
438   Transport transport The type of transport.
439   ++++++++++++++++++++++++++++++++++++++*/
440 
OutputTransport(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax,Transport transport)441 void OutputTransport(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax,Transport transport)
442 {
443  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
444 
445  OSMNodes=nodes;
446  OSMSegments=segments;
447  OSMWays=ways;
448  OSMRelations=relations;
449 
450  LatMin=latmin;
451  LatMax=latmax;
452  LonMin=lonmin;
453  LonMax=lonmax;
454 
455  /* Iterate through the nodes and process them */
456 
457  transports=TRANSPORTS(transport);
458 
459  find_all_nodes(nodes,(callback_t)output_transport);
460 }
461 
462 
463 /*++++++++++++++++++++++++++++++++++++++
464   Process a single node and output all connected segments for a particular traffic type (called as a callback).
465 
466   index_t node The node to output.
467 
468   double latitude The latitude of the node.
469 
470   double longitude The longitude of the node.
471   ++++++++++++++++++++++++++++++++++++++*/
472 
output_transport(index_t node,double latitude,double longitude)473 static void output_transport(index_t node,double latitude,double longitude)
474 {
475  Node *nodep=LookupNode(OSMNodes,node,1);
476  Segment *segmentp;
477 
478  segmentp=FirstSegment(OSMSegments,nodep,1);
479 
480  do
481    {
482     if(IsNormalSegment(segmentp))
483       {
484        Way *wayp=LookupWay(OSMWays,segmentp->way,1);
485 
486        if(wayp->allow&transports)
487          {
488           index_t othernode=OtherNode(segmentp,node);
489           double lat,lon;
490 
491           GetLatLong(OSMNodes,othernode,NULL,&lat,&lon);
492 
493           if(node>othernode || (lat<LatMin || lat>LatMax || lon<LonMin || lon>LonMax))
494              printf("segment%"Pindex_t" %.6f %.6f %.6f %.6f\n",IndexSegment(OSMSegments,segmentp),radians_to_degrees(latitude),radians_to_degrees(longitude),radians_to_degrees(lat),radians_to_degrees(lon));
495          }
496       }
497 
498     segmentp=NextSegment(OSMSegments,segmentp,node);
499    }
500  while(segmentp);
501 }
502 
503 
504 /*++++++++++++++++++++++++++++++++++++++
505   Output the data for nodes disallowed for a particular type of traffic (--data=barrier).
506 
507   Nodes *nodes The set of nodes to use.
508 
509   Segments *segments The set of segments to use.
510 
511   Ways *ways The set of ways to use.
512 
513   Relations *relations The set of relations to use.
514 
515   double latmin The minimum latitude.
516 
517   double latmax The maximum latitude.
518 
519   double lonmin The minimum longitude.
520 
521   double lonmax The maximum longitude.
522 
523   Transport transport The type of transport.
524   ++++++++++++++++++++++++++++++++++++++*/
525 
OutputBarrier(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax,Transport transport)526 void OutputBarrier(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax,Transport transport)
527 {
528  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
529 
530  OSMNodes=nodes;
531  OSMSegments=segments;
532  OSMWays=ways;
533  OSMRelations=relations;
534 
535  LatMin=latmin;
536  LatMax=latmax;
537  LonMin=lonmin;
538  LonMax=lonmax;
539 
540  /* Iterate through the nodes and process them */
541 
542  transports=TRANSPORTS(transport);
543 
544  find_all_nodes(nodes,(callback_t)output_barrier);
545 }
546 
547 
548 /*++++++++++++++++++++++++++++++++++++++
549   Process a single node and output those that are barriers (called as a callback).
550 
551   index_t node The node to output.
552 
553   double latitude The latitude of the node.
554 
555   double longitude The longitude of the node.
556   ++++++++++++++++++++++++++++++++++++++*/
557 
output_barrier(index_t node,double latitude,double longitude)558 static void output_barrier(index_t node,double latitude,double longitude)
559 {
560  Node *nodep=LookupNode(OSMNodes,node,1);
561 
562  if(!(nodep->allow&transports))
563     printf("node%"Pindex_t" %.6f %.6f\n",node,radians_to_degrees(latitude),radians_to_degrees(longitude));
564 }
565 
566 
567 /*++++++++++++++++++++++++++++++++++++++
568   Output the data for turn restrictions (--data=turns).
569 
570   Nodes *nodes The set of nodes to use.
571 
572   Segments *segments The set of segments to use.
573 
574   Ways *ways The set of ways to use.
575 
576   Relations *relations The set of relations to use.
577 
578   double latmin The minimum latitude.
579 
580   double latmax The maximum latitude.
581 
582   double lonmin The minimum longitude.
583 
584   double lonmax The maximum longitude.
585   ++++++++++++++++++++++++++++++++++++++*/
586 
OutputTurnRestrictions(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)587 void OutputTurnRestrictions(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
588 {
589  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
590 
591  OSMNodes=nodes;
592  OSMSegments=segments;
593  OSMWays=ways;
594  OSMRelations=relations;
595 
596  LatMin=latmin;
597  LatMax=latmax;
598  LonMin=lonmin;
599  LonMax=lonmax;
600 
601  /* Iterate through the nodes and process them */
602 
603  find_all_nodes(nodes,(callback_t)output_turnrestriction);
604 }
605 
606 
607 /*++++++++++++++++++++++++++++++++++++++
608   Process a single node and output those that are 'via' nodes for a turn restriction and the associated segments (called as a callback).
609 
610   index_t node The node to output.
611 
612   double latitude The latitude of the node.
613 
614   double longitude The longitude of the node.
615   ++++++++++++++++++++++++++++++++++++++*/
616 
output_turnrestriction(index_t node,double latitude,double longitude)617 static void output_turnrestriction(index_t node,double latitude,double longitude)
618 {
619  Node *nodep=LookupNode(OSMNodes,node,1);
620  index_t turnrelation=NO_RELATION;
621 
622  if(!IsTurnRestrictedNode(nodep))
623     return;
624 
625  turnrelation=FindFirstTurnRelation1(OSMRelations,node);
626 
627  do
628    {
629     TurnRelation *relation;
630     Segment *from_segmentp,*to_segmentp;
631     index_t from_node,to_node;
632     double from_lat,from_lon,to_lat,to_lon;
633 
634     relation=LookupTurnRelation(OSMRelations,turnrelation,1);
635 
636     from_segmentp=LookupSegment(OSMSegments,relation->from,1);
637     to_segmentp  =LookupSegment(OSMSegments,relation->to  ,2);
638 
639     from_node=OtherNode(from_segmentp,node);
640     to_node  =OtherNode(to_segmentp  ,node);
641 
642     GetLatLong(OSMNodes,from_node,NULL,&from_lat,&from_lon);
643     GetLatLong(OSMNodes,to_node  ,NULL,&to_lat  ,&to_lon);
644 
645     printf("turn-relation%"Pindex_t" %.6f %.6f %.6f %.6f %.6f %.6f\n",
646            turnrelation,
647            radians_to_degrees(from_lat),radians_to_degrees(from_lon),
648            radians_to_degrees(latitude),radians_to_degrees(longitude),
649            radians_to_degrees(to_lat),radians_to_degrees(to_lon));
650 
651     turnrelation=FindNextTurnRelation1(OSMRelations,turnrelation);
652    }
653  while(turnrelation!=NO_RELATION);
654 }
655 
656 
657 /*++++++++++++++++++++++++++++++++++++++
658   Output the data for speed limits (--data=speed).
659 
660   Nodes *nodes The set of nodes to use.
661 
662   Segments *segments The set of segments to use.
663 
664   Ways *ways The set of ways to use.
665 
666   Relations *relations The set of relations to use.
667 
668   double latmin The minimum latitude.
669 
670   double latmax The maximum latitude.
671 
672   double lonmin The minimum longitude.
673 
674   double lonmax The maximum longitude.
675   ++++++++++++++++++++++++++++++++++++++*/
676 
OutputSpeedLimits(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)677 void OutputSpeedLimits(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
678 {
679  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
680 
681  OSMNodes=nodes;
682  OSMSegments=segments;
683  OSMWays=ways;
684  OSMRelations=relations;
685 
686  LatMin=latmin;
687  LatMax=latmax;
688  LonMin=lonmin;
689  LonMax=lonmax;
690 
691  /* Iterate through the nodes and process them */
692 
693  limit_type=SPEED_LIMIT;
694 
695  find_all_nodes(nodes,(callback_t)output_limits);
696 }
697 
698 
699 /*++++++++++++++++++++++++++++++++++++++
700   Output the data for weight limits (--data=weight).
701 
702   Nodes *nodes The set of nodes to use.
703 
704   Segments *segments The set of segments to use.
705 
706   Ways *ways The set of ways to use.
707 
708   Relations *relations The set of relations to use.
709 
710   double latmin The minimum latitude.
711 
712   double latmax The maximum latitude.
713 
714   double lonmin The minimum longitude.
715 
716   double lonmax The maximum longitude.
717   ++++++++++++++++++++++++++++++++++++++*/
718 
OutputWeightLimits(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)719 void OutputWeightLimits(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
720 {
721  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
722 
723  OSMNodes=nodes;
724  OSMSegments=segments;
725  OSMWays=ways;
726  OSMRelations=relations;
727 
728  LatMin=latmin;
729  LatMax=latmax;
730  LonMin=lonmin;
731  LonMax=lonmax;
732 
733  /* Iterate through the nodes and process them */
734 
735  limit_type=WEIGHT_LIMIT;
736 
737  find_all_nodes(nodes,(callback_t)output_limits);
738 }
739 
740 
741 /*++++++++++++++++++++++++++++++++++++++
742   Output the data for height limits (--data=height).
743 
744   Nodes *nodes The set of nodes to use.
745 
746   Segments *segments The set of segments to use.
747 
748   Ways *ways The set of ways to use.
749 
750   Relations *relations The set of relations to use.
751 
752   double latmin The minimum latitude.
753 
754   double latmax The maximum latitude.
755 
756   double lonmin The minimum longitude.
757 
758   double lonmax The maximum longitude.
759   ++++++++++++++++++++++++++++++++++++++*/
760 
OutputHeightLimits(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)761 void OutputHeightLimits(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
762 {
763  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
764 
765  OSMNodes=nodes;
766  OSMSegments=segments;
767  OSMWays=ways;
768  OSMRelations=relations;
769 
770  LatMin=latmin;
771  LatMax=latmax;
772  LonMin=lonmin;
773  LonMax=lonmax;
774 
775  /* Iterate through the nodes and process them */
776 
777  limit_type=HEIGHT_LIMIT;
778 
779  find_all_nodes(nodes,(callback_t)output_limits);
780 }
781 
782 
783 /*++++++++++++++++++++++++++++++++++++++
784   Output the data for width limits (--data=width).
785 
786   Nodes *nodes The set of nodes to use.
787 
788   Segments *segments The set of segments to use.
789 
790   Ways *ways The set of ways to use.
791 
792   Relations *relations The set of relations to use.
793 
794   double latmin The minimum latitude.
795 
796   double latmax The maximum latitude.
797 
798   double lonmin The minimum longitude.
799 
800   double lonmax The maximum longitude.
801   ++++++++++++++++++++++++++++++++++++++*/
802 
OutputWidthLimits(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)803 void OutputWidthLimits(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
804 {
805  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
806 
807  OSMNodes=nodes;
808  OSMSegments=segments;
809  OSMWays=ways;
810  OSMRelations=relations;
811 
812  LatMin=latmin;
813  LatMax=latmax;
814  LonMin=lonmin;
815  LonMax=lonmax;
816 
817  /* Iterate through the nodes and process them */
818 
819  limit_type=WIDTH_LIMIT;
820 
821  find_all_nodes(nodes,(callback_t)output_limits);
822 }
823 
824 
825 /*++++++++++++++++++++++++++++++++++++++
826   Output the data for length limits (--data=length).
827 
828   Nodes *nodes The set of nodes to use.
829 
830   Segments *segments The set of segments to use.
831 
832   Ways *ways The set of ways to use.
833 
834   Relations *relations The set of relations to use.
835 
836   double latmin The minimum latitude.
837 
838   double latmax The maximum latitude.
839 
840   double lonmin The minimum longitude.
841 
842   double lonmax The maximum longitude.
843   ++++++++++++++++++++++++++++++++++++++*/
844 
OutputLengthLimits(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax)845 void OutputLengthLimits(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax)
846 {
847  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
848 
849  OSMNodes=nodes;
850  OSMSegments=segments;
851  OSMWays=ways;
852  OSMRelations=relations;
853 
854  LatMin=latmin;
855  LatMax=latmax;
856  LonMin=lonmin;
857  LonMax=lonmax;
858 
859  /* Iterate through the nodes and process them */
860 
861  limit_type=LENGTH_LIMIT;
862 
863  find_all_nodes(nodes,(callback_t)output_limits);
864 }
865 
866 
867 /*++++++++++++++++++++++++++++++++++++++
868   Process a single node and output those and connected segments that have a speed, weight, height, width or length limit change (called as a callback).
869 
870   index_t node The node to output.
871 
872   double latitude The latitude of the node.
873 
874   double longitude The longitude of the node.
875   ++++++++++++++++++++++++++++++++++++++*/
876 
output_limits(index_t node,double latitude,double longitude)877 static void output_limits(index_t node,double latitude,double longitude)
878 {
879  Node *nodep=LookupNode(OSMNodes,node,1);
880  Segment *segmentp,segmentps[MAX_SEG_PER_NODE];
881  index_t segments[MAX_SEG_PER_NODE];
882  int limits[MAX_SEG_PER_NODE];
883  int count=0;
884  int i,j,same=0;
885 
886  segmentp=FirstSegment(OSMSegments,nodep,1);
887 
888  do
889    {
890     if(IsNormalSegment(segmentp) && count<MAX_SEG_PER_NODE)
891       {
892        Way *wayp=LookupWay(OSMWays,segmentp->way,1);
893 
894        segmentps[count]=*segmentp;
895        segments [count]=IndexSegment(OSMSegments,segmentp);
896 
897        switch(limit_type)
898          {
899          case SPEED_LIMIT:  limits[count]=wayp->speed;  break;
900          case WEIGHT_LIMIT: limits[count]=wayp->weight; break;
901          case HEIGHT_LIMIT: limits[count]=wayp->height; break;
902          case WIDTH_LIMIT:  limits[count]=wayp->width;  break;
903          case LENGTH_LIMIT: limits[count]=wayp->length; break;
904          default:           limits[count]=0;            break;
905          }
906 
907        if(limits[count] || HIGHWAY(wayp->type)<Highway_Track)
908           count++;
909       }
910 
911     segmentp=NextSegment(OSMSegments,segmentp,node);
912    }
913  while(segmentp);
914 
915  /* Nodes with one or fewer limits are not interesting */
916 
917  if(count<=1)
918     return;
919 
920  /* Nodes with all segments the same limit are not interesting */
921 
922  same=0;
923  for(j=0;j<count;j++)
924     if(limits[0]==limits[j])
925        same++;
926 
927  if(same==count)
928     return;
929 
930  /* Display the interesting limits */
931 
932  printf("node%"Pindex_t" %.6f %.6f\n",node,radians_to_degrees(latitude),radians_to_degrees(longitude));
933 
934  for(i=0;i<count;i++)
935    {
936     same=0;
937     for(j=0;j<count;j++)
938        if(limits[i]==limits[j])
939           same++;
940 
941     if(count==2 || same!=(count-1))
942       {
943        double lat,lon;
944 
945        GetLatLong(OSMNodes,OtherNode(&segmentps[i],node),NULL,&lat,&lon);
946 
947        switch(limit_type)
948          {
949          case SPEED_LIMIT:
950           printf("segment%"Pindex_t" %.6f %.6f %d\n",segments[i],radians_to_degrees(lat),radians_to_degrees(lon),speed_to_kph(limits[i]));
951           break;
952          case WEIGHT_LIMIT:
953           printf("segment%"Pindex_t" %.6f %.6f %.1f\n",segments[i],radians_to_degrees(lat),radians_to_degrees(lon),weight_to_tonnes(limits[i]));
954           break;
955          case HEIGHT_LIMIT:
956           printf("segment%"Pindex_t" %.6f %.6f %.1f\n",segments[i],radians_to_degrees(lat),radians_to_degrees(lon),height_to_metres(limits[i]));
957           break;
958          case WIDTH_LIMIT:
959           printf("segment%"Pindex_t" %.6f %.6f %.1f\n",segments[i],radians_to_degrees(lat),radians_to_degrees(lon),width_to_metres(limits[i]));
960           break;
961          case LENGTH_LIMIT:
962           printf("segment%"Pindex_t" %.6f %.6f %.1f\n",segments[i],radians_to_degrees(lat),radians_to_degrees(lon),length_to_metres(limits[i]));
963           break;
964          }
965       }
966    }
967 }
968 
969 
970 /*++++++++++++++++++++++++++++++++++++++
971   Output the data for segments that have a particular property (--data=property-paved etc).
972 
973   Nodes *nodes The set of nodes to use.
974 
975   Segments *segments The set of segments to use.
976 
977   Ways *ways The set of ways to use.
978 
979   Relations *relations The set of relations to use.
980 
981   double latmin The minimum latitude.
982 
983   double latmax The maximum latitude.
984 
985   double lonmin The minimum longitude.
986 
987   double lonmax The maximum longitude.
988 
989   Property property The type of property.
990   ++++++++++++++++++++++++++++++++++++++*/
991 
OutputProperty(Nodes * nodes,Segments * segments,Ways * ways,Relations * relations,double latmin,double latmax,double lonmin,double lonmax,Property property)992 void OutputProperty(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,double latmin,double latmax,double lonmin,double lonmax,Property property)
993 {
994  /* Use local variables so that the callback doesn't need to pass them backwards and forwards */
995 
996  OSMNodes=nodes;
997  OSMSegments=segments;
998  OSMWays=ways;
999  OSMRelations=relations;
1000 
1001  LatMin=latmin;
1002  LatMax=latmax;
1003  LonMin=lonmin;
1004  LonMax=lonmax;
1005 
1006  /* Iterate through the nodes and process them */
1007 
1008  properties=PROPERTIES(property);
1009 
1010  find_all_nodes(nodes,(callback_t)output_property);
1011 }
1012 
1013 
1014 /*++++++++++++++++++++++++++++++++++++++
1015   Process a single node and output all connected segments with a particular property (called as a callback).
1016 
1017   index_t node The node to output.
1018 
1019   double latitude The latitude of the node.
1020 
1021   double longitude The longitude of the node.
1022   ++++++++++++++++++++++++++++++++++++++*/
1023 
output_property(index_t node,double latitude,double longitude)1024 static void output_property(index_t node,double latitude,double longitude)
1025 {
1026  Node *nodep=LookupNode(OSMNodes,node,1);
1027  Segment *segmentp;
1028 
1029  segmentp=FirstSegment(OSMSegments,nodep,1);
1030 
1031  do
1032    {
1033     if(IsNormalSegment(segmentp))
1034       {
1035        Way *wayp=LookupWay(OSMWays,segmentp->way,1);
1036 
1037        if(wayp->props&properties)
1038          {
1039           index_t othernode=OtherNode(segmentp,node);
1040           double lat,lon;
1041 
1042           GetLatLong(OSMNodes,othernode,NULL,&lat,&lon);
1043 
1044           if(node>othernode || (lat<LatMin || lat>LatMax || lon<LonMin || lon>LonMax))
1045              printf("segment%"Pindex_t" %.6f %.6f %.6f %.6f\n",IndexSegment(OSMSegments,segmentp),radians_to_degrees(latitude),radians_to_degrees(longitude),radians_to_degrees(lat),radians_to_degrees(lon));
1046          }
1047       }
1048 
1049     segmentp=NextSegment(OSMSegments,segmentp,node);
1050    }
1051  while(segmentp);
1052 }
1053 
1054 
1055 /*++++++++++++++++++++++++++++++++++++++
1056   A function to iterate through all nodes and call a callback function for each one.
1057 
1058   Nodes *nodes The set of nodes to use.
1059 
1060   callback_t callback The callback function for each node.
1061   ++++++++++++++++++++++++++++++++++++++*/
1062 
find_all_nodes(Nodes * nodes,callback_t callback)1063 static void find_all_nodes(Nodes *nodes,callback_t callback)
1064 {
1065  ll_bin_t latminbin=latlong_to_bin(radians_to_latlong(LatMin))-nodes->file.latzero;
1066  ll_bin_t latmaxbin=latlong_to_bin(radians_to_latlong(LatMax))-nodes->file.latzero;
1067  ll_bin_t lonminbin=latlong_to_bin(radians_to_latlong(LonMin))-nodes->file.lonzero;
1068  ll_bin_t lonmaxbin=latlong_to_bin(radians_to_latlong(LonMax))-nodes->file.lonzero;
1069  ll_bin_t latb,lonb;
1070  index_t i,index1,index2;
1071 
1072  /* Loop through all of the nodes. */
1073 
1074  if(latminbin<0)                   latminbin=0;
1075  if(latmaxbin>nodes->file.latbins) latmaxbin=nodes->file.latbins-1;
1076 
1077  if(lonminbin<0)                   lonminbin=0;
1078  if(lonmaxbin>nodes->file.lonbins) lonmaxbin=nodes->file.lonbins-1;
1079 
1080  for(latb=latminbin;latb<=latmaxbin;latb++)
1081     for(lonb=lonminbin;lonb<=lonmaxbin;lonb++)
1082       {
1083        ll_bin2_t llbin=lonb*nodes->file.latbins+latb;
1084 
1085        if(llbin<0 || llbin>(nodes->file.latbins*nodes->file.lonbins))
1086           continue;
1087 
1088        index1=LookupNodeOffset(nodes,llbin);
1089        index2=LookupNodeOffset(nodes,llbin+1);
1090 
1091        for(i=index1;i<index2;i++)
1092          {
1093           Node *nodep=LookupNode(nodes,i,1);
1094 
1095           double lat=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)+off_to_latlong(nodep->latoffset));
1096           double lon=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)+off_to_latlong(nodep->lonoffset));
1097 
1098           if(lat>LatMin && lat<LatMax && lon>LonMin && lon<LonMax)
1099              (*callback)(i,lat,lon);
1100          }
1101       }
1102 }
1103 
1104 
1105 /*++++++++++++++++++++++++++++++++++++++
1106   Output the data for error logs within the region (--data=errorlogs).
1107 
1108   ErrorLogs *errorlogs The set of error logs to use.
1109 
1110   double latmin The minimum latitude.
1111 
1112   double latmax The maximum latitude.
1113 
1114   double lonmin The minimum longitude.
1115 
1116   double lonmax The maximum longitude.
1117   ++++++++++++++++++++++++++++++++++++++*/
1118 
OutputErrorLog(ErrorLogs * errorlogs,double latmin,double latmax,double lonmin,double lonmax)1119 void OutputErrorLog(ErrorLogs *errorlogs,double latmin,double latmax,double lonmin,double lonmax)
1120 {
1121  ll_bin_t latminbin=latlong_to_bin(radians_to_latlong(latmin))-errorlogs->file.latzero;
1122  ll_bin_t latmaxbin=latlong_to_bin(radians_to_latlong(latmax))-errorlogs->file.latzero;
1123  ll_bin_t lonminbin=latlong_to_bin(radians_to_latlong(lonmin))-errorlogs->file.lonzero;
1124  ll_bin_t lonmaxbin=latlong_to_bin(radians_to_latlong(lonmax))-errorlogs->file.lonzero;
1125  ll_bin_t latb,lonb;
1126  index_t i,index1,index2;
1127 
1128  /* Loop through all of the error logs. */
1129 
1130  for(latb=latminbin;latb<=latmaxbin;latb++)
1131     for(lonb=lonminbin;lonb<=lonmaxbin;lonb++)
1132       {
1133        ll_bin2_t llbin=lonb*errorlogs->file.latbins+latb;
1134 
1135        if(llbin<0 || llbin>(errorlogs->file.latbins*errorlogs->file.lonbins))
1136           continue;
1137 
1138        index1=LookupErrorLogOffset(errorlogs,llbin);
1139        index2=LookupErrorLogOffset(errorlogs,llbin+1);
1140 
1141        if(index2>errorlogs->file.number_geo)
1142           index2=errorlogs->file.number_geo;
1143 
1144        for(i=index1;i<index2;i++)
1145          {
1146           ErrorLog *errorlogp=LookupErrorLog(errorlogs,i,1);
1147 
1148           double lat=latlong_to_radians(bin_to_latlong(errorlogs->file.latzero+latb)+off_to_latlong(errorlogp->latoffset));
1149           double lon=latlong_to_radians(bin_to_latlong(errorlogs->file.lonzero+lonb)+off_to_latlong(errorlogp->lonoffset));
1150 
1151           if(lat>latmin && lat<latmax && lon>lonmin && lon<lonmax)
1152              printf("errorlog%"Pindex_t" %.6f %.6f\n",i,radians_to_degrees(lat),radians_to_degrees(lon));
1153          }
1154       }
1155 }
1156