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 1120 - (hide annotations) (download) (as text)
Thu Nov 1 20:00:27 2012 UTC (12 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 26148 byte(s)
Introduce a new'--append' option for appending data from a file to the currently
parsed data.  Rename the intermediate file used for storing data to be appended
to.  Add a function to call after appending to a file which closes the file and
renames it to a temporary filename which is used for the remaining processing.

1 amb 110 /***************************************
2     Extended Segment data type functions.
3 amb 151
4     Part of the Routino routing software.
5 amb 110 ******************/ /******************
6 amb 949 This file Copyright 2008-2012 Andrew M. Bishop
7 amb 110
8 amb 151 This program is free software: you can redistribute it and/or modify
9     it under the terms of the GNU Affero General Public License as published by
10     the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12    
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     GNU Affero General Public License for more details.
17    
18     You should have received a copy of the GNU Affero General Public License
19     along with this program. If not, see <http://www.gnu.org/licenses/>.
20 amb 110 ***************************************/
21    
22    
23     #include <assert.h>
24     #include <math.h>
25     #include <stdlib.h>
26 amb 955 #include <string.h>
27 amb 110
28     #include "types.h"
29 amb 228 #include "segments.h"
30     #include "ways.h"
31 amb 110
32 amb 955 #include "typesx.h"
33 amb 449 #include "nodesx.h"
34     #include "segmentsx.h"
35     #include "waysx.h"
36 amb 110
37 amb 449 #include "files.h"
38 amb 519 #include "logging.h"
39 amb 532 #include "sorting.h"
40 amb 449
41    
42 amb 680 /* Global variables */
43 amb 110
44 amb 289 /*+ The command line '--tmpdir' option or its default value. +*/
45 amb 284 extern char *option_tmpdirname;
46 amb 110
47 amb 1100 /* Local variables */
48    
49 amb 1107 /*+ Temporary file-local variables for use by the sort functions. +*/
50 amb 1100 static SegmentsX *sortsegmentsx;
51 amb 1107 static NodesX *sortnodesx;
52 amb 1100
53 amb 680 /* Local functions */
54 amb 110
55 amb 275 static int sort_by_id(SegmentX *a,SegmentX *b);
56 amb 949 static int delete_pruned(SegmentX *segmentx,index_t index);
57 amb 1107 static int geographically_index(SegmentX *segmentx,index_t index);
58 amb 275
59 amb 228 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2);
60 amb 110
61    
62     /*++++++++++++++++++++++++++++++++++++++
63 amb 326 Allocate a new segment list (create a new file or open an existing one).
64 amb 110
65     SegmentsX *NewSegmentList Returns the segment list.
66 amb 326
67     int append Set to 1 if the file is to be opened for appending (now or later).
68 amb 110 ++++++++++++++++++++++++++++++++++++++*/
69    
70 amb 326 SegmentsX *NewSegmentList(int append)
71 amb 110 {
72     SegmentsX *segmentsx;
73    
74 amb 213 segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX));
75 amb 110
76 amb 243 assert(segmentsx); /* Check calloc() worked */
77    
78 amb 1120 segmentsx->filename =(char*)malloc(strlen(option_tmpdirname)+32);
79     segmentsx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
80 amb 216
81 amb 1120 sprintf(segmentsx->filename ,"%s/segmentsx.parsed.mem",option_tmpdirname);
82     sprintf(segmentsx->filename_tmp,"%s/segmentsx.%p.tmp" ,option_tmpdirname,(void*)segmentsx);
83 amb 256
84 amb 326 if(append)
85     {
86 amb 331 off_t size;
87 amb 326
88 amb 502 segmentsx->fd=OpenFileAppend(segmentsx->filename);
89 amb 326
90 amb 331 size=SizeFile(segmentsx->filename);
91 amb 326
92 amb 650 segmentsx->number=size/sizeof(SegmentX);
93 amb 326 }
94     else
95 amb 502 segmentsx->fd=OpenFileNew(segmentsx->filename);
96 amb 326
97 amb 110 return(segmentsx);
98     }
99    
100    
101     /*++++++++++++++++++++++++++++++++++++++
102 amb 226 Free a segment list.
103 amb 110
104 amb 681 SegmentsX *segmentsx The set of segments to be freed.
105 amb 326
106 amb 680 int keep Set to 1 if the file is to be kept (for appending later).
107 amb 110 ++++++++++++++++++++++++++++++++++++++*/
108    
109 amb 326 void FreeSegmentList(SegmentsX *segmentsx,int keep)
110 amb 110 {
111 amb 326 if(!keep)
112     DeleteFile(segmentsx->filename);
113    
114 amb 1120 DeleteFile(segmentsx->filename_tmp);
115    
116 amb 283 free(segmentsx->filename);
117 amb 1120 free(segmentsx->filename_tmp);
118 amb 256
119 amb 949 if(segmentsx->firstnode)
120     free(segmentsx->firstnode);
121    
122     if(segmentsx->next1)
123     free(segmentsx->next1);
124    
125 amb 643 if(segmentsx->usednode)
126     free(segmentsx->usednode);
127    
128 amb 110 free(segmentsx);
129     }
130    
131    
132     /*++++++++++++++++++++++++++++++++++++++
133 amb 493 Append a single segment to an unsorted segment list.
134 amb 110
135 amb 681 SegmentsX *segmentsx The set of segments to modify.
136 amb 110
137 amb 285 way_t way The way that the segment belongs to.
138    
139     node_t node1 The first node in the segment.
140    
141     node_t node2 The second node in the segment.
142    
143     distance_t distance The distance between the nodes (or just the flags).
144 amb 110 ++++++++++++++++++++++++++++++++++++++*/
145    
146 amb 681 void AppendSegment(SegmentsX *segmentsx,way_t way,node_t node1,node_t node2,distance_t distance)
147 amb 110 {
148 amb 285 SegmentX segmentx;
149 amb 110
150 amb 643 if(node1>node2)
151     {
152     node_t temp;
153    
154     temp=node1;
155     node1=node2;
156     node2=temp;
157    
158     if(distance&(ONEWAY_2TO1|ONEWAY_1TO2))
159     distance^=ONEWAY_2TO1|ONEWAY_1TO2;
160     }
161    
162 amb 285 segmentx.node1=node1;
163     segmentx.node2=node2;
164 amb 643 segmentx.next2=NO_SEGMENT;
165 amb 285 segmentx.way=way;
166     segmentx.distance=distance;
167 amb 110
168 amb 285 WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
169 amb 281
170 amb 650 segmentsx->number++;
171 amb 466
172 amb 650 assert(segmentsx->number<SEGMENT_FAKE); /* SEGMENT_FAKE marks the high-water mark for real segments. */
173 amb 285 }
174 amb 227
175 amb 281
176 amb 285 /*++++++++++++++++++++++++++++++++++++++
177 amb 1120 Finish appending segments and change the filename over.
178    
179     SegmentsX *segmentsx The segments that have been appended.
180     ++++++++++++++++++++++++++++++++++++++*/
181    
182     void FinishSegmentList(SegmentsX *segmentsx)
183     {
184     /* Close the file (finished appending) */
185    
186     segmentsx->fd=CloseFile(segmentsx->fd);
187    
188     /* Rename the file to the temporary name (used everywhere else) */
189    
190     RenameFile(segmentsx->filename,segmentsx->filename_tmp);
191     }
192    
193    
194     /*++++++++++++++++++++++++++++++++++++++
195 amb 285 Sort the segment list.
196 amb 232
197 amb 949 SegmentsX *segmentsx The set of segments to sort and modify.
198 amb 1100 ++++++++++++++++++++++++++++++++++++++*/
199 amb 949
200 amb 1100 void SortSegmentList(SegmentsX *segmentsx)
201     {
202     int fd;
203    
204     /* Print the start message */
205    
206     printf_first("Sorting Segments");
207    
208     /* Re-open the file read-only and a new file writeable */
209    
210 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
211 amb 1100
212 amb 1120 DeleteFile(segmentsx->filename_tmp);
213 amb 1100
214 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
215 amb 1100
216     /* Sort by node indexes */
217    
218 amb 1106 filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL,
219     (int (*)(const void*,const void*))sort_by_id,
220     NULL);
221 amb 1100
222     /* Close the files */
223    
224     segmentsx->fd=CloseFile(segmentsx->fd);
225     CloseFile(fd);
226    
227     /* Print the final message */
228    
229     printf_last("Sorted Segments: Segments=%"Pindex_t,segmentsx->number);
230     }
231    
232    
233     /*++++++++++++++++++++++++++++++++++++++
234     Prune the deleted segments while resorting the list.
235    
236     SegmentsX *segmentsx The set of segments to sort and modify.
237    
238     WaysX *waysx The set of ways to check.
239 amb 285 ++++++++++++++++++++++++++++++++++++++*/
240 amb 110
241 amb 1100 void RemovePrunedSegments(SegmentsX *segmentsx,WaysX *waysx)
242 amb 285 {
243     int fd;
244 amb 949 index_t kept;
245 amb 243
246 amb 285 /* Print the start message */
247 amb 232
248 amb 1106 printf_first("Sorting and Pruning Segments");
249 amb 110
250 amb 555 /* Close the file (finished appending) */
251 amb 110
252 amb 700 if(segmentsx->fd!=-1)
253     segmentsx->fd=CloseFile(segmentsx->fd);
254 amb 555
255 amb 1100 /* Allocate the way usage bitmask */
256    
257     segmentsx->usedway=AllocBitMask(waysx->number);
258    
259     assert(segmentsx->usedway); /* Check AllocBitMask() worked */
260    
261 amb 555 /* Re-open the file read-only and a new file writeable */
262    
263 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
264 amb 110
265 amb 1120 DeleteFile(segmentsx->filename_tmp);
266 amb 110
267 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
268 amb 110
269 amb 285 /* Sort by node indexes */
270 amb 132
271 amb 1100 sortsegmentsx=segmentsx;
272 amb 285
273 amb 1111 kept=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))delete_pruned,
274 amb 1106 (int (*)(const void*,const void*))sort_by_id,
275 amb 1111 NULL);
276 amb 1100
277 amb 555 /* Close the files */
278 amb 285
279 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
280 amb 281 CloseFile(fd);
281    
282     /* Print the final message */
283    
284 amb 1106 printf_last("Sorted and Pruned Segments: Segments=%"Pindex_t" Deleted=%"Pindex_t,kept,segmentsx->number-kept);
285 amb 1100 segmentsx->number=kept;
286 amb 110 }
287    
288    
289     /*++++++++++++++++++++++++++++++++++++++
290 amb 680 Sort the segments into id order, first by node1 then by node2, finally by distance.
291 amb 110
292 amb 285 int sort_by_id Returns the comparison of the node fields.
293 amb 110
294 amb 285 SegmentX *a The first segment.
295 amb 110
296 amb 285 SegmentX *b The second segment.
297 amb 256 ++++++++++++++++++++++++++++++++++++++*/
298    
299 amb 285 static int sort_by_id(SegmentX *a,SegmentX *b)
300 amb 256 {
301 amb 285 node_t a_id1=a->node1;
302     node_t b_id1=b->node1;
303 amb 256
304 amb 285 if(a_id1<b_id1)
305     return(-1);
306     else if(a_id1>b_id1)
307     return(1);
308     else /* if(a_id1==b_id1) */
309 amb 256 {
310 amb 285 node_t a_id2=a->node2;
311     node_t b_id2=b->node2;
312 amb 256
313 amb 285 if(a_id2<b_id2)
314     return(-1);
315     else if(a_id2>b_id2)
316     return(1);
317     else
318     {
319 amb 914 distance_t a_distance=DISTANCE(a->distance);
320     distance_t b_distance=DISTANCE(b->distance);
321 amb 256
322 amb 285 if(a_distance<b_distance)
323     return(-1);
324     else if(a_distance>b_distance)
325     return(1);
326     else
327 amb 1118 return(FILESORT_PRESERVE_ORDER(a,b));
328 amb 285 }
329 amb 256 }
330     }
331    
332    
333     /*++++++++++++++++++++++++++++++++++++++
334 amb 949 Delete the pruned segments.
335    
336     int delete_pruned Return 1 if the value is to be kept, otherwise 0.
337    
338     SegmentX *segmentx The extended segment.
339    
340 amb 1112 index_t index The number of unsorted segments that have been read from the input file.
341 amb 949 ++++++++++++++++++++++++++++++++++++++*/
342    
343     static int delete_pruned(SegmentX *segmentx,index_t index)
344     {
345     if(IsPrunedSegmentX(segmentx))
346     return(0);
347    
348 amb 1100 SetBit(sortsegmentsx->usedway,segmentx->way);
349    
350 amb 949 return(1);
351     }
352    
353    
354     /*++++++++++++++++++++++++++++++++++++++
355 amb 1107 Sort the segments geographically after updating the node indexes.
356    
357     SegmentsX *segmentsx The set of segments to modify.
358    
359     NodesX *nodesx The set of nodes to use.
360     ++++++++++++++++++++++++++++++++++++++*/
361    
362     void SortSegmentListGeographically(SegmentsX *segmentsx,NodesX *nodesx)
363     {
364     int fd;
365    
366     /* Print the start message */
367    
368     printf_first("Sorting Segments Geographically");
369    
370     /* Re-open the file read-only and a new file writeable */
371    
372 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
373 amb 1107
374 amb 1120 DeleteFile(segmentsx->filename_tmp);
375 amb 1107
376 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
377 amb 1107
378     /* Update the segments with geographically sorted node indexes and sort them */
379    
380     sortnodesx=nodesx;
381    
382     filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))geographically_index,
383     (int (*)(const void*,const void*))sort_by_id,
384     NULL);
385     /* Close the files */
386    
387     segmentsx->fd=CloseFile(segmentsx->fd);
388     CloseFile(fd);
389    
390     /* Print the final message */
391    
392 amb 1110 printf_last("Sorted Segments Geographically: Segments=%"Pindex_t,segmentsx->number);
393 amb 1107 }
394    
395    
396     /*++++++++++++++++++++++++++++++++++++++
397     Update the segment indexes.
398    
399     int geographically_index Return 1 if the value is to be kept, otherwise 0.
400    
401     SegmentX *segmentx The extended segment.
402    
403 amb 1112 index_t index The number of unsorted segments that have been read from the input file.
404 amb 1107 ++++++++++++++++++++++++++++++++++++++*/
405    
406     static int geographically_index(SegmentX *segmentx,index_t index)
407     {
408     segmentx->node1=sortnodesx->gdata[segmentx->node1];
409     segmentx->node2=sortnodesx->gdata[segmentx->node2];
410    
411     if(segmentx->node1>segmentx->node2)
412     {
413     index_t temp;
414    
415     temp=segmentx->node1;
416     segmentx->node1=segmentx->node2;
417     segmentx->node2=temp;
418    
419     if(segmentx->distance&(ONEWAY_2TO1|ONEWAY_1TO2))
420     segmentx->distance^=ONEWAY_2TO1|ONEWAY_1TO2;
421     }
422    
423     return(1);
424     }
425    
426    
427     /*++++++++++++++++++++++++++++++++++++++
428 amb 643 Find the first extended segment with a particular starting node index.
429    
430 amb 646 SegmentX *FirstSegmentX Returns a pointer to the first extended segment with the specified id.
431 amb 544
432 amb 681 SegmentsX *segmentsx The set of segments to use.
433 amb 544
434 amb 643 index_t nodeindex The node index to look for.
435    
436     int position A flag to pass through.
437     ++++++++++++++++++++++++++++++++++++++*/
438    
439 amb 681 SegmentX *FirstSegmentX(SegmentsX *segmentsx,index_t nodeindex,int position)
440 amb 643 {
441     index_t index=segmentsx->firstnode[nodeindex];
442     SegmentX *segmentx;
443    
444 amb 793 if(index==NO_SEGMENT)
445     return(NULL);
446    
447 amb 643 segmentx=LookupSegmentX(segmentsx,index,position);
448    
449     return(segmentx);
450     }
451    
452    
453     /*++++++++++++++++++++++++++++++++++++++
454     Find the next segment with a particular starting node index.
455    
456 amb 646 SegmentX *NextSegmentX Returns a pointer to the next segment with the same id.
457 amb 643
458 amb 681 SegmentsX *segmentsx The set of segments to use.
459 amb 544
460 amb 643 SegmentX *segmentx The current segment.
461 amb 544
462 amb 771 index_t nodeindex The node index.
463 amb 110 ++++++++++++++++++++++++++++++++++++++*/
464    
465 amb 943 SegmentX *NextSegmentX(SegmentsX *segmentsx,SegmentX *segmentx,index_t nodeindex)
466 amb 110 {
467 amb 943 #if SLIM
468     int position=1+(segmentx-&segmentsx->cached[0]);
469     #endif
470    
471 amb 771 if(segmentx->node1==nodeindex)
472 amb 643 {
473 amb 949 if(segmentsx->next1)
474     {
475     index_t index=IndexSegmentX(segmentsx,segmentx);
476    
477 amb 952 if(segmentsx->next1[index]==NO_SEGMENT)
478 amb 949 return(NULL);
479    
480     segmentx=LookupSegmentX(segmentsx,segmentsx->next1[index],position);
481    
482     return(segmentx);
483     }
484     else
485     {
486 amb 643 #if SLIM
487 amb 949 index_t index=IndexSegmentX(segmentsx,segmentx);
488     index++;
489 amb 544
490 amb 949 if(index>=segmentsx->number)
491     return(NULL);
492    
493     segmentx=LookupSegmentX(segmentsx,index,position);
494 amb 643 #else
495 amb 949 segmentx++;
496    
497     if(IndexSegmentX(segmentsx,segmentx)>=segmentsx->number)
498     return(NULL);
499     #endif
500    
501     if(segmentx->node1!=nodeindex)
502     return(NULL);
503    
504 amb 643 return(segmentx);
505 amb 949 }
506 amb 643 }
507 amb 229 else
508 amb 643 {
509     if(segmentx->next2==NO_SEGMENT)
510     return(NULL);
511 amb 949
512     return(LookupSegmentX(segmentsx,segmentx->next2,position));
513 amb 643 }
514 amb 110 }
515    
516    
517     /*++++++++++++++++++++++++++++++++++++++
518 amb 680 Remove bad segments (duplicated, zero length or with missing nodes).
519 amb 110
520 amb 681 NodesX *nodesx The set of nodes to use.
521 amb 195
522 amb 681 SegmentsX *segmentsx The set of segments to modify.
523 amb 110 ++++++++++++++++++++++++++++++++++++++*/
524    
525 amb 204 void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
526 amb 110 {
527 amb 780 index_t duplicate=0,loop=0,nonode=0,good=0,total=0;
528 amb 275 SegmentX segmentx;
529     int fd;
530 amb 755 node_t prevnode1=NO_NODE_ID,prevnode2=NO_NODE_ID;
531 amb 914 distance_t prevdist=0;
532 amb 110
533 amb 275 /* Print the start message */
534    
535 amb 761 printf_first("Checking Segments: Segments=0 Duplicate=0 Loop=0 No-Node=0");
536 amb 227
537 amb 1100 /* Allocate the node usage bitmask */
538 amb 643
539 amb 950 segmentsx->usednode=AllocBitMask(nodesx->number);
540 amb 643
541 amb 950 assert(segmentsx->usednode); /* Check AllocBitMask() worked */
542 amb 643
543 amb 555 /* Re-open the file read-only and a new file writeable */
544 amb 275
545 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
546 amb 555
547 amb 1120 DeleteFile(segmentsx->filename_tmp);
548 amb 275
549 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
550 amb 275
551 amb 555 /* Modify the on-disk image */
552    
553 amb 275 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
554 amb 110 {
555 amb 643 index_t index1=IndexNodeX(nodesx,segmentx.node1);
556     index_t index2=IndexNodeX(nodesx,segmentx.node2);
557    
558 amb 275 if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2)
559 amb 812 {
560 amb 914 if(!prevdist && !DISTANCE(segmentx.distance))
561     logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated.\n",segmentx.node1,segmentx.node2);
562 amb 812
563 amb 914 if(!prevdist && DISTANCE(segmentx.distance))
564     logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the area).\n",segmentx.node1,segmentx.node2);
565    
566     if(prevdist && !DISTANCE(segmentx.distance))
567     logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the non-area).\n",segmentx.node1,segmentx.node2);
568    
569     if(prevdist && DISTANCE(segmentx.distance))
570     logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (both are areas).\n",segmentx.node1,segmentx.node2);
571    
572 amb 275 duplicate++;
573 amb 812 }
574 amb 275 else if(segmentx.node1==segmentx.node2)
575 amb 812 {
576     logerror("Segment connects node %"Pnode_t" to itself.\n",segmentx.node1);
577    
578 amb 257 loop++;
579 amb 812 }
580 amb 643 else if(index1==NO_NODE || index2==NO_NODE)
581 amb 812 {
582     if(index1==NO_NODE && index2==NO_NODE)
583     logerror("Segment connects nodes %"Pnode_t" and %"Pnode_t" but neither exist.\n",segmentx.node1,segmentx.node2);
584    
585     if(index1==NO_NODE && index2!=NO_NODE)
586     logerror("Segment connects nodes %"Pnode_t" and %"Pnode_t" but the first one does not exist.\n",segmentx.node1,segmentx.node2);
587    
588     if(index1!=NO_NODE && index2==NO_NODE)
589     logerror("Segment connects nodes %"Pnode_t" and %"Pnode_t" but the second one does not exist.\n",segmentx.node1,segmentx.node2);
590    
591 amb 761 nonode++;
592 amb 812 }
593 amb 275 else
594 amb 257 {
595 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
596    
597 amb 655 SetBit(segmentsx->usednode,index1);
598     SetBit(segmentsx->usednode,index2);
599 amb 643
600 amb 275 good++;
601    
602     prevnode1=segmentx.node1;
603     prevnode2=segmentx.node2;
604 amb 914 prevdist=DISTANCE(segmentx.distance);
605 amb 110 }
606    
607 amb 275 total++;
608 amb 256
609 amb 275 if(!(total%10000))
610 amb 790 printf_middle("Checking Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t" Loop=%"Pindex_t" No-Node=%"Pindex_t,total,duplicate,loop,nonode);
611 amb 110 }
612    
613 amb 555 segmentsx->number=good;
614 amb 275
615 amb 555 /* Close the files */
616    
617 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
618 amb 275 CloseFile(fd);
619    
620     /* Print the final message */
621    
622 amb 790 printf_last("Checked Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t" Loop=%"Pindex_t" No-Node=%"Pindex_t,total,duplicate,loop,nonode);
623 amb 110 }
624    
625    
626     /*++++++++++++++++++++++++++++++++++++++
627 amb 285 Measure the segments and replace node/way ids with indexes.
628 amb 110
629 amb 681 SegmentsX *segmentsx The set of segments to process.
630 amb 110
631 amb 680 NodesX *nodesx The set of nodes to use.
632 amb 279
633 amb 680 WaysX *waysx The set of ways to use.
634 amb 110 ++++++++++++++++++++++++++++++++++++++*/
635    
636 amb 681 void MeasureSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
637 amb 110 {
638 amb 279 index_t index=0;
639 amb 643 int fd;
640 amb 256 SegmentX segmentx;
641 amb 110
642 amb 275 /* Print the start message */
643    
644 amb 519 printf_first("Measuring Segments: Segments=0");
645 amb 227
646 amb 555 /* Map into memory / open the file */
647 amb 257
648 amb 452 #if !SLIM
649 amb 1120 nodesx->data=MapFile(nodesx->filename_tmp);
650 amb 555 #else
651 amb 1120 nodesx->fd=ReOpenFile(nodesx->filename_tmp);
652 amb 452 #endif
653 amb 258
654 amb 1100 /* Allocate the way usage bitmask */
655    
656     segmentsx->usedway=AllocBitMask(waysx->number);
657    
658     assert(segmentsx->usedway); /* Check AllocBitMask() worked */
659    
660 amb 555 /* Re-open the file read-only and a new file writeable */
661 amb 275
662 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
663 amb 555
664 amb 1120 DeleteFile(segmentsx->filename_tmp);
665 amb 256
666 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
667 amb 256
668 amb 555 /* Modify the on-disk image */
669    
670 amb 256 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
671 amb 110 {
672 amb 279 index_t node1=IndexNodeX(nodesx,segmentx.node1);
673     index_t node2=IndexNodeX(nodesx,segmentx.node2);
674     index_t way =IndexWayX (waysx ,segmentx.way);
675 amb 110
676 amb 279 NodeX *nodex1=LookupNodeX(nodesx,node1,1);
677     NodeX *nodex2=LookupNodeX(nodesx,node2,2);
678    
679     /* Replace the node and way ids with their indexes */
680    
681     segmentx.node1=node1;
682     segmentx.node2=node2;
683     segmentx.way =way;
684    
685 amb 1100 SetBit(segmentsx->usedway,segmentx.way);
686    
687 amb 949 /* Set the distance but preserve the other flags */
688 amb 275
689     segmentx.distance|=DISTANCE(DistanceX(nodex1,nodex2));
690    
691 amb 279 /* Write the modified segment */
692    
693 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
694    
695 amb 279 index++;
696 amb 275
697 amb 279 if(!(index%10000))
698 amb 790 printf_middle("Measuring Segments: Segments=%"Pindex_t,index);
699 amb 275 }
700 amb 110
701 amb 555 /* Close the files */
702 amb 257
703 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
704 amb 275 CloseFile(fd);
705    
706 amb 280 /* Free the other now-unneeded indexes */
707 amb 279
708     free(nodesx->idata);
709     nodesx->idata=NULL;
710    
711     free(waysx->idata);
712     waysx->idata=NULL;
713    
714 amb 555 /* Unmap from memory / close the file */
715 amb 275
716 amb 452 #if !SLIM
717 amb 1120 nodesx->data=UnmapFile(nodesx->filename_tmp);
718 amb 555 #else
719 amb 612 nodesx->fd=CloseFile(nodesx->fd);
720 amb 452 #endif
721 amb 275
722     /* Print the final message */
723    
724 amb 790 printf_last("Measured Segments: Segments=%"Pindex_t,segmentsx->number);
725 amb 275 }
726    
727    
728     /*++++++++++++++++++++++++++++++++++++++
729     Remove the duplicate segments.
730 amb 110
731 amb 681 SegmentsX *segmentsx The set of segments to modify.
732 amb 110
733 amb 680 NodesX *nodesx The set of nodes to use.
734 amb 279
735 amb 680 WaysX *waysx The set of ways to use.
736 amb 110 ++++++++++++++++++++++++++++++++++++++*/
737    
738 amb 681 void DeduplicateSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
739 amb 110 {
740 amb 780 index_t duplicate=0,good=0;
741 amb 658 index_t index=0;
742     int fd,nprev=0;
743 amb 770 index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
744 amb 759 SegmentX prevsegx[MAX_SEG_PER_NODE],segmentx;
745     Way prevway[MAX_SEG_PER_NODE];
746 amb 110
747 amb 275 /* Print the start message */
748    
749 amb 519 printf_first("Deduplicating Segments: Segments=0 Duplicate=0");
750 amb 227
751 amb 555 /* Map into memory / open the file */
752 amb 256
753 amb 452 #if !SLIM
754 amb 1120 waysx->data=MapFile(waysx->filename_tmp);
755 amb 555 #else
756 amb 1120 waysx->fd=ReOpenFile(waysx->filename_tmp);
757 amb 452 #endif
758 amb 275
759 amb 555 /* Re-open the file read-only and a new file writeable */
760 amb 275
761 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
762 amb 555
763 amb 1120 DeleteFile(segmentsx->filename_tmp);
764 amb 275
765 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
766 amb 275
767 amb 555 /* Modify the on-disk image */
768    
769 amb 275 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
770 amb 110 {
771 amb 657 WayX *wayx=LookupWayX(waysx,segmentx.way,1);
772 amb 275 int isduplicate=0;
773 amb 256
774 amb 658 if(segmentx.node1==prevnode1 && segmentx.node2==prevnode2)
775 amb 110 {
776 amb 658 int offset;
777 amb 110
778 amb 658 for(offset=0;offset<nprev;offset++)
779 amb 110 {
780 amb 658 if(DISTFLAG(segmentx.distance)==DISTFLAG(prevsegx[offset].distance))
781 amb 657 if(!WaysCompare(&prevway[offset],&wayx->way))
782 amb 264 {
783 amb 275 isduplicate=1;
784     break;
785 amb 264 }
786 amb 658 }
787 amb 264
788 amb 658 if(isduplicate)
789     {
790     nprev--;
791    
792     for(;offset<nprev;offset++)
793     {
794     prevsegx[offset]=prevsegx[offset+1];
795     prevway[offset] =prevway[offset+1];
796     }
797 amb 110 }
798 amb 658 else
799     {
800 amb 759 assert(nprev<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */
801 amb 275
802 amb 658 prevsegx[nprev]=segmentx;
803     prevway[nprev] =wayx->way;
804 amb 666
805     nprev++;
806 amb 658 }
807 amb 110 }
808 amb 264 else
809     {
810 amb 658 nprev=1;
811     prevnode1=segmentx.node1;
812     prevnode2=segmentx.node2;
813     prevsegx[0]=segmentx;
814     prevway[0] =wayx->way;
815 amb 264 }
816 amb 110
817 amb 640 if(isduplicate)
818     duplicate++;
819     else
820 amb 110 {
821 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
822    
823     good++;
824     }
825    
826     index++;
827    
828     if(!(index%10000))
829 amb 790 printf_middle("Deduplicating Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t,index,duplicate);
830 amb 110 }
831    
832 amb 555 segmentsx->number=good;
833 amb 275
834 amb 555 /* Close the files */
835    
836 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
837 amb 275 CloseFile(fd);
838    
839 amb 555 /* Unmap from memory / close the file */
840 amb 275
841 amb 452 #if !SLIM
842 amb 1120 waysx->data=UnmapFile(waysx->filename_tmp);
843 amb 555 #else
844 amb 612 waysx->fd=CloseFile(waysx->fd);
845 amb 452 #endif
846 amb 275
847     /* Print the final message */
848    
849 amb 790 printf_last("Deduplicated Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t" Unique=%"Pindex_t,index,duplicate,good);
850 amb 110 }
851    
852    
853     /*++++++++++++++++++++++++++++++++++++++
854 amb 680 Index the segments by creating the firstnode index and filling in the segment next2 parameter.
855 amb 209
856 amb 681 SegmentsX *segmentsx The set of segments to modify.
857 amb 209
858 amb 1100 NodesX *nodesx The set of nodes to use.
859    
860     WaysX *waysx The set of ways to use.
861 amb 209 ++++++++++++++++++++++++++++++++++++++*/
862    
863 amb 1100 void IndexSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
864 amb 209 {
865 amb 780 index_t index,i;
866 amb 209
867 amb 660 if(segmentsx->number==0)
868     return;
869    
870 amb 275 /* Print the start message */
871    
872 amb 643 printf_first("Indexing Segments: Segments=0");
873 amb 227
874 amb 643 /* Allocate the array of indexes */
875    
876 amb 1102 if(segmentsx->firstnode)
877     free(segmentsx->firstnode);
878 amb 643
879 amb 1102 segmentsx->firstnode=(index_t*)malloc(nodesx->number*sizeof(index_t));
880 amb 643
881 amb 1102 assert(segmentsx->firstnode); /* Check malloc() worked */
882    
883 amb 643 for(i=0;i<nodesx->number;i++)
884     segmentsx->firstnode[i]=NO_SEGMENT;
885    
886 amb 555 /* Map into memory / open the files */
887 amb 209
888 amb 452 #if !SLIM
889 amb 1120 segmentsx->data=MapFileWriteable(segmentsx->filename_tmp);
890 amb 555 #else
891 amb 1120 segmentsx->fd=ReOpenFileWriteable(segmentsx->filename_tmp);
892 amb 452 #endif
893 amb 275
894 amb 643 /* Read through the segments in reverse order */
895 amb 280
896 amb 643 for(index=segmentsx->number-1;index!=NO_SEGMENT;index--)
897 amb 209 {
898 amb 643 SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
899 amb 209
900 amb 1098 if(nodesx->pdata)
901     {
902     segmentx->node1=nodesx->pdata[segmentx->node1];
903     segmentx->node2=nodesx->pdata[segmentx->node2];
904     }
905    
906 amb 1100 if(waysx->cdata)
907     segmentx->way=waysx->cdata[segmentx->way];
908    
909 amb 674 segmentx->next2=segmentsx->firstnode[segmentx->node2];
910 amb 209
911 amb 942 PutBackSegmentX(segmentsx,segmentx);
912 amb 448
913 amb 643 segmentsx->firstnode[segmentx->node1]=index;
914     segmentsx->firstnode[segmentx->node2]=index;
915 amb 558
916 amb 643 if(!(index%10000))
917 amb 790 printf_middle("Indexing Segments: Segments=%"Pindex_t,segmentsx->number-index);
918 amb 209 }
919    
920 amb 555 /* Unmap from memory / close the files */
921 amb 275
922 amb 452 #if !SLIM
923 amb 1120 segmentsx->data=UnmapFile(segmentsx->filename_tmp);
924 amb 555 #else
925 amb 643 segmentsx->fd=CloseFile(segmentsx->fd);
926 amb 452 #endif
927 amb 275
928 amb 1100 /* Free the memory */
929    
930     if(nodesx->pdata)
931     {
932     free(nodesx->pdata);
933     nodesx->pdata=NULL;
934     }
935    
936     if(waysx->cdata)
937     {
938     free(waysx->cdata);
939     waysx->cdata=NULL;
940     }
941    
942 amb 275 /* Print the final message */
943    
944 amb 790 printf_last("Indexed Segments: Segments=%"Pindex_t,segmentsx->number);
945 amb 209 }
946    
947    
948     /*++++++++++++++++++++++++++++++++++++++
949 amb 285 Save the segment list to a file.
950    
951 amb 681 SegmentsX *segmentsx The set of segments to save.
952 amb 285
953     const char *filename The name of the file to save.
954     ++++++++++++++++++++++++++++++++++++++*/
955    
956 amb 681 void SaveSegmentList(SegmentsX *segmentsx,const char *filename)
957 amb 285 {
958     index_t i;
959     int fd;
960 amb 500 SegmentsFile segmentsfile={0};
961 amb 780 index_t super_number=0,normal_number=0;
962 amb 285
963     /* Print the start message */
964    
965 amb 519 printf_first("Writing Segments: Segments=0");
966 amb 285
967 amb 558 /* Re-open the file */
968    
969 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
970 amb 558
971 amb 461 /* Write out the segments data */
972 amb 285
973 amb 502 fd=OpenFileNew(filename);
974 amb 461
975     SeekFile(fd,sizeof(SegmentsFile));
976    
977 amb 285 for(i=0;i<segmentsx->number;i++)
978     {
979 amb 643 SegmentX segmentx;
980 amb 944 Segment segment={0};
981 amb 448
982 amb 643 ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
983 amb 558
984 amb 643 segment.node1 =segmentx.node1;
985     segment.node2 =segmentx.node2;
986     segment.next2 =segmentx.next2;
987     segment.way =segmentx.way;
988     segment.distance=segmentx.distance;
989    
990 amb 558 if(IsSuperSegment(&segment))
991 amb 285 super_number++;
992 amb 558 if(IsNormalSegment(&segment))
993 amb 285 normal_number++;
994    
995 amb 558 WriteFile(fd,&segment,sizeof(Segment));
996 amb 448
997 amb 285 if(!((i+1)%10000))
998 amb 790 printf_middle("Writing Segments: Segments=%"Pindex_t,i+1);
999 amb 285 }
1000    
1001 amb 461 /* Write out the header structure */
1002    
1003     segmentsfile.number=segmentsx->number;
1004     segmentsfile.snumber=super_number;
1005     segmentsfile.nnumber=normal_number;
1006    
1007     SeekFile(fd,0);
1008     WriteFile(fd,&segmentsfile,sizeof(SegmentsFile));
1009    
1010 amb 285 CloseFile(fd);
1011    
1012 amb 558 /* Close the file */
1013    
1014 amb 643 segmentsx->fd=CloseFile(segmentsx->fd);
1015 amb 558
1016 amb 285 /* Print the final message */
1017    
1018 amb 790 printf_last("Wrote Segments: Segments=%"Pindex_t,segmentsx->number);
1019 amb 285 }
1020    
1021    
1022     /*++++++++++++++++++++++++++++++++++++++
1023 amb 110 Calculate the distance between two nodes.
1024    
1025     distance_t DistanceX Returns the distance between the extended nodes.
1026    
1027     NodeX *nodex1 The starting node.
1028    
1029     NodeX *nodex2 The end node.
1030     ++++++++++++++++++++++++++++++++++++++*/
1031    
1032 amb 228 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
1033 amb 110 {
1034 amb 223 double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude);
1035     double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude);
1036     double lat1 = latlong_to_radians(nodex1->latitude);
1037     double lat2 = latlong_to_radians(nodex2->latitude);
1038 amb 110
1039 amb 219 double a1,a2,a,sa,c,d;
1040 amb 110
1041     if(dlon==0 && dlat==0)
1042     return 0;
1043    
1044 amb 219 a1 = sin (dlat / 2);
1045     a2 = sin (dlon / 2);
1046     a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
1047     sa = sqrt (a);
1048 amb 110 if (sa <= 1.0)
1049 amb 219 {c = 2 * asin (sa);}
1050 amb 110 else
1051 amb 219 {c = 2 * asin (1.0);}
1052 amb 110 d = 6378.137 * c;
1053    
1054     return km_to_distance(d);
1055     }

Properties

Name Value
cvs:description Extended segments functions.