Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/segmentsx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1122 - (show annotations) (download) (as text)
Sat Nov 3 08:58:47 2012 UTC (12 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 26124 byte(s)
Change the UnmapFile() function to take a pointer to the data instead of the
filename (like the CloseFile() function takes the file descriptor).

1 /***************************************
2 Extended Segment data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2012 Andrew M. Bishop
7
8 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 ***************************************/
21
22
23 #include <assert.h>
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "types.h"
29 #include "segments.h"
30 #include "ways.h"
31
32 #include "typesx.h"
33 #include "nodesx.h"
34 #include "segmentsx.h"
35 #include "waysx.h"
36
37 #include "files.h"
38 #include "logging.h"
39 #include "sorting.h"
40
41
42 /* Global variables */
43
44 /*+ The command line '--tmpdir' option or its default value. +*/
45 extern char *option_tmpdirname;
46
47 /* Local variables */
48
49 /*+ Temporary file-local variables for use by the sort functions. +*/
50 static SegmentsX *sortsegmentsx;
51 static NodesX *sortnodesx;
52
53 /* Local functions */
54
55 static int sort_by_id(SegmentX *a,SegmentX *b);
56 static int delete_pruned(SegmentX *segmentx,index_t index);
57 static int geographically_index(SegmentX *segmentx,index_t index);
58
59 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2);
60
61
62 /*++++++++++++++++++++++++++++++++++++++
63 Allocate a new segment list (create a new file or open an existing one).
64
65 SegmentsX *NewSegmentList Returns the segment list.
66
67 int append Set to 1 if the file is to be opened for appending (now or later).
68 ++++++++++++++++++++++++++++++++++++++*/
69
70 SegmentsX *NewSegmentList(int append)
71 {
72 SegmentsX *segmentsx;
73
74 segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX));
75
76 assert(segmentsx); /* Check calloc() worked */
77
78 segmentsx->filename =(char*)malloc(strlen(option_tmpdirname)+32);
79 segmentsx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
80
81 sprintf(segmentsx->filename ,"%s/segmentsx.parsed.mem",option_tmpdirname);
82 sprintf(segmentsx->filename_tmp,"%s/segmentsx.%p.tmp" ,option_tmpdirname,(void*)segmentsx);
83
84 if(append)
85 {
86 off_t size;
87
88 segmentsx->fd=OpenFileAppend(segmentsx->filename);
89
90 size=SizeFile(segmentsx->filename);
91
92 segmentsx->number=size/sizeof(SegmentX);
93 }
94 else
95 segmentsx->fd=OpenFileNew(segmentsx->filename);
96
97 return(segmentsx);
98 }
99
100
101 /*++++++++++++++++++++++++++++++++++++++
102 Free a segment list.
103
104 SegmentsX *segmentsx The set of segments to be freed.
105
106 int keep Set to 1 if the file is to be kept (for appending later).
107 ++++++++++++++++++++++++++++++++++++++*/
108
109 void FreeSegmentList(SegmentsX *segmentsx,int keep)
110 {
111 if(!keep)
112 DeleteFile(segmentsx->filename);
113
114 DeleteFile(segmentsx->filename_tmp);
115
116 free(segmentsx->filename);
117 free(segmentsx->filename_tmp);
118
119 if(segmentsx->firstnode)
120 free(segmentsx->firstnode);
121
122 if(segmentsx->next1)
123 free(segmentsx->next1);
124
125 if(segmentsx->usednode)
126 free(segmentsx->usednode);
127
128 free(segmentsx);
129 }
130
131
132 /*++++++++++++++++++++++++++++++++++++++
133 Append a single segment to an unsorted segment list.
134
135 SegmentsX *segmentsx The set of segments to modify.
136
137 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 ++++++++++++++++++++++++++++++++++++++*/
145
146 void AppendSegment(SegmentsX *segmentsx,way_t way,node_t node1,node_t node2,distance_t distance)
147 {
148 SegmentX segmentx;
149
150 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 segmentx.node1=node1;
163 segmentx.node2=node2;
164 segmentx.next2=NO_SEGMENT;
165 segmentx.way=way;
166 segmentx.distance=distance;
167
168 WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
169
170 segmentsx->number++;
171
172 assert(segmentsx->number<SEGMENT_FAKE); /* SEGMENT_FAKE marks the high-water mark for real segments. */
173 }
174
175
176 /*++++++++++++++++++++++++++++++++++++++
177 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 Sort the segment list.
196
197 SegmentsX *segmentsx The set of segments to sort and modify.
198 ++++++++++++++++++++++++++++++++++++++*/
199
200 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 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
211
212 DeleteFile(segmentsx->filename_tmp);
213
214 fd=OpenFileNew(segmentsx->filename_tmp);
215
216 /* Sort by node indexes */
217
218 filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL,
219 (int (*)(const void*,const void*))sort_by_id,
220 NULL);
221
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 ++++++++++++++++++++++++++++++++++++++*/
240
241 void RemovePrunedSegments(SegmentsX *segmentsx,WaysX *waysx)
242 {
243 int fd;
244 index_t kept;
245
246 /* Print the start message */
247
248 printf_first("Sorting and Pruning Segments");
249
250 /* Close the file (finished appending) */
251
252 if(segmentsx->fd!=-1)
253 segmentsx->fd=CloseFile(segmentsx->fd);
254
255 /* Allocate the way usage bitmask */
256
257 segmentsx->usedway=AllocBitMask(waysx->number);
258
259 assert(segmentsx->usedway); /* Check AllocBitMask() worked */
260
261 /* Re-open the file read-only and a new file writeable */
262
263 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
264
265 DeleteFile(segmentsx->filename_tmp);
266
267 fd=OpenFileNew(segmentsx->filename_tmp);
268
269 /* Sort by node indexes */
270
271 sortsegmentsx=segmentsx;
272
273 kept=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))delete_pruned,
274 (int (*)(const void*,const void*))sort_by_id,
275 NULL);
276
277 /* Close the files */
278
279 segmentsx->fd=CloseFile(segmentsx->fd);
280 CloseFile(fd);
281
282 /* Print the final message */
283
284 printf_last("Sorted and Pruned Segments: Segments=%"Pindex_t" Deleted=%"Pindex_t,kept,segmentsx->number-kept);
285 segmentsx->number=kept;
286 }
287
288
289 /*++++++++++++++++++++++++++++++++++++++
290 Sort the segments into id order, first by node1 then by node2, finally by distance.
291
292 int sort_by_id Returns the comparison of the node fields.
293
294 SegmentX *a The first segment.
295
296 SegmentX *b The second segment.
297 ++++++++++++++++++++++++++++++++++++++*/
298
299 static int sort_by_id(SegmentX *a,SegmentX *b)
300 {
301 node_t a_id1=a->node1;
302 node_t b_id1=b->node1;
303
304 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 {
310 node_t a_id2=a->node2;
311 node_t b_id2=b->node2;
312
313 if(a_id2<b_id2)
314 return(-1);
315 else if(a_id2>b_id2)
316 return(1);
317 else
318 {
319 distance_t a_distance=DISTANCE(a->distance);
320 distance_t b_distance=DISTANCE(b->distance);
321
322 if(a_distance<b_distance)
323 return(-1);
324 else if(a_distance>b_distance)
325 return(1);
326 else
327 return(FILESORT_PRESERVE_ORDER(a,b));
328 }
329 }
330 }
331
332
333 /*++++++++++++++++++++++++++++++++++++++
334 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 index_t index The number of unsorted segments that have been read from the input file.
341 ++++++++++++++++++++++++++++++++++++++*/
342
343 static int delete_pruned(SegmentX *segmentx,index_t index)
344 {
345 if(IsPrunedSegmentX(segmentx))
346 return(0);
347
348 SetBit(sortsegmentsx->usedway,segmentx->way);
349
350 return(1);
351 }
352
353
354 /*++++++++++++++++++++++++++++++++++++++
355 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 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
373
374 DeleteFile(segmentsx->filename_tmp);
375
376 fd=OpenFileNew(segmentsx->filename_tmp);
377
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 printf_last("Sorted Segments Geographically: Segments=%"Pindex_t,segmentsx->number);
393 }
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 index_t index The number of unsorted segments that have been read from the input file.
404 ++++++++++++++++++++++++++++++++++++++*/
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 Find the first extended segment with a particular starting node index.
429
430 SegmentX *FirstSegmentX Returns a pointer to the first extended segment with the specified id.
431
432 SegmentsX *segmentsx The set of segments to use.
433
434 index_t nodeindex The node index to look for.
435
436 int position A flag to pass through.
437 ++++++++++++++++++++++++++++++++++++++*/
438
439 SegmentX *FirstSegmentX(SegmentsX *segmentsx,index_t nodeindex,int position)
440 {
441 index_t index=segmentsx->firstnode[nodeindex];
442 SegmentX *segmentx;
443
444 if(index==NO_SEGMENT)
445 return(NULL);
446
447 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 SegmentX *NextSegmentX Returns a pointer to the next segment with the same id.
457
458 SegmentsX *segmentsx The set of segments to use.
459
460 SegmentX *segmentx The current segment.
461
462 index_t nodeindex The node index.
463 ++++++++++++++++++++++++++++++++++++++*/
464
465 SegmentX *NextSegmentX(SegmentsX *segmentsx,SegmentX *segmentx,index_t nodeindex)
466 {
467 #if SLIM
468 int position=1+(segmentx-&segmentsx->cached[0]);
469 #endif
470
471 if(segmentx->node1==nodeindex)
472 {
473 if(segmentsx->next1)
474 {
475 index_t index=IndexSegmentX(segmentsx,segmentx);
476
477 if(segmentsx->next1[index]==NO_SEGMENT)
478 return(NULL);
479
480 segmentx=LookupSegmentX(segmentsx,segmentsx->next1[index],position);
481
482 return(segmentx);
483 }
484 else
485 {
486 #if SLIM
487 index_t index=IndexSegmentX(segmentsx,segmentx);
488 index++;
489
490 if(index>=segmentsx->number)
491 return(NULL);
492
493 segmentx=LookupSegmentX(segmentsx,index,position);
494 #else
495 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 return(segmentx);
505 }
506 }
507 else
508 {
509 if(segmentx->next2==NO_SEGMENT)
510 return(NULL);
511
512 return(LookupSegmentX(segmentsx,segmentx->next2,position));
513 }
514 }
515
516
517 /*++++++++++++++++++++++++++++++++++++++
518 Remove bad segments (duplicated, zero length or with missing nodes).
519
520 NodesX *nodesx The set of nodes to use.
521
522 SegmentsX *segmentsx The set of segments to modify.
523 ++++++++++++++++++++++++++++++++++++++*/
524
525 void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
526 {
527 index_t duplicate=0,loop=0,nonode=0,good=0,total=0;
528 SegmentX segmentx;
529 int fd;
530 node_t prevnode1=NO_NODE_ID,prevnode2=NO_NODE_ID;
531 distance_t prevdist=0;
532
533 /* Print the start message */
534
535 printf_first("Checking Segments: Segments=0 Duplicate=0 Loop=0 No-Node=0");
536
537 /* Allocate the node usage bitmask */
538
539 segmentsx->usednode=AllocBitMask(nodesx->number);
540
541 assert(segmentsx->usednode); /* Check AllocBitMask() worked */
542
543 /* Re-open the file read-only and a new file writeable */
544
545 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
546
547 DeleteFile(segmentsx->filename_tmp);
548
549 fd=OpenFileNew(segmentsx->filename_tmp);
550
551 /* Modify the on-disk image */
552
553 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
554 {
555 index_t index1=IndexNodeX(nodesx,segmentx.node1);
556 index_t index2=IndexNodeX(nodesx,segmentx.node2);
557
558 if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2)
559 {
560 if(!prevdist && !DISTANCE(segmentx.distance))
561 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated.\n",segmentx.node1,segmentx.node2);
562
563 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 duplicate++;
573 }
574 else if(segmentx.node1==segmentx.node2)
575 {
576 logerror("Segment connects node %"Pnode_t" to itself.\n",segmentx.node1);
577
578 loop++;
579 }
580 else if(index1==NO_NODE || index2==NO_NODE)
581 {
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 nonode++;
592 }
593 else
594 {
595 WriteFile(fd,&segmentx,sizeof(SegmentX));
596
597 SetBit(segmentsx->usednode,index1);
598 SetBit(segmentsx->usednode,index2);
599
600 good++;
601
602 prevnode1=segmentx.node1;
603 prevnode2=segmentx.node2;
604 prevdist=DISTANCE(segmentx.distance);
605 }
606
607 total++;
608
609 if(!(total%10000))
610 printf_middle("Checking Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t" Loop=%"Pindex_t" No-Node=%"Pindex_t,total,duplicate,loop,nonode);
611 }
612
613 segmentsx->number=good;
614
615 /* Close the files */
616
617 segmentsx->fd=CloseFile(segmentsx->fd);
618 CloseFile(fd);
619
620 /* Print the final message */
621
622 printf_last("Checked Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t" Loop=%"Pindex_t" No-Node=%"Pindex_t,total,duplicate,loop,nonode);
623 }
624
625
626 /*++++++++++++++++++++++++++++++++++++++
627 Measure the segments and replace node/way ids with indexes.
628
629 SegmentsX *segmentsx The set of segments to process.
630
631 NodesX *nodesx The set of nodes to use.
632
633 WaysX *waysx The set of ways to use.
634 ++++++++++++++++++++++++++++++++++++++*/
635
636 void MeasureSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
637 {
638 index_t index=0;
639 int fd;
640 SegmentX segmentx;
641
642 /* Print the start message */
643
644 printf_first("Measuring Segments: Segments=0");
645
646 /* Map into memory / open the file */
647
648 #if !SLIM
649 nodesx->data=MapFile(nodesx->filename_tmp);
650 #else
651 nodesx->fd=ReOpenFile(nodesx->filename_tmp);
652 #endif
653
654 /* Allocate the way usage bitmask */
655
656 segmentsx->usedway=AllocBitMask(waysx->number);
657
658 assert(segmentsx->usedway); /* Check AllocBitMask() worked */
659
660 /* Re-open the file read-only and a new file writeable */
661
662 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
663
664 DeleteFile(segmentsx->filename_tmp);
665
666 fd=OpenFileNew(segmentsx->filename_tmp);
667
668 /* Modify the on-disk image */
669
670 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
671 {
672 index_t node1=IndexNodeX(nodesx,segmentx.node1);
673 index_t node2=IndexNodeX(nodesx,segmentx.node2);
674 index_t way =IndexWayX (waysx ,segmentx.way);
675
676 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 SetBit(segmentsx->usedway,segmentx.way);
686
687 /* Set the distance but preserve the other flags */
688
689 segmentx.distance|=DISTANCE(DistanceX(nodex1,nodex2));
690
691 /* Write the modified segment */
692
693 WriteFile(fd,&segmentx,sizeof(SegmentX));
694
695 index++;
696
697 if(!(index%10000))
698 printf_middle("Measuring Segments: Segments=%"Pindex_t,index);
699 }
700
701 /* Close the files */
702
703 segmentsx->fd=CloseFile(segmentsx->fd);
704 CloseFile(fd);
705
706 /* Free the other now-unneeded indexes */
707
708 free(nodesx->idata);
709 nodesx->idata=NULL;
710
711 free(waysx->idata);
712 waysx->idata=NULL;
713
714 /* Unmap from memory / close the file */
715
716 #if !SLIM
717 nodesx->data=UnmapFile(nodesx->data);
718 #else
719 nodesx->fd=CloseFile(nodesx->fd);
720 #endif
721
722 /* Print the final message */
723
724 printf_last("Measured Segments: Segments=%"Pindex_t,segmentsx->number);
725 }
726
727
728 /*++++++++++++++++++++++++++++++++++++++
729 Remove the duplicate segments.
730
731 SegmentsX *segmentsx The set of segments to modify.
732
733 NodesX *nodesx The set of nodes to use.
734
735 WaysX *waysx The set of ways to use.
736 ++++++++++++++++++++++++++++++++++++++*/
737
738 void DeduplicateSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
739 {
740 index_t duplicate=0,good=0;
741 index_t index=0;
742 int fd,nprev=0;
743 index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
744 SegmentX prevsegx[MAX_SEG_PER_NODE],segmentx;
745 Way prevway[MAX_SEG_PER_NODE];
746
747 /* Print the start message */
748
749 printf_first("Deduplicating Segments: Segments=0 Duplicate=0");
750
751 /* Map into memory / open the file */
752
753 #if !SLIM
754 waysx->data=MapFile(waysx->filename_tmp);
755 #else
756 waysx->fd=ReOpenFile(waysx->filename_tmp);
757 #endif
758
759 /* Re-open the file read-only and a new file writeable */
760
761 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
762
763 DeleteFile(segmentsx->filename_tmp);
764
765 fd=OpenFileNew(segmentsx->filename_tmp);
766
767 /* Modify the on-disk image */
768
769 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
770 {
771 WayX *wayx=LookupWayX(waysx,segmentx.way,1);
772 int isduplicate=0;
773
774 if(segmentx.node1==prevnode1 && segmentx.node2==prevnode2)
775 {
776 int offset;
777
778 for(offset=0;offset<nprev;offset++)
779 {
780 if(DISTFLAG(segmentx.distance)==DISTFLAG(prevsegx[offset].distance))
781 if(!WaysCompare(&prevway[offset],&wayx->way))
782 {
783 isduplicate=1;
784 break;
785 }
786 }
787
788 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 }
798 else
799 {
800 assert(nprev<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */
801
802 prevsegx[nprev]=segmentx;
803 prevway[nprev] =wayx->way;
804
805 nprev++;
806 }
807 }
808 else
809 {
810 nprev=1;
811 prevnode1=segmentx.node1;
812 prevnode2=segmentx.node2;
813 prevsegx[0]=segmentx;
814 prevway[0] =wayx->way;
815 }
816
817 if(isduplicate)
818 duplicate++;
819 else
820 {
821 WriteFile(fd,&segmentx,sizeof(SegmentX));
822
823 good++;
824 }
825
826 index++;
827
828 if(!(index%10000))
829 printf_middle("Deduplicating Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t,index,duplicate);
830 }
831
832 segmentsx->number=good;
833
834 /* Close the files */
835
836 segmentsx->fd=CloseFile(segmentsx->fd);
837 CloseFile(fd);
838
839 /* Unmap from memory / close the file */
840
841 #if !SLIM
842 waysx->data=UnmapFile(waysx->data);
843 #else
844 waysx->fd=CloseFile(waysx->fd);
845 #endif
846
847 /* Print the final message */
848
849 printf_last("Deduplicated Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t" Unique=%"Pindex_t,index,duplicate,good);
850 }
851
852
853 /*++++++++++++++++++++++++++++++++++++++
854 Index the segments by creating the firstnode index and filling in the segment next2 parameter.
855
856 SegmentsX *segmentsx The set of segments to modify.
857
858 NodesX *nodesx The set of nodes to use.
859
860 WaysX *waysx The set of ways to use.
861 ++++++++++++++++++++++++++++++++++++++*/
862
863 void IndexSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
864 {
865 index_t index,i;
866
867 if(segmentsx->number==0)
868 return;
869
870 /* Print the start message */
871
872 printf_first("Indexing Segments: Segments=0");
873
874 /* Allocate the array of indexes */
875
876 if(segmentsx->firstnode)
877 free(segmentsx->firstnode);
878
879 segmentsx->firstnode=(index_t*)malloc(nodesx->number*sizeof(index_t));
880
881 assert(segmentsx->firstnode); /* Check malloc() worked */
882
883 for(i=0;i<nodesx->number;i++)
884 segmentsx->firstnode[i]=NO_SEGMENT;
885
886 /* Map into memory / open the files */
887
888 #if !SLIM
889 segmentsx->data=MapFileWriteable(segmentsx->filename_tmp);
890 #else
891 segmentsx->fd=ReOpenFileWriteable(segmentsx->filename_tmp);
892 #endif
893
894 /* Read through the segments in reverse order */
895
896 for(index=segmentsx->number-1;index!=NO_SEGMENT;index--)
897 {
898 SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
899
900 if(nodesx->pdata)
901 {
902 segmentx->node1=nodesx->pdata[segmentx->node1];
903 segmentx->node2=nodesx->pdata[segmentx->node2];
904 }
905
906 if(waysx->cdata)
907 segmentx->way=waysx->cdata[segmentx->way];
908
909 segmentx->next2=segmentsx->firstnode[segmentx->node2];
910
911 PutBackSegmentX(segmentsx,segmentx);
912
913 segmentsx->firstnode[segmentx->node1]=index;
914 segmentsx->firstnode[segmentx->node2]=index;
915
916 if(!(index%10000))
917 printf_middle("Indexing Segments: Segments=%"Pindex_t,segmentsx->number-index);
918 }
919
920 /* Unmap from memory / close the files */
921
922 #if !SLIM
923 segmentsx->data=UnmapFile(segmentsx->data);
924 #else
925 segmentsx->fd=CloseFile(segmentsx->fd);
926 #endif
927
928 /* 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 /* Print the final message */
943
944 printf_last("Indexed Segments: Segments=%"Pindex_t,segmentsx->number);
945 }
946
947
948 /*++++++++++++++++++++++++++++++++++++++
949 Save the segment list to a file.
950
951 SegmentsX *segmentsx The set of segments to save.
952
953 const char *filename The name of the file to save.
954 ++++++++++++++++++++++++++++++++++++++*/
955
956 void SaveSegmentList(SegmentsX *segmentsx,const char *filename)
957 {
958 index_t i;
959 int fd;
960 SegmentsFile segmentsfile={0};
961 index_t super_number=0,normal_number=0;
962
963 /* Print the start message */
964
965 printf_first("Writing Segments: Segments=0");
966
967 /* Re-open the file */
968
969 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
970
971 /* Write out the segments data */
972
973 fd=OpenFileNew(filename);
974
975 SeekFile(fd,sizeof(SegmentsFile));
976
977 for(i=0;i<segmentsx->number;i++)
978 {
979 SegmentX segmentx;
980 Segment segment={0};
981
982 ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
983
984 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 if(IsSuperSegment(&segment))
991 super_number++;
992 if(IsNormalSegment(&segment))
993 normal_number++;
994
995 WriteFile(fd,&segment,sizeof(Segment));
996
997 if(!((i+1)%10000))
998 printf_middle("Writing Segments: Segments=%"Pindex_t,i+1);
999 }
1000
1001 /* 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 CloseFile(fd);
1011
1012 /* Close the file */
1013
1014 segmentsx->fd=CloseFile(segmentsx->fd);
1015
1016 /* Print the final message */
1017
1018 printf_last("Wrote Segments: Segments=%"Pindex_t,segmentsx->number);
1019 }
1020
1021
1022 /*++++++++++++++++++++++++++++++++++++++
1023 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 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
1033 {
1034 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
1039 double a1,a2,a,sa,c,d;
1040
1041 if(dlon==0 && dlat==0)
1042 return 0;
1043
1044 a1 = sin (dlat / 2);
1045 a2 = sin (dlon / 2);
1046 a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
1047 sa = sqrt (a);
1048 if (sa <= 1.0)
1049 {c = 2 * asin (sa);}
1050 else
1051 {c = 2 * asin (1.0);}
1052 d = 6378.137 * c;
1053
1054 return km_to_distance(d);
1055 }

Properties

Name Value
cvs:description Extended segments functions.