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 310 - (hide annotations) (download) (as text)
Fri Dec 11 19:27:39 2009 UTC (15 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 24402 byte(s)
Added a new function to sort variable length data - simplifies the compacting of
ways, reduces memory usage potentially required for it and simplifies the code.

1 amb 110 /***************************************
2 amb 310 $Header: /home/amb/CVS/routino/src/segmentsx.c,v 1.47 2009-12-11 19:27:39 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 <stdlib.h>
28     #include <stdio.h>
29 amb 256 #include <string.h>
30 amb 110
31     #include "types.h"
32     #include "functions.h"
33     #include "nodesx.h"
34     #include "segmentsx.h"
35     #include "waysx.h"
36 amb 228 #include "nodes.h"
37     #include "segments.h"
38     #include "ways.h"
39 amb 110
40    
41 amb 275 /* Constants */
42    
43 amb 289 /*+ The amount of memory to use for sorting. +*/
44 amb 275 #define SORT_RAMSIZE (64*1024*1024)
45    
46 amb 256 /* Variables */
47 amb 110
48 amb 289 /*+ The command line '--slim' option. +*/
49 amb 256 extern int option_slim;
50 amb 289
51     /*+ The command line '--tmpdir' option or its default value. +*/
52 amb 284 extern char *option_tmpdirname;
53 amb 110
54 amb 228 /* Local Functions */
55 amb 110
56 amb 275 static int sort_by_id(SegmentX *a,SegmentX *b);
57    
58 amb 228 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2);
59 amb 110
60    
61     /*++++++++++++++++++++++++++++++++++++++
62     Allocate a new segment list.
63    
64     SegmentsX *NewSegmentList Returns the segment list.
65     ++++++++++++++++++++++++++++++++++++++*/
66    
67     SegmentsX *NewSegmentList(void)
68     {
69     SegmentsX *segmentsx;
70    
71 amb 213 segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX));
72 amb 110
73 amb 243 assert(segmentsx); /* Check calloc() worked */
74    
75 amb 284 segmentsx->filename=(char*)malloc(strlen(option_tmpdirname)+32);
76     sprintf(segmentsx->filename,"%s/segments.%p.tmp",option_tmpdirname,segmentsx);
77 amb 216
78 amb 256 segmentsx->fd=OpenFile(segmentsx->filename);
79    
80 amb 110 return(segmentsx);
81     }
82    
83    
84     /*++++++++++++++++++++++++++++++++++++++
85 amb 226 Free a segment list.
86 amb 110
87     SegmentsX *segmentsx The list to be freed.
88     ++++++++++++++++++++++++++++++++++++++*/
89    
90     void FreeSegmentList(SegmentsX *segmentsx)
91     {
92 amb 256 DeleteFile(segmentsx->filename);
93 amb 283 free(segmentsx->filename);
94 amb 256
95 amb 275 if(segmentsx->idata)
96     free(segmentsx->idata);
97 amb 226
98 amb 279 if(segmentsx->firstnode)
99     free(segmentsx->firstnode);
100    
101 amb 226 if(segmentsx->sdata)
102     free(segmentsx->sdata);
103    
104 amb 110 free(segmentsx);
105     }
106    
107    
108     /*++++++++++++++++++++++++++++++++++++++
109 amb 285 Append a single segment to a segment list.
110 amb 110
111 amb 285 SegmentsX* segmentsx The set of segments to process.
112 amb 110
113 amb 285 way_t way The way that the segment belongs to.
114    
115     node_t node1 The first node in the segment.
116    
117     node_t node2 The second node in the segment.
118    
119     distance_t distance The distance between the nodes (or just the flags).
120 amb 110 ++++++++++++++++++++++++++++++++++++++*/
121    
122 amb 285 void AppendSegment(SegmentsX* segmentsx,way_t way,node_t node1,node_t node2,distance_t distance)
123 amb 110 {
124 amb 285 SegmentX segmentx;
125 amb 110
126 amb 285 assert(!segmentsx->idata); /* Must not have idata filled in => unsorted */
127 amb 281
128 amb 285 segmentx.node1=node1;
129     segmentx.node2=node2;
130     segmentx.way=way;
131     segmentx.distance=distance;
132 amb 110
133 amb 285 WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
134 amb 281
135 amb 285 segmentsx->xnumber++;
136     }
137 amb 227
138 amb 281
139 amb 285 /*++++++++++++++++++++++++++++++++++++++
140     Sort the segment list.
141 amb 232
142 amb 285 SegmentsX* segmentsx The set of segments to process.
143     ++++++++++++++++++++++++++++++++++++++*/
144 amb 110
145 amb 285 void SortSegmentList(SegmentsX* segmentsx)
146     {
147     int fd;
148 amb 243
149 amb 285 /* Check the start conditions */
150 amb 243
151 amb 285 assert(!segmentsx->idata); /* Must not have idata filled in => unsorted */
152 amb 232
153 amb 285 /* Print the start message */
154 amb 232
155 amb 285 printf("Sorting Segments");
156     fflush(stdout);
157 amb 110
158 amb 285 /* Close the files and re-open them (finished appending) */
159 amb 110
160 amb 285 CloseFile(segmentsx->fd);
161     segmentsx->fd=ReOpenFile(segmentsx->filename);
162 amb 110
163 amb 285 DeleteFile(segmentsx->filename);
164 amb 110
165 amb 285 fd=OpenFile(segmentsx->filename);
166 amb 110
167 amb 285 /* Sort by node indexes */
168 amb 132
169 amb 310 filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),SORT_RAMSIZE,(int (*)(const void*,const void*))sort_by_id,NULL);
170 amb 285
171     segmentsx->number=segmentsx->xnumber;
172    
173     /* Close the files and re-open them */
174    
175     CloseFile(segmentsx->fd);
176 amb 281 CloseFile(fd);
177    
178 amb 285 segmentsx->fd=ReOpenFile(segmentsx->filename);
179    
180 amb 281 /* Print the final message */
181    
182 amb 285 printf("\rSorted Segments: Segments=%d\n",segmentsx->xnumber);
183 amb 132 fflush(stdout);
184 amb 110 }
185    
186    
187     /*++++++++++++++++++++++++++++++++++++++
188 amb 285 Sort the segments into id order (node1 then node2).
189 amb 110
190 amb 285 int sort_by_id Returns the comparison of the node fields.
191 amb 110
192 amb 285 SegmentX *a The first segment.
193 amb 110
194 amb 285 SegmentX *b The second segment.
195 amb 256 ++++++++++++++++++++++++++++++++++++++*/
196    
197 amb 285 static int sort_by_id(SegmentX *a,SegmentX *b)
198 amb 256 {
199 amb 285 node_t a_id1=a->node1;
200     node_t b_id1=b->node1;
201 amb 256
202 amb 285 if(a_id1<b_id1)
203     return(-1);
204     else if(a_id1>b_id1)
205     return(1);
206     else /* if(a_id1==b_id1) */
207 amb 256 {
208 amb 285 node_t a_id2=a->node2;
209     node_t b_id2=b->node2;
210 amb 256
211 amb 285 if(a_id2<b_id2)
212     return(-1);
213     else if(a_id2>b_id2)
214     return(1);
215     else
216     {
217     distance_t a_distance=a->distance;
218     distance_t b_distance=b->distance;
219 amb 256
220 amb 285 if(a_distance<b_distance)
221     return(-1);
222     else if(a_distance>b_distance)
223     return(1);
224     else
225     return(0);
226     }
227 amb 256 }
228     }
229    
230    
231     /*++++++++++++++++++++++++++++++++++++++
232 amb 275 Find the first segment index with a particular starting node.
233 amb 257
234 amb 275 index_t IndexFirstSegmentX Returns a pointer to the index of the first extended segment with the specified id.
235 amb 256
236     SegmentsX* segmentsx The set of segments to process.
237    
238 amb 110 node_t node The node to look for.
239     ++++++++++++++++++++++++++++++++++++++*/
240    
241 amb 275 index_t IndexFirstSegmentX(SegmentsX* segmentsx,node_t node)
242 amb 110 {
243     int start=0;
244     int end=segmentsx->number-1;
245     int mid;
246     int found;
247    
248 amb 280 /* Check if the first node index exists */
249    
250 amb 279 if(segmentsx->firstnode)
251     {
252     index_t index=segmentsx->firstnode[node];
253    
254     if(segmentsx->firstnode[node+1]==index)
255     return(NO_SEGMENT);
256    
257     return(index);
258     }
259    
260 amb 275 assert(segmentsx->idata); /* Must have idata filled in => sorted by node 1 */
261 amb 110
262     /* Binary search - search key exact match only is required.
263     *
264     * # <- start | Check mid and move start or end if it doesn't match
265     * # |
266     * # | Since an exact match is wanted we can set end=mid-1
267     * # <- mid | or start=mid+1 because we know that mid doesn't match.
268     * # |
269     * # | Eventually either end=start or end=start+1 and one of
270     * # <- end | start or end is the wanted one.
271     */
272    
273 amb 275 if(end<start) /* There are no nodes */
274     return(NO_SEGMENT);
275     else if(node<segmentsx->idata[start]) /* Check key is not before start */
276     return(NO_SEGMENT);
277     else if(node>segmentsx->idata[end]) /* Check key is not after end */
278     return(NO_SEGMENT);
279 amb 257 else
280 amb 110 {
281 amb 257 do
282     {
283 amb 275 mid=(start+end)/2; /* Choose mid point */
284 amb 110
285 amb 275 if(segmentsx->idata[mid]<node) /* Mid point is too low */
286 amb 257 start=mid;
287 amb 275 else if(segmentsx->idata[mid]>node) /* Mid point is too high */
288 amb 257 end=mid;
289 amb 275 else /* Mid point is correct */
290 amb 257 {found=mid; goto found;}
291     }
292     while((end-start)>1);
293 amb 110
294 amb 275 if(segmentsx->idata[start]==node) /* Start is correct */
295 amb 257 {found=start; goto found;}
296    
297 amb 275 if(segmentsx->idata[end]==node) /* End is correct */
298 amb 257 {found=end; goto found;}
299 amb 110 }
300    
301 amb 275 return(NO_SEGMENT);
302 amb 110
303     found:
304    
305 amb 275 while(found>0 && segmentsx->idata[found-1]==node)
306 amb 110 found--;
307    
308 amb 275 return(found);
309 amb 110 }
310    
311    
312     /*++++++++++++++++++++++++++++++++++++++
313 amb 257 Find the next segment index with a particular starting node.
314 amb 110
315 amb 275 index_t IndexNextSegmentX Returns the index of the next segment with the same id.
316 amb 110
317     SegmentsX* segmentsx The set of segments to process.
318    
319 amb 279 index_t segindex The current segment index.
320    
321     index_t nodeindex The node index.
322 amb 110 ++++++++++++++++++++++++++++++++++++++*/
323    
324 amb 279 index_t IndexNextSegmentX(SegmentsX* segmentsx,index_t segindex,index_t nodeindex)
325 amb 110 {
326 amb 279 assert(segmentsx->firstnode); /* Must have firstnode filled in => segments updated */
327    
328     if(++segindex==segmentsx->firstnode[nodeindex+1])
329 amb 275 return(NO_SEGMENT);
330 amb 229 else
331 amb 279 return(segindex);
332 amb 110 }
333    
334    
335     /*++++++++++++++++++++++++++++++++++++++
336 amb 285 Lookup a particular segment.
337 amb 110
338 amb 285 SegmentX *LookupSegmentX Returns a pointer to the extended segment with the specified id.
339 amb 110
340 amb 256 SegmentsX* segmentsx The set of segments to process.
341    
342 amb 285 index_t index The segment index to look for.
343 amb 256
344 amb 285 int position The position in the cache to use.
345 amb 110 ++++++++++++++++++++++++++++++++++++++*/
346    
347 amb 285 SegmentX *LookupSegmentX(SegmentsX* segmentsx,index_t index,int position)
348 amb 110 {
349 amb 285 assert(index!=NO_SEGMENT); /* Must be a valid segment */
350 amb 275
351 amb 285 if(option_slim)
352 amb 110 {
353 amb 285 SeekFile(segmentsx->fd,index*sizeof(SegmentX));
354 amb 110
355 amb 285 ReadFile(segmentsx->fd,&segmentsx->cached[position-1],sizeof(SegmentX));
356 amb 110
357 amb 285 return(&segmentsx->cached[position-1]);
358 amb 110 }
359 amb 285 else
360     {
361     return(&segmentsx->xdata[index]);
362     }
363 amb 110 }
364    
365    
366     /*++++++++++++++++++++++++++++++++++++++
367 amb 275 Remove bad segments (duplicated, zero length or missing nodes).
368 amb 110
369 amb 195 NodesX *nodesx The nodes to check.
370    
371 amb 110 SegmentsX *segmentsx The segments to modify.
372     ++++++++++++++++++++++++++++++++++++++*/
373    
374 amb 204 void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
375 amb 110 {
376 amb 275 int duplicate=0,loop=0,missing=0,good=0,total=0;
377     SegmentX segmentx;
378     int fd;
379     node_t prevnode1=NO_NODE,prevnode2=NO_NODE;
380 amb 110
381 amb 275 /* Print the start message */
382    
383 amb 227 printf("Checking: Segments=0 Duplicate=0 Loop=0 Missing-Node=0");
384     fflush(stdout);
385    
386 amb 279 /* Allocate the array of indexes */
387    
388     segmentsx->idata=(node_t*)malloc(segmentsx->xnumber*sizeof(node_t));
389    
390     assert(segmentsx->idata); /* Check malloc() worked */
391    
392 amb 275 /* Modify the on-disk image */
393    
394     DeleteFile(segmentsx->filename);
395    
396     fd=OpenFile(segmentsx->filename);
397     SeekFile(segmentsx->fd,0);
398    
399     while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
400 amb 110 {
401 amb 275 if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2)
402     duplicate++;
403     else if(segmentx.node1==segmentx.node2)
404 amb 257 loop++;
405 amb 275 else if(IndexNodeX(nodesx,segmentx.node1)==NO_NODE ||
406     IndexNodeX(nodesx,segmentx.node2)==NO_NODE)
407     missing++;
408     else
409 amb 257 {
410 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
411    
412 amb 279 segmentsx->idata[good]=segmentx.node1;
413 amb 275 good++;
414    
415     prevnode1=segmentx.node1;
416     prevnode2=segmentx.node2;
417 amb 110 }
418    
419 amb 275 total++;
420 amb 256
421 amb 275 if(!(total%10000))
422 amb 110 {
423 amb 275 printf("\rChecking: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",total,duplicate,loop,missing);
424 amb 110 fflush(stdout);
425     }
426     }
427    
428 amb 275 /* Close the files and re-open them */
429    
430     CloseFile(segmentsx->fd);
431     CloseFile(fd);
432    
433     segmentsx->fd=ReOpenFile(segmentsx->filename);
434    
435     segmentsx->number=good;
436    
437     /* Print the final message */
438    
439     printf("\rChecked: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d \n",total,duplicate,loop,missing);
440 amb 110 fflush(stdout);
441     }
442    
443    
444     /*++++++++++++++++++++++++++++++++++++++
445 amb 285 Measure the segments and replace node/way ids with indexes.
446 amb 110
447     SegmentsX* segmentsx The set of segments to process.
448    
449     NodesX *nodesx The list of nodes to use.
450 amb 279
451     WaysX *waysx The list of ways to use.
452 amb 110 ++++++++++++++++++++++++++++++++++++++*/
453    
454 amb 279 void UpdateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
455 amb 110 {
456 amb 279 index_t index=0;
457     int i,fd;
458 amb 256 SegmentX segmentx;
459 amb 110
460 amb 275 /* Print the start message */
461    
462 amb 227 printf("Measuring Segments: Segments=0");
463     fflush(stdout);
464    
465 amb 275 /* Map into memory */
466 amb 257
467 amb 258 if(!option_slim)
468 amb 275 nodesx->xdata=MapFile(nodesx->filename);
469 amb 258
470 amb 280 /* Free the now-unneeded index */
471    
472     free(segmentsx->idata);
473     segmentsx->idata=NULL;
474    
475 amb 279 /* Allocate the array of indexes */
476    
477     segmentsx->firstnode=(index_t*)malloc((nodesx->number+1)*sizeof(index_t));
478    
479     assert(segmentsx->firstnode); /* Check malloc() worked */
480    
481     for(i=0;i<nodesx->number;i++)
482     segmentsx->firstnode[i]=NO_SEGMENT;
483    
484     segmentsx->firstnode[nodesx->number]=segmentsx->number;
485    
486 amb 275 /* Modify the on-disk image */
487    
488 amb 256 DeleteFile(segmentsx->filename);
489    
490     fd=OpenFile(segmentsx->filename);
491     SeekFile(segmentsx->fd,0);
492    
493     while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
494 amb 110 {
495 amb 279 index_t node1=IndexNodeX(nodesx,segmentx.node1);
496     index_t node2=IndexNodeX(nodesx,segmentx.node2);
497     index_t way =IndexWayX (waysx ,segmentx.way);
498 amb 110
499 amb 279 NodeX *nodex1=LookupNodeX(nodesx,node1,1);
500     NodeX *nodex2=LookupNodeX(nodesx,node2,2);
501    
502     /* Replace the node and way ids with their indexes */
503    
504     segmentx.node1=node1;
505     segmentx.node2=node2;
506     segmentx.way =way;
507    
508 amb 275 /* Set the distance but preserve the ONEWAY_* flags */
509    
510     segmentx.distance|=DISTANCE(DistanceX(nodex1,nodex2));
511    
512 amb 279 /* Set the first segment index in the nodes */
513    
514     if(index<segmentsx->firstnode[node1])
515     segmentsx->firstnode[node1]=index;
516    
517     /* Write the modified segment */
518    
519 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
520    
521 amb 279 index++;
522 amb 275
523 amb 279 if(!(index%10000))
524 amb 257 {
525 amb 279 printf("\rMeasuring Segments: Segments=%d",index);
526 amb 275 fflush(stdout);
527     }
528     }
529 amb 110
530 amb 275 /* Close the files and re-open them */
531 amb 257
532 amb 275 CloseFile(segmentsx->fd);
533     CloseFile(fd);
534    
535     segmentsx->fd=ReOpenFile(segmentsx->filename);
536    
537 amb 280 /* Free the other now-unneeded indexes */
538 amb 279
539     free(nodesx->idata);
540     nodesx->idata=NULL;
541    
542     free(waysx->idata);
543     waysx->idata=NULL;
544    
545 amb 275 /* Unmap from memory */
546    
547     if(!option_slim)
548     nodesx->xdata=UnmapFile(nodesx->filename);
549    
550     /* Print the final message */
551    
552     printf("\rMeasured Segments: Segments=%d \n",segmentsx->number);
553     fflush(stdout);
554     }
555    
556    
557     /*++++++++++++++++++++++++++++++++++++++
558     Make the segments all point the same way (node1<node2).
559    
560     SegmentsX* segmentsx The set of segments to process.
561     ++++++++++++++++++++++++++++++++++++++*/
562    
563     void RotateSegments(SegmentsX* segmentsx)
564     {
565     int index=0,rotated=0;
566     int fd;
567     SegmentX segmentx;
568    
569     /* Check the start conditions */
570    
571     assert(!segmentsx->idata); /* Must not have idata filled in => not sorted by node 1 */
572    
573     /* Print the start message */
574    
575     printf("Rotating Segments: Segments=0 Rotated=0");
576     fflush(stdout);
577    
578     /* Close the files and re-open them (finished appending) */
579    
580     CloseFile(segmentsx->fd);
581     segmentsx->fd=ReOpenFile(segmentsx->filename);
582    
583     DeleteFile(segmentsx->filename);
584    
585     fd=OpenFile(segmentsx->filename);
586    
587     /* Modify the file contents */
588    
589     while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
590     {
591     if(segmentx.node1>segmentx.node2)
592     {
593     node_t temp;
594    
595     temp=segmentx.node1;
596     segmentx.node1=segmentx.node2;
597     segmentx.node2=temp;
598    
599     if(segmentx.distance&(ONEWAY_2TO1|ONEWAY_1TO2))
600     segmentx.distance^=ONEWAY_2TO1|ONEWAY_1TO2;
601    
602     rotated++;
603 amb 257 }
604 amb 110
605 amb 256 WriteFile(fd,&segmentx,sizeof(SegmentX));
606    
607 amb 275 index++;
608 amb 256
609 amb 275 if(!(index%10000))
610 amb 110 {
611 amb 275 printf("\rRotating Segments: Segments=%d Rotated=%d",index,rotated);
612 amb 110 fflush(stdout);
613     }
614     }
615    
616 amb 275 /* Close the files and re-open them */
617    
618 amb 256 CloseFile(segmentsx->fd);
619     CloseFile(fd);
620    
621     segmentsx->fd=ReOpenFile(segmentsx->filename);
622    
623 amb 275 /* Print the final message */
624 amb 256
625 amb 275 printf("\rRotated Segments: Segments=%d Rotated=%d \n",index,rotated);
626 amb 110 fflush(stdout);
627     }
628    
629    
630     /*++++++++++++++++++++++++++++++++++++++
631 amb 275 Remove the duplicate segments.
632 amb 110
633     SegmentsX* segmentsx The set of segments to process.
634    
635 amb 279 NodesX *nodesx The list of nodes to use.
636    
637 amb 110 WaysX *waysx The list of ways to use.
638     ++++++++++++++++++++++++++++++++++++++*/
639    
640 amb 279 void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
641 amb 110 {
642 amb 275 int duplicate=0,good=0;
643     index_t firstindex=0,index=0;
644 amb 279 int i,fd;
645 amb 275 SegmentX prevsegmentx[16],segmentx;
646 amb 110
647 amb 275 /* Print the start message */
648    
649 amb 227 printf("Deduplicating Segments: Segments=0 Duplicate=0");
650     fflush(stdout);
651    
652 amb 275 /* Map into memory */
653 amb 256
654 amb 275 if(!option_slim)
655     waysx->xdata=MapFile(waysx->filename);
656    
657 amb 279 /* Allocate the array of indexes */
658    
659     segmentsx->firstnode=(index_t*)malloc((nodesx->number+1)*sizeof(index_t));
660    
661     assert(segmentsx->firstnode); /* Check malloc() worked */
662    
663     for(i=0;i<nodesx->number;i++)
664     segmentsx->firstnode[i]=NO_SEGMENT;
665    
666     segmentsx->firstnode[nodesx->number]=segmentsx->number;
667    
668 amb 275 /* Modify the on-disk image */
669    
670     DeleteFile(segmentsx->filename);
671    
672     fd=OpenFile(segmentsx->filename);
673     SeekFile(segmentsx->fd,0);
674    
675     while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
676 amb 110 {
677 amb 275 int isduplicate=0;
678 amb 256
679 amb 275 if(index && segmentx.node1==prevsegmentx[0].node1 &&
680     segmentx.node2==prevsegmentx[0].node2)
681 amb 110 {
682 amb 264 index_t previndex=firstindex;
683 amb 110
684 amb 275 while(previndex<index)
685 amb 110 {
686 amb 275 int offset=previndex-firstindex;
687    
688     if(DISTFLAG(segmentx.distance)==DISTFLAG(prevsegmentx[offset].distance))
689 amb 264 {
690 amb 279 WayX *wayx1=LookupWayX(waysx,prevsegmentx[offset].way,1);
691     WayX *wayx2=LookupWayX(waysx, segmentx .way,2);
692 amb 110
693 amb 275 if(!WaysCompare(&wayx1->way,&wayx2->way))
694 amb 264 {
695 amb 275 isduplicate=1;
696     duplicate++;
697     break;
698 amb 264 }
699     }
700    
701     previndex++;
702 amb 110 }
703 amb 275
704     assert((index-firstindex)<(sizeof(prevsegmentx)/sizeof(prevsegmentx[0])));
705    
706     prevsegmentx[index-firstindex]=segmentx;
707 amb 110 }
708 amb 264 else
709     {
710 amb 275 firstindex=index;
711     prevsegmentx[0]=segmentx;
712 amb 264 }
713 amb 110
714 amb 275 if(!isduplicate)
715 amb 110 {
716 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
717    
718 amb 279 if(good<segmentsx->firstnode[segmentx.node1])
719     segmentsx->firstnode[segmentx.node1]=good;
720    
721 amb 275 good++;
722     }
723    
724     index++;
725    
726     if(!(index%10000))
727     {
728     printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",index,duplicate);
729 amb 110 fflush(stdout);
730     }
731     }
732    
733 amb 275 /* Close the files and re-open them */
734    
735     CloseFile(segmentsx->fd);
736     CloseFile(fd);
737    
738     segmentsx->fd=ReOpenFile(segmentsx->filename);
739    
740 amb 279 segmentsx->number=good;
741 amb 275
742 amb 279 /* Fix-up the firstnode index for the missing nodes */
743 amb 275
744 amb 279 for(i=nodesx->number-1;i>=0;i--)
745     if(segmentsx->firstnode[i]==NO_SEGMENT)
746     segmentsx->firstnode[i]=segmentsx->firstnode[i+1];
747 amb 275
748     /* Unmap from memory */
749    
750     if(!option_slim)
751     waysx->xdata=UnmapFile(waysx->filename);
752    
753     /* Print the final message */
754    
755     printf("\rDeduplicated Segments: Segments=%d Duplicate=%d Unique=%d\n",index,duplicate,index-duplicate);
756 amb 110 fflush(stdout);
757     }
758    
759    
760     /*++++++++++++++++++++++++++++++++++++++
761 amb 209 Create the real segments data.
762    
763     SegmentsX* segmentsx The set of segments to use.
764    
765     WaysX* waysx The set of ways to use.
766     ++++++++++++++++++++++++++++++++++++++*/
767    
768     void CreateRealSegments(SegmentsX *segmentsx,WaysX *waysx)
769     {
770 amb 214 index_t i;
771 amb 209
772 amb 275 /* Check the start conditions */
773    
774 amb 243 assert(!segmentsx->sdata); /* Must not have sdata filled in => no real segments */
775 amb 213
776 amb 275 /* Print the start message */
777    
778 amb 227 printf("Creating Real Segments: Segments=0");
779     fflush(stdout);
780    
781 amb 275 /* Map into memory */
782 amb 209
783 amb 275 if(!option_slim)
784     {
785     segmentsx->xdata=MapFile(segmentsx->filename);
786     waysx->xdata=MapFile(waysx->filename);
787     }
788    
789 amb 280 /* Free the unneeded memory */
790    
791     free(segmentsx->firstnode);
792     segmentsx->firstnode=NULL;
793    
794 amb 279 /* Allocate the memory */
795 amb 275
796 amb 209 segmentsx->sdata=(Segment*)malloc(segmentsx->number*sizeof(Segment));
797    
798 amb 243 assert(segmentsx->sdata); /* Check malloc() worked */
799    
800 amb 275 /* Loop through and fill */
801 amb 209
802     for(i=0;i<segmentsx->number;i++)
803     {
804 amb 275 SegmentX *segmentx=LookupSegmentX(segmentsx,i,1);
805 amb 279 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
806 amb 209
807     segmentsx->sdata[i].node1=0;
808     segmentsx->sdata[i].node2=0;
809     segmentsx->sdata[i].next2=NO_NODE;
810 amb 310 segmentsx->sdata[i].way=wayx->prop;
811 amb 256 segmentsx->sdata[i].distance=segmentx->distance;
812 amb 209
813     if(!((i+1)%10000))
814     {
815     printf("\rCreating Real Segments: Segments=%d",i+1);
816     fflush(stdout);
817     }
818     }
819    
820 amb 275 /* Unmap from memory */
821    
822     if(!option_slim)
823     {
824     segmentsx->xdata=UnmapFile(segmentsx->filename);
825     waysx->xdata=UnmapFile(waysx->filename);
826     }
827    
828     /* Print the final message */
829    
830 amb 209 printf("\rCreating Real Segments: Segments=%d \n",segmentsx->number);
831     fflush(stdout);
832     }
833    
834    
835     /*++++++++++++++++++++++++++++++++++++++
836 amb 110 Assign the nodes indexes to the segments.
837    
838     SegmentsX* segmentsx The set of segments to process.
839    
840     NodesX *nodesx The list of nodes to use.
841     ++++++++++++++++++++++++++++++++++++++*/
842    
843     void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx)
844     {
845 amb 214 index_t i;
846 amb 110
847 amb 275 /* Check the start conditions */
848    
849 amb 281 assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */
850     assert(segmentsx->sdata); /* Must have sdata filled in => real segments exist */
851 amb 110
852 amb 275 /* Print the start message */
853    
854 amb 227 printf("Indexing Nodes: Nodes=0");
855     fflush(stdout);
856    
857 amb 275 /* Map into memory */
858    
859     if(!option_slim)
860 amb 281 {
861     nodesx->xdata=MapFile(nodesx->filename);
862 amb 275 segmentsx->xdata=MapFile(segmentsx->filename);
863 amb 281 }
864 amb 275
865 amb 110 /* Index the segments */
866    
867     for(i=0;i<nodesx->number;i++)
868     {
869 amb 281 NodeX *nodex=LookupNodeX(nodesx,i,1);
870     Node *node =&nodesx->ndata[nodex->id];
871 amb 212 index_t index=SEGMENT(node->firstseg);
872 amb 110
873     do
874     {
875 amb 275 SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
876 amb 256
877 amb 281 if(segmentx->node1==nodex->id)
878 amb 110 {
879 amb 209 segmentsx->sdata[index].node1=i;
880 amb 110
881 amb 209 index++;
882 amb 128
883 amb 256 if(index>=segmentsx->number)
884 amb 209 break;
885 amb 256
886 amb 275 segmentx=LookupSegmentX(segmentsx,index,1);
887 amb 256
888 amb 281 if(segmentx->node1!=nodex->id)
889 amb 256 break;
890 amb 110 }
891     else
892     {
893 amb 209 segmentsx->sdata[index].node2=i;
894 amb 110
895 amb 209 if(segmentsx->sdata[index].next2==NO_NODE)
896     break;
897 amb 110 else
898 amb 209 index=segmentsx->sdata[index].next2;
899 amb 110 }
900     }
901 amb 209 while(1);
902 amb 110
903     if(!((i+1)%10000))
904     {
905     printf("\rIndexing Nodes: Nodes=%d",i+1);
906     fflush(stdout);
907     }
908     }
909    
910 amb 275 /* Unmap from memory */
911    
912     if(!option_slim)
913 amb 281 {
914     nodesx->xdata=UnmapFile(nodesx->filename);
915 amb 275 segmentsx->xdata=UnmapFile(segmentsx->filename);
916 amb 281 }
917 amb 275
918     /* Print the final message */
919    
920 amb 110 printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number);
921     fflush(stdout);
922     }
923    
924    
925     /*++++++++++++++++++++++++++++++++++++++
926 amb 285 Save the segment list to a file.
927    
928     SegmentsX* segmentsx The set of segments to save.
929    
930     const char *filename The name of the file to save.
931     ++++++++++++++++++++++++++++++++++++++*/
932    
933     void SaveSegmentList(SegmentsX* segmentsx,const char *filename)
934     {
935     index_t i;
936     int fd;
937     Segments *segments;
938     int super_number=0,normal_number=0;
939    
940     /* Check the start conditions */
941    
942     assert(segmentsx->sdata); /* Must have sdata filled in => real segments */
943    
944     /* Print the start message */
945    
946     printf("Writing Segments: Segments=0");
947     fflush(stdout);
948    
949     /* Count the number of super-segments and normal segments */
950    
951     for(i=0;i<segmentsx->number;i++)
952     {
953     if(IsSuperSegment(&segmentsx->sdata[i]))
954     super_number++;
955     if(IsNormalSegment(&segmentsx->sdata[i]))
956     normal_number++;
957     }
958    
959     /* Fill in a Segments structure with the offset of the real data in the file after
960     the Segment structure itself. */
961    
962     segments=calloc(1,sizeof(Segments));
963    
964     assert(segments); /* Check calloc() worked */
965    
966     segments->number=segmentsx->number;
967     segments->snumber=super_number;
968     segments->nnumber=normal_number;
969    
970     segments->data=NULL;
971    
972     segments->segments=(void*)sizeof(Segments);
973    
974     /* Write out the Segments structure and then the real data. */
975    
976     fd=OpenFile(filename);
977    
978     WriteFile(fd,segments,sizeof(Segments));
979    
980     for(i=0;i<segments->number;i++)
981     {
982     WriteFile(fd,&segmentsx->sdata[i],sizeof(Segment));
983    
984     if(!((i+1)%10000))
985     {
986     printf("\rWriting Segments: Segments=%d",i+1);
987     fflush(stdout);
988     }
989     }
990    
991     CloseFile(fd);
992    
993     /* Print the final message */
994    
995     printf("\rWrote Segments: Segments=%d \n",segments->number);
996     fflush(stdout);
997    
998     /* Free the fake Segments */
999    
1000     free(segments);
1001     }
1002    
1003    
1004     /*++++++++++++++++++++++++++++++++++++++
1005 amb 110 Calculate the distance between two nodes.
1006    
1007     distance_t DistanceX Returns the distance between the extended nodes.
1008    
1009     NodeX *nodex1 The starting node.
1010    
1011     NodeX *nodex2 The end node.
1012     ++++++++++++++++++++++++++++++++++++++*/
1013    
1014 amb 228 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
1015 amb 110 {
1016 amb 223 double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude);
1017     double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude);
1018     double lat1 = latlong_to_radians(nodex1->latitude);
1019     double lat2 = latlong_to_radians(nodex2->latitude);
1020 amb 110
1021 amb 219 double a1,a2,a,sa,c,d;
1022 amb 110
1023     if(dlon==0 && dlat==0)
1024     return 0;
1025    
1026 amb 219 a1 = sin (dlat / 2);
1027     a2 = sin (dlon / 2);
1028     a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
1029     sa = sqrt (a);
1030 amb 110 if (sa <= 1.0)
1031 amb 219 {c = 2 * asin (sa);}
1032 amb 110 else
1033 amb 219 {c = 2 * asin (1.0);}
1034 amb 110 d = 6378.137 * c;
1035    
1036     return km_to_distance(d);
1037     }

Properties

Name Value
cvs:description Extended segments functions.