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 1131 - (show annotations) (download) (as text)
Sat Nov 10 12:18:56 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 27753 byte(s)
De-duplicate the raw segments before any other processing (to match the node,
way and turn relation processing).

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

Properties

Name Value
cvs:description Extended segments functions.