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/segmentsx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 110 - (hide annotations) (download) (as text)
Sat Feb 7 15:57:42 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 14486 byte(s)
Initial revision

1 amb 110 /***************************************
2     $Header: /home/amb/CVS/routino/src/segmentsx.c,v 1.1 2009-02-07 15:56:50 amb Exp $
3    
4     Extended Segment data type functions.
5     ******************/ /******************
6     Written by Andrew M. Bishop
7    
8     This file Copyright 2008,2009 Andrew M. Bishop
9     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     #include <assert.h>
16     #include <math.h>
17     #include <string.h>
18     #include <stdlib.h>
19     #include <stdio.h>
20    
21     #include "types.h"
22     #include "functions.h"
23     #include "nodesx.h"
24     #include "segmentsx.h"
25     #include "waysx.h"
26    
27    
28     /* Constants */
29    
30     /*+ The array size increment for segments - expect ~8,000,000 segments. +*/
31     #define INCREMENT_SEGMENTS 1024*1024
32    
33    
34     /* Functions */
35    
36     static int sort_by_id(SegmentX **a,SegmentX **b);
37    
38    
39     /*++++++++++++++++++++++++++++++++++++++
40     Allocate a new segment list.
41    
42     SegmentsX *NewSegmentList Returns the segment list.
43     ++++++++++++++++++++++++++++++++++++++*/
44    
45     SegmentsX *NewSegmentList(void)
46     {
47     SegmentsX *segmentsx;
48    
49     segmentsx=(SegmentsX*)malloc(sizeof(SegmentsX));
50    
51     segmentsx->sorted=0;
52     segmentsx->alloced=INCREMENT_SEGMENTS;
53     segmentsx->xnumber=0;
54    
55     segmentsx->xdata=(SegmentX*)malloc(segmentsx->alloced*sizeof(SegmentX));
56     segmentsx->sdata=NULL;
57    
58     return(segmentsx);
59     }
60    
61    
62     /*++++++++++++++++++++++++++++++++++++++
63     Free a segment list.
64    
65     SegmentsX *segmentsx The list to be freed.
66     ++++++++++++++++++++++++++++++++++++++*/
67    
68     void FreeSegmentList(SegmentsX *segmentsx)
69     {
70     free(segmentsx->xdata);
71     free(segmentsx->sdata);
72     free(segmentsx);
73     }
74    
75    
76     /*++++++++++++++++++++++++++++++++++++++
77     Save the segment list to a file.
78    
79     SegmentsX* segmentsx The set of segments to save.
80    
81     const char *filename The name of the file to save.
82     ++++++++++++++++++++++++++++++++++++++*/
83    
84     void SaveSegmentList(SegmentsX* segmentsx,const char *filename)
85     {
86     int i;
87     int fd;
88     Segments *segments=calloc(1,sizeof(Segments));
89    
90     assert(segmentsx->sorted); /* Must be sorted */
91    
92     /* Fill in a Segments structure with the offset of the real data in the file after
93     the Segment structure itself. */
94    
95     segments->number=segmentsx->number;
96     segments->data=NULL;
97     segments->segments=(void*)sizeof(Segments);
98    
99     /* Write out the Segments structure and then the real data. */
100    
101     fd=OpenFile(filename);
102    
103     WriteFile(fd,segments,sizeof(Segments));
104    
105     for(i=0;i<segmentsx->number;i++)
106     WriteFile(fd,&segmentsx->sdata[i]->segment,sizeof(Segment));
107    
108     CloseFile(fd);
109    
110     /* Free the fake Segments */
111    
112     free(segments);
113     }
114    
115    
116     /*++++++++++++++++++++++++++++++++++++++
117     Find the first segment with a particular starting node.
118    
119     SegmentX **FindFirstSegmentX Returns a pointer to the first extended segment with the specified id.
120    
121     SegmentsX* segmentsx The set of segments to process.
122    
123     node_t node The node to look for.
124     ++++++++++++++++++++++++++++++++++++++*/
125    
126     SegmentX **FindFirstSegmentX(SegmentsX* segmentsx,node_t node)
127     {
128     int start=0;
129     int end=segmentsx->number-1;
130     int mid;
131     int found;
132    
133     assert(segmentsx->sorted); /* Must be sorted */
134    
135     /* Binary search - search key exact match only is required.
136     *
137     * # <- start | Check mid and move start or end if it doesn't match
138     * # |
139     * # | Since an exact match is wanted we can set end=mid-1
140     * # <- mid | or start=mid+1 because we know that mid doesn't match.
141     * # |
142     * # | Eventually either end=start or end=start+1 and one of
143     * # <- end | start or end is the wanted one.
144     */
145    
146     if(end<start) /* There are no nodes */
147     return(NULL);
148     else if(node<segmentsx->sdata[start]->node1) /* Check key is not before start */
149     return(NULL);
150     else if(node>segmentsx->sdata[end]->node1) /* Check key is not after end */
151     return(NULL);
152     else
153     {
154     do
155     {
156     mid=(start+end)/2; /* Choose mid point */
157    
158     if(segmentsx->sdata[mid]->node1<node) /* Mid point is too low */
159     start=mid;
160     else if(segmentsx->sdata[mid]->node1>node) /* Mid point is too high */
161     end=mid;
162     else /* Mid point is correct */
163     {found=mid; goto found;}
164     }
165     while((end-start)>1);
166    
167     if(segmentsx->sdata[start]->node1==node) /* Start is correct */
168     {found=start; goto found;}
169    
170     if(segmentsx->sdata[end]->node1==node) /* End is correct */
171     {found=end; goto found;}
172     }
173    
174     return(NULL);
175    
176     found:
177    
178     while(found>0 && segmentsx->sdata[found-1]->node1==node)
179     found--;
180    
181     return(&segmentsx->sdata[found]);
182     }
183    
184    
185     /*++++++++++++++++++++++++++++++++++++++
186     Find the next segment with a particular starting node.
187    
188     SegmentX **FindNextSegmentX Returns a pointer to the next segment with the same id.
189    
190     SegmentsX* segmentsx The set of segments to process.
191    
192     SegmentX **segmentx The current segment.
193     ++++++++++++++++++++++++++++++++++++++*/
194    
195     SegmentX **FindNextSegmentX(SegmentsX* segmentsx,SegmentX **segmentx)
196     {
197     SegmentX **next=segmentx+1;
198    
199     if((next-segmentsx->sdata)==segmentsx->number)
200     return(NULL);
201    
202     if((*next)->node1==(*segmentx)->node1)
203     return(next);
204    
205     return(NULL);
206     }
207    
208    
209     /*++++++++++++++++++++++++++++++++++++++
210     Append a segment to a segment list.
211    
212     Segment *AppendSegment Returns the appended segment.
213    
214     SegmentsX* segmentsx The set of segments to process.
215    
216     node_t node1 The first node in the segment.
217    
218     node_t node2 The second node in the segment.
219     ++++++++++++++++++++++++++++++++++++++*/
220    
221     Segment *AppendSegment(SegmentsX* segmentsx,node_t node1,node_t node2)
222     {
223     /* Check that the array has enough space. */
224    
225     if(segmentsx->xnumber==segmentsx->alloced)
226     {
227     segmentsx->alloced+=INCREMENT_SEGMENTS;
228    
229     segmentsx->xdata=(SegmentX*)realloc((void*)segmentsx->xdata,segmentsx->alloced*sizeof(SegmentX));
230     }
231    
232     /* Insert the segment */
233    
234     segmentsx->xdata[segmentsx->xnumber].node1=node1;
235     segmentsx->xdata[segmentsx->xnumber].node2=node2;
236    
237     memset(&segmentsx->xdata[segmentsx->xnumber].segment,0,sizeof(Segment));
238    
239     segmentsx->xnumber++;
240    
241     segmentsx->sorted=0;
242    
243     return(&segmentsx->xdata[segmentsx->xnumber-1].segment);
244     }
245    
246    
247     /*++++++++++++++++++++++++++++++++++++++
248     Sort the segment list.
249    
250     SegmentsX* segmentsx The set of segments to process.
251     ++++++++++++++++++++++++++++++++++++++*/
252    
253     void SortSegmentList(SegmentsX* segmentsx)
254     {
255     int i;
256    
257     /* Allocate the arrays of pointers */
258    
259     if(segmentsx->sorted)
260     segmentsx->sdata=realloc(segmentsx->sdata,segmentsx->xnumber*sizeof(SegmentX*));
261     else
262     segmentsx->sdata=malloc(segmentsx->xnumber*sizeof(SegmentX*));
263    
264     segmentsx->number=0;
265    
266     for(i=0;i<segmentsx->xnumber;i++)
267     if(segmentsx->xdata[i].node1!=~0)
268     {
269     segmentsx->sdata[segmentsx->number]=&segmentsx->xdata[i];
270     segmentsx->number++;
271     }
272    
273     qsort(segmentsx->sdata,segmentsx->number,sizeof(SegmentX*),(int (*)(const void*,const void*))sort_by_id);
274    
275     segmentsx->sorted=1;
276     }
277    
278    
279     /*++++++++++++++++++++++++++++++++++++++
280     Sort the segments into id order.
281    
282     int sort_by_id Returns the comparison of the node fields.
283    
284     SegmentX **a The first Segment.
285    
286     SegmentX **b The second Segment.
287     ++++++++++++++++++++++++++++++++++++++*/
288    
289     static int sort_by_id(SegmentX **a,SegmentX **b)
290     {
291     node_t a_id1=(*a)->node1;
292     node_t b_id1=(*b)->node1;
293    
294     if(a_id1<b_id1)
295     return(-1);
296     else if(a_id1>b_id1)
297     return(1);
298     else /* if(a_id1==b_id1) */
299     {
300     node_t a_id2=(*a)->node2;
301     node_t b_id2=(*b)->node2;
302    
303     if(a_id2<b_id2)
304     return(-1);
305     else if(a_id2>b_id2)
306     return(1);
307     else
308     {
309     distance_t a_distance=(*a)->segment.distance;
310     distance_t b_distance=(*b)->segment.distance;
311    
312     if(a_distance<b_distance)
313     return(-1);
314     else if(a_distance>b_distance)
315     return(1);
316     else
317     return(0);
318     }
319     }
320     }
321    
322    
323     /*++++++++++++++++++++++++++++++++++++++
324     Remove bad segments (zero length or duplicated).
325    
326     SegmentsX *segmentsx The segments to modify.
327     ++++++++++++++++++++++++++++++++++++++*/
328    
329     void RemoveBadSegments(SegmentsX *segmentsx)
330     {
331     int i;
332     int duplicate=0,loop=0;
333    
334     assert(segmentsx->sorted); /* Must be sorted */
335    
336     for(i=0;i<segmentsx->number;i++)
337     {
338     if(i && segmentsx->sdata[i]->node1==segmentsx->sdata[i-1]->node1 &&
339     segmentsx->sdata[i]->node2==segmentsx->sdata[i-1]->node2)
340     {
341     duplicate++;
342     segmentsx->sdata[i-1]->node1=~0;
343     }
344     else if(segmentsx->sdata[i]->node1==segmentsx->sdata[i]->node2)
345     {
346     loop++;
347     segmentsx->sdata[i]->node1=~0;
348     }
349    
350     if(!((i+1)%10000))
351     {
352     printf("\rChecking: Segments=%d Duplicate=%d Loop=%d",i+1,duplicate,loop);
353     fflush(stdout);
354     }
355     }
356    
357     printf("\rChecked: Segments=%d Duplicate=%d Loop=%d \n",segmentsx->number,duplicate,loop);
358     fflush(stdout);
359     }
360    
361    
362     /*++++++++++++++++++++++++++++++++++++++
363     Measure the segments.
364    
365     SegmentsX* segmentsx The set of segments to process.
366    
367     NodesX *nodesx The list of nodes to use.
368     ++++++++++++++++++++++++++++++++++++++*/
369    
370     void MeasureSegments(SegmentsX* segmentsx,NodesX *nodesx)
371     {
372     int i;
373    
374     assert(segmentsx->sorted); /* Must be sorted */
375    
376     for(i=0;i<segmentsx->number;i++)
377     {
378     NodeX *node1=FindNodeX(nodesx,segmentsx->sdata[i]->node1);
379     NodeX *node2=FindNodeX(nodesx,segmentsx->sdata[i]->node2);
380    
381     /* Set the distance but preserve the ONEWAY_* flags */
382    
383     segmentsx->sdata[i]->segment.distance|=DistanceX(node1,node2);
384    
385     if(!((i+1)%10000))
386     {
387     printf("\rMeasuring Segments: Segments=%d",i+1);
388     fflush(stdout);
389     }
390     }
391    
392     printf("\rMeasured Segments: Segments=%d \n",segmentsx->number);
393     fflush(stdout);
394     }
395    
396    
397     /*++++++++++++++++++++++++++++++++++++++
398     Make the segments all point the same way (node1<node2).
399    
400     SegmentsX* segmentsx The set of segments to process.
401    
402     NodesX *nodesx The list of nodes to use.
403     ++++++++++++++++++++++++++++++++++++++*/
404    
405     void RotateSegments(SegmentsX* segmentsx,NodesX *nodesx)
406     {
407     int i,rotated=0;
408    
409     assert(segmentsx->sorted); /* Must be sorted */
410    
411     for(i=0;i<segmentsx->number;i++)
412     {
413     if(segmentsx->sdata[i]->node1>segmentsx->sdata[i]->node2)
414     {
415     segmentsx->sdata[i]->node1^=segmentsx->sdata[i]->node2;
416     segmentsx->sdata[i]->node2^=segmentsx->sdata[i]->node1;
417     segmentsx->sdata[i]->node1^=segmentsx->sdata[i]->node2;
418    
419     if(segmentsx->sdata[i]->segment.distance&(ONEWAY_2TO1|ONEWAY_1TO2))
420     segmentsx->sdata[i]->segment.distance^=ONEWAY_2TO1|ONEWAY_1TO2;
421    
422     rotated++;
423     }
424    
425     if(!((i+1)%10000))
426     {
427     printf("\rRotating Segments: Segments=%d Rotated=%d",i+1,rotated);
428     fflush(stdout);
429     }
430     }
431    
432     printf("\rRotated Segments: Segments=%d Rotated=%d \n",segmentsx->number,rotated);
433     fflush(stdout);
434     }
435    
436    
437     /*++++++++++++++++++++++++++++++++++++++
438     Mark the duplicate segments.
439    
440     SegmentsX* segmentsx The set of segments to process.
441    
442     NodesX *nodesx The list of nodes to use.
443    
444     WaysX *waysx The list of ways to use.
445     ++++++++++++++++++++++++++++++++++++++*/
446    
447     void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
448     {
449     int i,duplicate=0;
450    
451     assert(segmentsx->sorted); /* Must be sorted */
452    
453     for(i=1;i<segmentsx->number;i++)
454     {
455     if(segmentsx->sdata[i]->node1==segmentsx->sdata[i-1]->node1 &&
456     segmentsx->sdata[i]->node2==segmentsx->sdata[i-1]->node2 &&
457     segmentsx->sdata[i]->segment.node1==segmentsx->sdata[i-1]->segment.node1 &&
458     segmentsx->sdata[i]->segment.node2==segmentsx->sdata[i-1]->segment.node2 &&
459     segmentsx->sdata[i]->segment.distance==segmentsx->sdata[i-1]->segment.distance)
460     {
461     WayX *wayx1=LookupWayX(waysx,segmentsx->sdata[i-1]->segment.way);
462     WayX *wayx2=LookupWayX(waysx,segmentsx->sdata[i]->segment.way);
463    
464     if(wayx1==wayx2 ||
465     (wayx1->way.type==wayx2->way.type && wayx1->way.allow==wayx2->way.allow && wayx1->way.limit==wayx2->way.limit))
466     {
467     segmentsx->sdata[i-1]->node1=~0;
468     segmentsx->sdata[i-1]->node2=~0;
469    
470     duplicate++;
471     }
472     }
473    
474     if(!((i+1)%10000))
475     {
476     printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",i+1,duplicate);
477     fflush(stdout);
478     }
479     }
480    
481     printf("\rDeduplicated Segments: Segments=%d Duplicate=%d \n",segmentsx->number,duplicate);
482     fflush(stdout);
483     }
484    
485    
486     /*++++++++++++++++++++++++++++++++++++++
487     Assign the nodes indexes to the segments.
488    
489     SegmentsX* segmentsx The set of segments to process.
490    
491     NodesX *nodesx The list of nodes to use.
492     ++++++++++++++++++++++++++++++++++++++*/
493    
494     void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx)
495     {
496     int i;
497    
498     assert(segmentsx->sorted); /* Must be sorted */
499     assert(nodesx->sorted); /* Must be sorted */
500    
501     /* Index the segments */
502    
503     for(i=0;i<nodesx->number;i++)
504     {
505     SegmentX *segmentx=LookupSegmentX(segmentsx,SEGMENT(nodesx->gdata[i]->node.firstseg));
506    
507     do
508     {
509     if(segmentx->node1==nodesx->gdata[i]->id)
510     {
511     segmentx->segment.node1|=i;
512    
513     if(segmentx->segment.next1==~0)
514     segmentx=NULL;
515     else
516     segmentx=LookupSegmentX(segmentsx,segmentx->segment.next1);
517     }
518     else
519     {
520     segmentx->segment.node2|=i;
521    
522     if(segmentx->segment.next2==~0)
523     segmentx=NULL;
524     else
525     segmentx=LookupSegmentX(segmentsx,segmentx->segment.next2);
526     }
527     }
528     while(segmentx);
529    
530     if(!((i+1)%10000))
531     {
532     printf("\rIndexing Nodes: Nodes=%d",i+1);
533     fflush(stdout);
534     }
535     }
536    
537     printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number);
538     fflush(stdout);
539     }
540    
541    
542     /*++++++++++++++++++++++++++++++++++++++
543     Calculate the distance between two nodes.
544    
545     distance_t DistanceX Returns the distance between the extended nodes.
546    
547     NodeX *nodex1 The starting node.
548    
549     NodeX *nodex2 The end node.
550     ++++++++++++++++++++++++++++++++++++++*/
551    
552     distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
553     {
554     double radiant = M_PI / 180;
555    
556     double dlon = radiant * (nodex1->longitude - nodex2->longitude);
557     double dlat = radiant * (nodex1->latitude - nodex2->latitude);
558    
559     double a1,a2,a,sa,c,d;
560    
561     if(dlon==0 && dlat==0)
562     return 0;
563    
564     a1 = sin (dlat / 2);
565     a2 = sin (dlon / 2);
566     a = (a1 * a1) + cos (nodex1->latitude * radiant) * cos (nodex2->latitude * radiant) * a2 * a2;
567     sa = sqrt (a);
568     if (sa <= 1.0)
569     {c = 2 * asin (sa);}
570     else
571     {c = 2 * asin (1.0);}
572     d = 6378.137 * c;
573    
574     return km_to_distance(d);
575     }

Properties

Name Value
cvs:description Extended segments functions.