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 209 - (hide annotations) (download) (as text)
Tue Jun 30 18:32:42 2009 UTC (15 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 16313 byte(s)
Remove the Segment structure from the SegmentX structure to save memory.

1 amb 110 /***************************************
2 amb 209 $Header: /home/amb/CVS/routino/src/segmentsx.c,v 1.15 2009-06-30 18:32:42 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 amb 204 static int sort_by_id_and_distance(SegmentX **a,SegmentX **b);
47 amb 110
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 amb 209 segmentsx->number=0;
65 amb 110
66     segmentsx->xdata=(SegmentX*)malloc(segmentsx->alloced*sizeof(SegmentX));
67 amb 206 segmentsx->ndata=NULL;
68 amb 110
69 amb 209 segmentsx->sdata=NULL;
70    
71 amb 110 return(segmentsx);
72     }
73    
74    
75     /*++++++++++++++++++++++++++++++++++++++
76     Free a segment list.
77    
78     SegmentsX *segmentsx The list to be freed.
79     ++++++++++++++++++++++++++++++++++++++*/
80    
81     void FreeSegmentList(SegmentsX *segmentsx)
82     {
83 amb 209 if(segmentsx->sdata)
84     free(segmentsx->sdata);
85 amb 110 free(segmentsx->xdata);
86 amb 206 free(segmentsx->ndata);
87 amb 110 free(segmentsx);
88     }
89    
90    
91     /*++++++++++++++++++++++++++++++++++++++
92     Save the segment list to a file.
93    
94     SegmentsX* segmentsx The set of segments to save.
95    
96     const char *filename The name of the file to save.
97     ++++++++++++++++++++++++++++++++++++++*/
98    
99     void SaveSegmentList(SegmentsX* segmentsx,const char *filename)
100     {
101     int i;
102     int fd;
103     Segments *segments=calloc(1,sizeof(Segments));
104    
105     assert(segmentsx->sorted); /* Must be sorted */
106    
107     /* Fill in a Segments structure with the offset of the real data in the file after
108     the Segment structure itself. */
109    
110     segments->number=segmentsx->number;
111     segments->data=NULL;
112     segments->segments=(void*)sizeof(Segments);
113    
114     /* Write out the Segments structure and then the real data. */
115    
116     fd=OpenFile(filename);
117    
118     WriteFile(fd,segments,sizeof(Segments));
119    
120 amb 203 for(i=0;i<segments->number;i++)
121 amb 132 {
122 amb 209 WriteFile(fd,&segmentsx->sdata[i],sizeof(Segment));
123 amb 110
124 amb 132 if(!((i+1)%10000))
125     {
126     printf("\rWriting Segments: Segments=%d",i+1);
127     fflush(stdout);
128     }
129     }
130    
131 amb 203 printf("\rWrote Segments: Segments=%d \n",segments->number);
132 amb 132 fflush(stdout);
133    
134 amb 110 CloseFile(fd);
135    
136     /* Free the fake Segments */
137    
138     free(segments);
139     }
140    
141    
142     /*++++++++++++++++++++++++++++++++++++++
143     Find the first segment with a particular starting node.
144    
145     SegmentX **FindFirstSegmentX Returns a pointer to the first extended segment with the specified id.
146    
147     SegmentsX* segmentsx The set of segments to process.
148    
149     node_t node The node to look for.
150     ++++++++++++++++++++++++++++++++++++++*/
151    
152     SegmentX **FindFirstSegmentX(SegmentsX* segmentsx,node_t node)
153     {
154     int start=0;
155     int end=segmentsx->number-1;
156     int mid;
157     int found;
158    
159     assert(segmentsx->sorted); /* Must be sorted */
160    
161     /* Binary search - search key exact match only is required.
162     *
163     * # <- start | Check mid and move start or end if it doesn't match
164     * # |
165     * # | Since an exact match is wanted we can set end=mid-1
166     * # <- mid | or start=mid+1 because we know that mid doesn't match.
167     * # |
168     * # | Eventually either end=start or end=start+1 and one of
169     * # <- end | start or end is the wanted one.
170     */
171    
172     if(end<start) /* There are no nodes */
173     return(NULL);
174 amb 206 else if(node<segmentsx->ndata[start]->node1) /* Check key is not before start */
175 amb 110 return(NULL);
176 amb 206 else if(node>segmentsx->ndata[end]->node1) /* Check key is not after end */
177 amb 110 return(NULL);
178     else
179     {
180     do
181     {
182     mid=(start+end)/2; /* Choose mid point */
183    
184 amb 206 if(segmentsx->ndata[mid]->node1<node) /* Mid point is too low */
185 amb 110 start=mid;
186 amb 206 else if(segmentsx->ndata[mid]->node1>node) /* Mid point is too high */
187 amb 110 end=mid;
188     else /* Mid point is correct */
189     {found=mid; goto found;}
190     }
191     while((end-start)>1);
192    
193 amb 206 if(segmentsx->ndata[start]->node1==node) /* Start is correct */
194 amb 110 {found=start; goto found;}
195    
196 amb 206 if(segmentsx->ndata[end]->node1==node) /* End is correct */
197 amb 110 {found=end; goto found;}
198     }
199    
200     return(NULL);
201    
202     found:
203    
204 amb 206 while(found>0 && segmentsx->ndata[found-1]->node1==node)
205 amb 110 found--;
206    
207 amb 206 return(&segmentsx->ndata[found]);
208 amb 110 }
209    
210    
211     /*++++++++++++++++++++++++++++++++++++++
212     Find the next segment with a particular starting node.
213    
214     SegmentX **FindNextSegmentX Returns a pointer to the next segment with the same id.
215    
216     SegmentsX* segmentsx The set of segments to process.
217    
218     SegmentX **segmentx The current segment.
219     ++++++++++++++++++++++++++++++++++++++*/
220    
221     SegmentX **FindNextSegmentX(SegmentsX* segmentsx,SegmentX **segmentx)
222     {
223     SegmentX **next=segmentx+1;
224    
225 amb 206 if((next-segmentsx->ndata)==segmentsx->number)
226 amb 110 return(NULL);
227    
228     if((*next)->node1==(*segmentx)->node1)
229     return(next);
230    
231     return(NULL);
232     }
233    
234    
235     /*++++++++++++++++++++++++++++++++++++++
236     Append a segment to a segment list.
237    
238     SegmentsX* segmentsx The set of segments to process.
239    
240 amb 203 way_t way The way that the segment belongs to.
241    
242 amb 110 node_t node1 The first node in the segment.
243    
244     node_t node2 The second node in the segment.
245     ++++++++++++++++++++++++++++++++++++++*/
246    
247 amb 209 void AppendSegment(SegmentsX* segmentsx,way_t way,node_t node1,node_t node2,distance_t distance)
248 amb 110 {
249     /* Check that the array has enough space. */
250    
251     if(segmentsx->xnumber==segmentsx->alloced)
252     {
253     segmentsx->alloced+=INCREMENT_SEGMENTS;
254    
255     segmentsx->xdata=(SegmentX*)realloc((void*)segmentsx->xdata,segmentsx->alloced*sizeof(SegmentX));
256     }
257    
258     /* Insert the segment */
259    
260 amb 203 segmentsx->xdata[segmentsx->xnumber].way=way;
261 amb 110 segmentsx->xdata[segmentsx->xnumber].node1=node1;
262     segmentsx->xdata[segmentsx->xnumber].node2=node2;
263 amb 209 segmentsx->xdata[segmentsx->xnumber].distance=distance;
264 amb 110
265     segmentsx->xnumber++;
266    
267     segmentsx->sorted=0;
268     }
269    
270    
271     /*++++++++++++++++++++++++++++++++++++++
272     Sort the segment list.
273    
274     SegmentsX* segmentsx The set of segments to process.
275     ++++++++++++++++++++++++++++++++++++++*/
276    
277     void SortSegmentList(SegmentsX* segmentsx)
278     {
279     int i;
280    
281 amb 132 printf("Sorting Segments"); fflush(stdout);
282    
283 amb 110 /* Allocate the arrays of pointers */
284    
285     if(segmentsx->sorted)
286 amb 206 segmentsx->ndata=realloc(segmentsx->ndata,segmentsx->xnumber*sizeof(SegmentX*));
287 amb 110 else
288 amb 206 segmentsx->ndata=malloc(segmentsx->xnumber*sizeof(SegmentX*));
289 amb 110
290     segmentsx->number=0;
291    
292     for(i=0;i<segmentsx->xnumber;i++)
293 amb 176 if(segmentsx->xdata[i].node1!=NO_NODE)
294 amb 110 {
295 amb 206 segmentsx->ndata[segmentsx->number]=&segmentsx->xdata[i];
296 amb 110 segmentsx->number++;
297     }
298    
299 amb 206 qsort(segmentsx->ndata,segmentsx->number,sizeof(SegmentX*),(int (*)(const void*,const void*))sort_by_id_and_distance);
300 amb 110
301     segmentsx->sorted=1;
302 amb 132
303     printf("\rSorted Segments \n"); fflush(stdout);
304 amb 110 }
305    
306    
307     /*++++++++++++++++++++++++++++++++++++++
308 amb 204 Sort the segments into id order and then distance order.
309 amb 110
310 amb 204 int sort_by_id_and_distance Returns the comparison of the node fields.
311 amb 110
312     SegmentX **a The first Segment.
313    
314     SegmentX **b The second Segment.
315     ++++++++++++++++++++++++++++++++++++++*/
316    
317 amb 204 static int sort_by_id_and_distance(SegmentX **a,SegmentX **b)
318 amb 110 {
319     node_t a_id1=(*a)->node1;
320     node_t b_id1=(*b)->node1;
321    
322     if(a_id1<b_id1)
323     return(-1);
324     else if(a_id1>b_id1)
325     return(1);
326     else /* if(a_id1==b_id1) */
327     {
328     node_t a_id2=(*a)->node2;
329     node_t b_id2=(*b)->node2;
330    
331     if(a_id2<b_id2)
332     return(-1);
333     else if(a_id2>b_id2)
334     return(1);
335     else
336     {
337 amb 209 distance_t a_distance=DISTANCE((*a)->distance);
338     distance_t b_distance=DISTANCE((*b)->distance);
339 amb 110
340     if(a_distance<b_distance)
341     return(-1);
342     else if(a_distance>b_distance)
343     return(1);
344     else
345     return(0);
346     }
347     }
348     }
349    
350    
351     /*++++++++++++++++++++++++++++++++++++++
352     Remove bad segments (zero length or duplicated).
353    
354 amb 195 NodesX *nodesx The nodes to check.
355    
356 amb 110 SegmentsX *segmentsx The segments to modify.
357     ++++++++++++++++++++++++++++++++++++++*/
358    
359 amb 204 void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
360 amb 110 {
361     int i;
362 amb 195 int duplicate=0,loop=0,missing=0;
363 amb 110
364     assert(segmentsx->sorted); /* Must be sorted */
365    
366     for(i=0;i<segmentsx->number;i++)
367     {
368 amb 206 if(i && segmentsx->ndata[i]->node1==segmentsx->ndata[i-1]->node1 &&
369     segmentsx->ndata[i]->node2==segmentsx->ndata[i-1]->node2)
370 amb 110 {
371     duplicate++;
372 amb 206 segmentsx->ndata[i-1]->node1=NO_NODE;
373 amb 110 }
374 amb 206 else if(segmentsx->ndata[i]->node1==segmentsx->ndata[i]->node2)
375 amb 110 {
376     loop++;
377 amb 206 segmentsx->ndata[i]->node1=NO_NODE;
378 amb 110 }
379 amb 206 else if(!FindNodeX(nodesx,segmentsx->ndata[i]->node1) ||
380     !FindNodeX(nodesx,segmentsx->ndata[i]->node2))
381 amb 195 {
382     missing++;
383 amb 206 segmentsx->ndata[i]->node1=NO_NODE;
384 amb 195 }
385 amb 110
386     if(!((i+1)%10000))
387     {
388 amb 195 printf("\rChecking: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",i+1,duplicate,loop,missing);
389 amb 110 fflush(stdout);
390     }
391     }
392    
393 amb 195 printf("\rChecked: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d \n",segmentsx->number,duplicate,loop,missing);
394 amb 110 fflush(stdout);
395     }
396    
397    
398     /*++++++++++++++++++++++++++++++++++++++
399     Measure the segments.
400    
401     SegmentsX* segmentsx The set of segments to process.
402    
403     NodesX *nodesx The list of nodes to use.
404     ++++++++++++++++++++++++++++++++++++++*/
405    
406     void MeasureSegments(SegmentsX* segmentsx,NodesX *nodesx)
407     {
408     int i;
409    
410     assert(segmentsx->sorted); /* Must be sorted */
411    
412     for(i=0;i<segmentsx->number;i++)
413     {
414 amb 206 NodeX *node1=FindNodeX(nodesx,segmentsx->ndata[i]->node1);
415     NodeX *node2=FindNodeX(nodesx,segmentsx->ndata[i]->node2);
416 amb 110
417     /* Set the distance but preserve the ONEWAY_* flags */
418    
419 amb 209 segmentsx->ndata[i]->distance|=DISTANCE(DistanceX(node1,node2));
420 amb 110
421     if(!((i+1)%10000))
422     {
423     printf("\rMeasuring Segments: Segments=%d",i+1);
424     fflush(stdout);
425     }
426     }
427    
428     printf("\rMeasured Segments: Segments=%d \n",segmentsx->number);
429     fflush(stdout);
430     }
431    
432    
433     /*++++++++++++++++++++++++++++++++++++++
434     Make the segments all point the same way (node1<node2).
435    
436     SegmentsX* segmentsx The set of segments to process.
437    
438     NodesX *nodesx The list of nodes to use.
439     ++++++++++++++++++++++++++++++++++++++*/
440    
441     void RotateSegments(SegmentsX* segmentsx,NodesX *nodesx)
442     {
443     int i,rotated=0;
444    
445     assert(segmentsx->sorted); /* Must be sorted */
446    
447     for(i=0;i<segmentsx->number;i++)
448     {
449 amb 206 if(segmentsx->ndata[i]->node1>segmentsx->ndata[i]->node2)
450 amb 110 {
451 amb 206 segmentsx->ndata[i]->node1^=segmentsx->ndata[i]->node2;
452     segmentsx->ndata[i]->node2^=segmentsx->ndata[i]->node1;
453     segmentsx->ndata[i]->node1^=segmentsx->ndata[i]->node2;
454 amb 110
455 amb 209 if(segmentsx->ndata[i]->distance&(ONEWAY_2TO1|ONEWAY_1TO2))
456     segmentsx->ndata[i]->distance^=ONEWAY_2TO1|ONEWAY_1TO2;
457 amb 110
458     rotated++;
459     }
460    
461     if(!((i+1)%10000))
462     {
463     printf("\rRotating Segments: Segments=%d Rotated=%d",i+1,rotated);
464     fflush(stdout);
465     }
466     }
467    
468     printf("\rRotated Segments: Segments=%d Rotated=%d \n",segmentsx->number,rotated);
469     fflush(stdout);
470     }
471    
472    
473     /*++++++++++++++++++++++++++++++++++++++
474     Mark the duplicate segments.
475    
476     SegmentsX* segmentsx The set of segments to process.
477    
478     NodesX *nodesx The list of nodes to use.
479    
480     WaysX *waysx The list of ways to use.
481     ++++++++++++++++++++++++++++++++++++++*/
482    
483     void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
484     {
485     int i,duplicate=0;
486    
487     assert(segmentsx->sorted); /* Must be sorted */
488    
489     for(i=1;i<segmentsx->number;i++)
490     {
491 amb 206 if(segmentsx->ndata[i]->node1==segmentsx->ndata[i-1]->node1 &&
492     segmentsx->ndata[i]->node2==segmentsx->ndata[i-1]->node2 &&
493 amb 209 segmentsx->ndata[i]->distance==segmentsx->ndata[i-1]->distance)
494 amb 110 {
495 amb 206 WayX *wayx1=FindWayX(waysx,segmentsx->ndata[i-1]->way);
496     WayX *wayx2=FindWayX(waysx,segmentsx->ndata[i ]->way);
497 amb 110
498 amb 204 if(!WaysCompare(wayx1->way,wayx2->way))
499 amb 110 {
500 amb 206 segmentsx->ndata[i-1]->node1=NO_NODE;
501     segmentsx->ndata[i-1]->node2=NO_NODE;
502 amb 110
503     duplicate++;
504     }
505     }
506    
507     if(!((i+1)%10000))
508     {
509     printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",i+1,duplicate);
510     fflush(stdout);
511     }
512     }
513    
514     printf("\rDeduplicated Segments: Segments=%d Duplicate=%d \n",segmentsx->number,duplicate);
515     fflush(stdout);
516     }
517    
518    
519     /*++++++++++++++++++++++++++++++++++++++
520 amb 209 Create the real segments data.
521    
522     SegmentsX* segmentsx The set of segments to use.
523    
524     WaysX* waysx The set of ways to use.
525     ++++++++++++++++++++++++++++++++++++++*/
526    
527     void CreateRealSegments(SegmentsX *segmentsx,WaysX *waysx)
528     {
529     int i;
530    
531     /* Allocate the memory */
532    
533     segmentsx->sdata=(Segment*)malloc(segmentsx->number*sizeof(Segment));
534    
535     /* Loop through and allocate. */
536    
537     for(i=0;i<segmentsx->number;i++)
538     {
539     WayX *wayx=FindWayX(waysx,segmentsx->ndata[i]->way);
540    
541     segmentsx->sdata[i].node1=0;
542     segmentsx->sdata[i].node2=0;
543     segmentsx->sdata[i].next2=NO_NODE;
544     segmentsx->sdata[i].way=wayx->way-waysx->wdata;
545     segmentsx->sdata[i].distance=segmentsx->ndata[i]->distance;
546    
547     if(!((i+1)%10000))
548     {
549     printf("\rCreating Real Segments: Segments=%d",i+1);
550     fflush(stdout);
551     }
552     }
553    
554     printf("\rCreating Real Segments: Segments=%d \n",segmentsx->number);
555     fflush(stdout);
556     }
557    
558    
559     /*++++++++++++++++++++++++++++++++++++++
560 amb 110 Assign the nodes indexes to the segments.
561    
562     SegmentsX* segmentsx The set of segments to process.
563    
564     NodesX *nodesx The list of nodes to use.
565     ++++++++++++++++++++++++++++++++++++++*/
566    
567     void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx)
568     {
569     int i;
570    
571     assert(segmentsx->sorted); /* Must be sorted */
572 amb 209 assert(segmentsx->sdata); /* Must have real segments */
573 amb 110 assert(nodesx->sorted); /* Must be sorted */
574    
575     /* Index the segments */
576    
577     for(i=0;i<nodesx->number;i++)
578     {
579 amb 209 index_t index=SEGMENT(nodesx->gdata[i]->node.firstseg);
580 amb 110
581     do
582     {
583 amb 209 if(segmentsx->ndata[index]->node1==nodesx->gdata[i]->id)
584 amb 110 {
585 amb 209 segmentsx->sdata[index].node1=i;
586 amb 110
587 amb 209 index++;
588 amb 128
589 amb 209 if(index>=segmentsx->number || segmentsx->ndata[index]->node1!=nodesx->gdata[i]->id)
590     break;
591 amb 110 }
592     else
593     {
594 amb 209 segmentsx->sdata[index].node2=i;
595 amb 110
596 amb 209 if(segmentsx->sdata[index].next2==NO_NODE)
597     break;
598 amb 110 else
599 amb 209 index=segmentsx->sdata[index].next2;
600 amb 110 }
601     }
602 amb 209 while(1);
603 amb 110
604     if(!((i+1)%10000))
605     {
606     printf("\rIndexing Nodes: Nodes=%d",i+1);
607     fflush(stdout);
608     }
609     }
610    
611     printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number);
612     fflush(stdout);
613     }
614    
615    
616     /*++++++++++++++++++++++++++++++++++++++
617     Calculate the distance between two nodes.
618    
619     distance_t DistanceX Returns the distance between the extended nodes.
620    
621     NodeX *nodex1 The starting node.
622    
623     NodeX *nodex2 The end node.
624     ++++++++++++++++++++++++++++++++++++++*/
625    
626     distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
627     {
628 amb 121 float dlon = nodex1->longitude - nodex2->longitude;
629     float dlat = nodex1->latitude - nodex2->latitude;
630 amb 110
631 amb 120 float a1,a2,a,sa,c,d;
632 amb 110
633     if(dlon==0 && dlat==0)
634     return 0;
635    
636 amb 120 a1 = sinf (dlat / 2);
637     a2 = sinf (dlon / 2);
638 amb 121 a = (a1 * a1) + cosf (nodex1->latitude) * cosf (nodex2->latitude) * a2 * a2;
639 amb 120 sa = sqrtf (a);
640 amb 110 if (sa <= 1.0)
641 amb 120 {c = 2 * asinf (sa);}
642 amb 110 else
643 amb 120 {c = 2 * asinf (1.0);}
644 amb 110 d = 6378.137 * c;
645    
646     return km_to_distance(d);
647     }

Properties

Name Value
cvs:description Extended segments functions.