Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/nodes.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 99 - (hide annotations) (download) (as text)
Wed Feb 4 18:23:33 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 15122 byte(s)
Sort the nodes geographically and take coordinates as command line arguments.

1 amb 2 /***************************************
2 amb 99 $Header: /home/amb/CVS/routino/src/nodes.c,v 1.17 2009-02-04 18:23:32 amb Exp $
3 amb 2
4     Node data type functions.
5     ******************/ /******************
6     Written by Andrew M. Bishop
7    
8 amb 4 This file Copyright 2008,2009 Andrew M. Bishop
9 amb 2 It may be distributed under the GNU Public License, version 2, or
10     any higher version. See section COPYING of the GNU Public license
11     for conditions under which this file may be redistributed.
12     ***************************************/
13    
14    
15 amb 8 #include <assert.h>
16 amb 2 #include <stdlib.h>
17    
18     #include "functions.h"
19 amb 17 #include "nodes.h"
20 amb 2
21    
22 amb 96 /* Constants */
23    
24     /*+ The array size increment for nodes - expect ~8,000,000 nodes. +*/
25     #define INCREMENT_NODES 1024*1024
26    
27 amb 99 /*+ The latitude and longitude conversion factor from float to integer. +*/
28     #define LAT_LONG_SCALE (1024*1024)
29 amb 96
30 amb 99 /*+ The latitude and longitude integer range within each bin. +*/
31     #define LAT_LONG_BIN 65536
32    
33     /*+ The latitude and longitude number of bins per degree. +*/
34     #define LAT_LONG_DEGBIN (LAT_LONG_SCALE/LAT_LONG_BIN)
35    
36    
37 amb 17 /* Functions */
38 amb 2
39 amb 99 static int sort_by_id(NodeX **a,NodeX **b);
40     static int sort_by_lat_long(NodeX *a,NodeX *b);
41 amb 2
42 amb 8
43 amb 17 /*++++++++++++++++++++++++++++++++++++++
44 amb 2 Load in a node list from a file.
45    
46 amb 19 Nodes* LoadNodeList Returns the node list.
47 amb 17
48 amb 2 const char *filename The name of the file to load.
49     ++++++++++++++++++++++++++++++++++++++*/
50    
51 amb 19 Nodes *LoadNodeList(const char *filename)
52 amb 2 {
53 amb 88 void *data;
54     Nodes *nodes;
55    
56     nodes=(Nodes*)malloc(sizeof(Nodes));
57    
58     data=MapFile(filename);
59    
60     /* Copy the Nodes structure from the loaded data */
61    
62     *nodes=*((Nodes*)data);
63    
64     /* Adjust the pointers in the Nodes structure. */
65    
66 amb 99 nodes->data=data;
67     nodes->offsets=(index_t*)(data+(off_t)nodes->offsets);
68 amb 88 nodes->nodes=(Node*)(data+(off_t)nodes->nodes);
69    
70     return(nodes);
71 amb 2 }
72    
73    
74     /*++++++++++++++++++++++++++++++++++++++
75 amb 99 Find a node given its latitude and longitude.
76    
77     Node *FindNode Returns the node.
78    
79     Nodes* nodes The set of nodes to search.
80    
81     float latitude The latitude to look for.
82    
83     float longitude The longitude to look for.
84     ++++++++++++++++++++++++++++++++++++++*/
85    
86     Node *FindNode(Nodes* nodes,float latitude,float longitude)
87     {
88     int32_t latbin=(int32_t)((latitude-nodes->latzero)*LAT_LONG_DEGBIN);
89     int32_t lonbin=(int32_t)((longitude-nodes->lonzero)*LAT_LONG_DEGBIN);
90     int llbin=lonbin*nodes->latbins+latbin;
91     int i,best;
92     float distance=1000000;
93    
94     for(i=nodes->offsets[llbin];i<nodes->offsets[llbin+1];i++)
95     {
96     float lat=nodes->latzero+(double)latbin/(double)LAT_LONG_DEGBIN+(double)nodes->nodes[i].latoffset/(double)LAT_LONG_SCALE;
97     float lon=nodes->lonzero+(double)lonbin/(double)LAT_LONG_DEGBIN+(double)nodes->nodes[i].lonoffset/(double)LAT_LONG_SCALE;
98    
99     float dist=Distance(lat,lon,latitude,longitude);
100    
101     if(dist<distance)
102     {best=i; distance=dist;}
103     }
104    
105     return(&nodes->nodes[best]);
106     }
107    
108    
109     /*++++++++++++++++++++++++++++++++++++++
110     Get the latitude and longitude associated with a node.
111    
112     Nodes *nodes The set of nodes.
113    
114     Node *node The node.
115    
116     float *latitude Returns the latitude.
117    
118     float *longitude Returns the logitude.
119     ++++++++++++++++++++++++++++++++++++++*/
120    
121     void GetLatLong(Nodes *nodes,Node *node,float *latitude,float *longitude)
122     {
123     index_t index=IndexNode(nodes,node);
124     int latbin=-1,lonbin=-1;
125     int start,end,mid;
126    
127     /* Binary search - search key closest below is required.
128     *
129     * # <- start | Check mid and move start or end if it doesn't match
130     * # |
131     * # | Since an inexact match is wanted we must set end=mid-1
132     * # <- mid | or start=mid because we know that mid doesn't match.
133     * # |
134     * # | Eventually either end=start or end=start+1 and one of
135     * # <- end | start or end is the wanted one.
136     */
137    
138     /* Search for longitude */
139    
140     start=0;
141     end=nodes->lonbins-1;
142    
143     do
144     {
145     mid=(start+end)/2; /* Choose mid point */
146    
147     if(nodes->offsets[nodes->latbins*mid]<index) /* Mid point is too low */
148     start=mid;
149     else if(nodes->offsets[nodes->latbins*mid]>index) /* Mid point is too high */
150     end=mid-1;
151     else /* Mid point is correct */
152     {lonbin=mid;break;}
153     }
154     while((end-start)>1);
155    
156     if(lonbin==-1)
157     {
158     if(nodes->offsets[nodes->latbins*end]>index)
159     lonbin=start;
160     else
161     lonbin=end;
162     }
163    
164     while(lonbin<nodes->lonbins && nodes->offsets[lonbin*nodes->latbins]==nodes->offsets[(lonbin+1)*nodes->latbins])
165     lonbin++;
166    
167     /* Search for latitude */
168    
169     start=0;
170     end=nodes->latbins-1;
171    
172     do
173     {
174     mid=(start+end)/2; /* Choose mid point */
175    
176     if(nodes->offsets[lonbin*nodes->latbins+mid]<index) /* Mid point is too low */
177     start=mid;
178     else if(nodes->offsets[lonbin*nodes->latbins+mid]>index) /* Mid point is too high */
179     end=mid-1;
180     else /* Mid point is correct */
181     {latbin=mid;break;}
182     }
183     while((end-start)>1);
184    
185     if(latbin==-1)
186     {
187     if(nodes->offsets[lonbin*nodes->latbins+end]>index)
188     latbin=start;
189     else
190     latbin=end;
191     }
192    
193     while(latbin<nodes->latbins && nodes->offsets[lonbin*nodes->latbins+latbin]==nodes->offsets[lonbin*nodes->latbins+latbin+1])
194     latbin++;
195    
196     /* Return the values */
197    
198     *latitude =nodes->latzero+(double)latbin/(double)LAT_LONG_DEGBIN+(double)node->latoffset/(double)LAT_LONG_SCALE;
199     *longitude=nodes->lonzero+(double)lonbin/(double)LAT_LONG_DEGBIN+(double)node->lonoffset/(double)LAT_LONG_SCALE;
200     }
201    
202    
203     /*++++++++++++++++++++++++++++++++++++++
204 amb 97 Allocate a new node list.
205    
206     NodesX *NewNodeList Returns the node list.
207     ++++++++++++++++++++++++++++++++++++++*/
208    
209     NodesX *NewNodeList(void)
210     {
211     NodesX *nodesx;
212    
213     nodesx=(NodesX*)malloc(sizeof(NodesX));
214    
215     nodesx->alloced=INCREMENT_NODES;
216     nodesx->number=0;
217     nodesx->sorted=0;
218    
219 amb 99 nodesx->gdata=(NodeX*)malloc(nodesx->alloced*sizeof(NodeX));
220     nodesx->idata=NULL;
221 amb 97
222     return(nodesx);
223     }
224    
225    
226     /*++++++++++++++++++++++++++++++++++++++
227 amb 2 Save the node list to a file.
228    
229 amb 97 NodesX* nodesx The set of nodes to save.
230 amb 17
231 amb 2 const char *filename The name of the file to save.
232     ++++++++++++++++++++++++++++++++++++++*/
233    
234 amb 97 void SaveNodeList(NodesX* nodesx,const char *filename)
235 amb 2 {
236 amb 88 int i;
237     int fd;
238     Nodes *nodes=calloc(1,sizeof(Nodes));
239 amb 99 index_t *offsets;
240     float lat_min,lat_max,lon_min,lon_max;
241     int latbins,lonbins,latlonbin;
242 amb 2
243 amb 97 assert(nodesx->sorted); /* Must be sorted */
244 amb 2
245 amb 99 /* Work out the offsets (careful with the rounding) */
246    
247     lat_min=-180.0+(float)((int32_t)((180.0+nodesx->lat_min)*LAT_LONG_DEGBIN))/LAT_LONG_DEGBIN;
248     lon_min=-180.0+(float)((int32_t)((180.0+nodesx->lon_min)*LAT_LONG_DEGBIN))/LAT_LONG_DEGBIN;
249     lat_max=-180.0+(float)((int32_t)((180.0+nodesx->lat_max)*LAT_LONG_DEGBIN+1))/LAT_LONG_DEGBIN;
250     lon_max=-180.0+(float)((int32_t)((180.0+nodesx->lon_max)*LAT_LONG_DEGBIN+1))/LAT_LONG_DEGBIN;
251    
252     latbins=(lat_max-lat_min)*LAT_LONG_DEGBIN;
253     lonbins=(lon_max-lon_min)*LAT_LONG_DEGBIN;
254    
255     offsets=malloc((latbins*lonbins+1)*sizeof(index_t));
256    
257     latlonbin=0;
258    
259     for(i=0;i<nodesx->number;i++)
260     {
261     int32_t latbin=(int32_t)((nodesx->gdata[i].latitude-lat_min)*LAT_LONG_DEGBIN);
262     int32_t lonbin=(int32_t)((nodesx->gdata[i].longitude-lon_min)*LAT_LONG_DEGBIN);
263     int llbin=lonbin*latbins+latbin;
264    
265     for(;latlonbin<=llbin;latlonbin++)
266     offsets[latlonbin]=i;
267     }
268    
269     for(;latlonbin<=(latbins*lonbins);latlonbin++)
270     offsets[latlonbin]=nodesx->number;
271    
272 amb 88 /* Fill in a Nodes structure with the offset of the real data in the file after
273     the Node structure itself. */
274    
275 amb 97 nodes->number=nodesx->number;
276 amb 99
277     nodes->latbins=latbins;
278     nodes->lonbins=lonbins;
279    
280     nodes->latzero=lat_min;
281     nodes->lonzero=lon_min;
282    
283 amb 88 nodes->data=NULL;
284 amb 99 nodes->offsets=(void*)sizeof(Nodes);
285     nodes->nodes=(void*)sizeof(Nodes)+(latbins*lonbins+1)*sizeof(index_t);
286 amb 88
287     /* Write out the Nodes structure and then the real data. */
288    
289     fd=OpenFile(filename);
290    
291 amb 97 WriteFile(fd,nodes,sizeof(Nodes));
292 amb 88
293 amb 99 WriteFile(fd,offsets,(latbins*lonbins+1)*sizeof(index_t));
294    
295 amb 97 for(i=0;i<nodesx->number;i++)
296 amb 99 WriteFile(fd,&nodesx->gdata[i].node,sizeof(Node));
297 amb 88
298 amb 97 CloseFile(fd);
299 amb 88
300 amb 89 /* Free the fake Nodes */
301 amb 88
302 amb 19 free(nodes);
303 amb 99 free(offsets);
304 amb 2 }
305    
306    
307     /*++++++++++++++++++++++++++++++++++++++
308     Find a particular node.
309    
310 amb 98 NodeX *FindNodeX Returns the extended node with the specified id.
311 amb 2
312 amb 97 NodesX* nodesx The set of nodes to process.
313 amb 17
314 amb 2 node_t id The node id to look for.
315     ++++++++++++++++++++++++++++++++++++++*/
316    
317 amb 98 NodeX *FindNodeX(NodesX* nodesx,node_t id)
318 amb 2 {
319 amb 88 int start=0;
320 amb 97 int end=nodesx->number-1;
321 amb 2 int mid;
322    
323     /* Binary search - search key exact match only is required.
324     *
325     * # <- start | Check mid and move start or end if it doesn't match
326     * # |
327     * # | Since an exact match is wanted we can set end=mid-1
328     * # <- mid | or start=mid+1 because we know that mid doesn't match.
329     * # |
330     * # | Eventually either end=start or end=start+1 and one of
331     * # <- end | start or end is the wanted one.
332     */
333    
334 amb 99 if(end<start) /* There are no nodes */
335 amb 89 return(NULL);
336 amb 99 else if(id<nodesx->idata[start]->id) /* Check key is not before start */
337 amb 89 return(NULL);
338 amb 99 else if(id>nodesx->idata[end]->id) /* Check key is not after end */
339 amb 89 return(NULL);
340 amb 2 else
341     {
342     do
343     {
344 amb 99 mid=(start+end)/2; /* Choose mid point */
345 amb 2
346 amb 99 if(nodesx->idata[mid]->id<id) /* Mid point is too low */
347 amb 2 start=mid+1;
348 amb 99 else if(nodesx->idata[mid]->id>id) /* Mid point is too high */
349 amb 2 end=mid-1;
350 amb 99 else /* Mid point is correct */
351     return(nodesx->idata[mid]);
352 amb 2 }
353     while((end-start)>1);
354    
355 amb 99 if(nodesx->idata[start]->id==id) /* Start is correct */
356     return(nodesx->idata[start]);
357 amb 2
358 amb 99 if(nodesx->idata[end]->id==id) /* End is correct */
359     return(nodesx->idata[end]);
360 amb 2 }
361    
362 amb 89 return(NULL);
363 amb 2 }
364    
365    
366     /*++++++++++++++++++++++++++++++++++++++
367     Append a node to a newly created node list (unsorted).
368    
369 amb 98 Node *AppendNode Return a pointer to the new node.
370 amb 32
371 amb 97 NodesX* nodesx The set of nodes to process.
372 amb 17
373 amb 2 node_t id The node identification.
374    
375 amb 98 float latitude The latitude of the node.
376 amb 2
377 amb 98 float longitude The longitude of the node.
378 amb 2 ++++++++++++++++++++++++++++++++++++++*/
379    
380 amb 98 Node *AppendNode(NodesX* nodesx,node_t id,float latitude,float longitude)
381 amb 2 {
382 amb 19 /* Check that the array has enough space. */
383 amb 8
384 amb 97 if(nodesx->number==nodesx->alloced)
385 amb 4 {
386 amb 97 nodesx->alloced+=INCREMENT_NODES;
387 amb 4
388 amb 99 nodesx->gdata=(NodeX*)realloc((void*)nodesx->gdata,nodesx->alloced*sizeof(NodeX));
389 amb 4 }
390    
391     /* Insert the node */
392    
393 amb 99 nodesx->gdata[nodesx->number].id=id;
394     nodesx->gdata[nodesx->number].super=0;
395     nodesx->gdata[nodesx->number].latitude=latitude;
396     nodesx->gdata[nodesx->number].longitude=longitude;
397 amb 2
398 amb 97 nodesx->number++;
399 amb 2
400 amb 97 nodesx->sorted=0;
401 amb 32
402 amb 99 return(&nodesx->gdata[nodesx->number-1].node);
403 amb 2 }
404    
405    
406     /*++++++++++++++++++++++++++++++++++++++
407     Sort the node list.
408 amb 17
409 amb 97 NodesX* nodesx The set of nodes to process.
410 amb 2 ++++++++++++++++++++++++++++++++++++++*/
411    
412 amb 97 void SortNodeList(NodesX* nodesx)
413 amb 2 {
414 amb 99 int i;
415 amb 40
416 amb 99 qsort(nodesx->gdata,nodesx->number,sizeof(NodeX),(int (*)(const void*,const void*))sort_by_lat_long);
417    
418     while(nodesx->gdata[nodesx->number-1].id==~0)
419 amb 97 nodesx->number--;
420 amb 8
421 amb 99 nodesx->idata=malloc(nodesx->number*sizeof(NodeX*));
422    
423     nodesx->lat_min=90;
424     nodesx->lat_max=-90;
425     nodesx->lon_min=180;
426     nodesx->lon_max=-180;
427    
428     for(i=0;i<nodesx->number;i++)
429     {
430     int32_t lat=(int32_t)(nodesx->gdata[i].latitude*LAT_LONG_SCALE);
431     int32_t lon=(int32_t)(nodesx->gdata[i].longitude*LAT_LONG_SCALE);
432    
433     nodesx->gdata[i].node.latoffset=lat%LAT_LONG_BIN;
434     nodesx->gdata[i].node.lonoffset=lon%LAT_LONG_BIN;
435    
436     if(nodesx->gdata[i].latitude<nodesx->lat_min)
437     nodesx->lat_min=nodesx->gdata[i].latitude;
438     if(nodesx->gdata[i].latitude>nodesx->lat_max)
439     nodesx->lat_max=nodesx->gdata[i].latitude;
440     if(nodesx->gdata[i].longitude<nodesx->lon_min)
441     nodesx->lon_min=nodesx->gdata[i].longitude;
442     if(nodesx->gdata[i].longitude>nodesx->lon_max)
443     nodesx->lon_max=nodesx->gdata[i].longitude;
444    
445     nodesx->idata[i]=&nodesx->gdata[i];
446     }
447    
448     qsort(nodesx->idata,nodesx->number,sizeof(NodeX*),(int (*)(const void*,const void*))sort_by_id);
449    
450 amb 97 nodesx->sorted=1;
451 amb 2 }
452    
453    
454     /*++++++++++++++++++++++++++++++++++++++
455     Sort the nodes into id order.
456    
457     int sort_by_id Returns the comparison of the id fields.
458    
459 amb 99 NodeX **a The first Node.
460    
461     NodeX **b The second Node.
462     ++++++++++++++++++++++++++++++++++++++*/
463    
464     static int sort_by_id(NodeX **a,NodeX **b)
465     {
466     node_t a_id=(*a)->id;
467     node_t b_id=(*b)->id;
468    
469     if(a_id<b_id)
470     return(-1);
471     else
472     return(1);
473     }
474    
475    
476     /*++++++++++++++++++++++++++++++++++++++
477     Sort the nodes into latitude and longitude order.
478    
479     int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
480    
481 amb 97 NodeX *a The first Node.
482 amb 2
483 amb 97 NodeX *b The second Node.
484 amb 2 ++++++++++++++++++++++++++++++++++++++*/
485    
486 amb 99 static int sort_by_lat_long(NodeX *a,NodeX *b)
487 amb 2 {
488     node_t a_id=a->id;
489     node_t b_id=b->id;
490 amb 99 int32_t a_lat=(int32_t)(a->latitude*LAT_LONG_DEGBIN);
491     int32_t a_lon=(int32_t)(a->longitude*LAT_LONG_DEGBIN);
492     int32_t b_lat=(int32_t)(b->latitude*LAT_LONG_DEGBIN);
493     int32_t b_lon=(int32_t)(b->longitude*LAT_LONG_DEGBIN);
494 amb 2
495 amb 99 if(a_id==~0)
496     return(1);
497     if(b_id==~0)
498 amb 40 return(-1);
499 amb 99
500     if(a_lon<b_lon)
501     return(-1);
502     else if(a_lon>b_lon)
503     return(1);
504 amb 88 else
505 amb 99 {
506     if(a_lat<b_lat)
507     return(-1);
508     else if(a_lat>b_lat)
509     return(1);
510     else
511     return(0);
512     }
513 amb 2 }
514 amb 40
515    
516     /*++++++++++++++++++++++++++++++++++++++
517 amb 88 Remove any nodes that are not part of a highway.
518 amb 40
519 amb 97 NodesX *nodesx The complete node list.
520 amb 40
521 amb 97 SegmentsX *segmentsx The list of segments.
522 amb 40 ++++++++++++++++++++++++++++++++++++++*/
523    
524 amb 97 void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx)
525 amb 40 {
526     int i;
527 amb 66 int highway=0,nothighway=0;
528 amb 40
529 amb 97 for(i=0;i<nodesx->number;i++)
530 amb 40 {
531 amb 99 if(FindFirstSegmentX(segmentsx,nodesx->gdata[i].id))
532 amb 89 highway++;
533     else
534 amb 40 {
535 amb 99 nodesx->gdata[i].id=~0;
536 amb 88 nothighway++;
537 amb 40 }
538    
539     if(!((i+1)%10000))
540     {
541 amb 66 printf("\rChecking: Nodes=%d Highway=%d not-Highway=%d",i+1,highway,nothighway);
542 amb 40 fflush(stdout);
543     }
544     }
545    
546 amb 97 printf("\rChecked: Nodes=%d Highway=%d not-Highway=%d \n",nodesx->number,highway,nothighway);
547 amb 40 fflush(stdout);
548 amb 88 }
549 amb 66
550 amb 88
551     /*++++++++++++++++++++++++++++++++++++++
552     Fix the node indexes to the segments.
553    
554 amb 97 NodesX* nodesx The set of nodes to process.
555 amb 88
556 amb 97 SegmentsX *segmentsx The list of segments to use.
557 amb 90
558     int iteration The current super-node / super-segment iteration number.
559 amb 88 ++++++++++++++++++++++++++++++++++++++*/
560    
561 amb 97 void FixupNodes(NodesX *nodesx,SegmentsX* segmentsx,int iteration)
562 amb 88 {
563     int i;
564    
565 amb 97 assert(nodesx->sorted); /* Must be sorted */
566 amb 88
567 amb 97 for(i=0;i<nodesx->number;i++)
568 amb 88 {
569 amb 99 SegmentX *firstseg=FindFirstSegmentX(segmentsx,nodesx->gdata[i].id);
570 amb 88
571 amb 99 nodesx->gdata[i].node.firstseg=IndexSegmentX(segmentsx,firstseg);
572 amb 88
573 amb 99 if(nodesx->gdata[i].super==iteration)
574     nodesx->gdata[i].node.firstseg|=SUPER_FLAG;
575 amb 90
576 amb 88 if(!((i+1)%10000))
577     {
578     printf("\rFixing Nodes: Nodes=%d",i+1);
579     fflush(stdout);
580     }
581     }
582    
583 amb 97 printf("\rFixed Nodes: Nodes=%d \n",nodesx->number);
584 amb 88 fflush(stdout);
585 amb 40 }

Properties

Name Value
cvs:description Node data type.