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 176 - (hide annotations) (download) (as text)
Thu May 14 18:02:30 2009 UTC (15 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 15136 byte(s)
Replace ~0 or 0 with NO_NODE value for "no node" condition.

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

Properties

Name Value
cvs:description Extended segments functions.