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 1351 - (show annotations) (download) (as text)
Thu May 30 17:33:21 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 25867 byte(s)
Merge the RemoveBadSegments() and MeasureSegments() functions.  Saves one
read/write iteration through the segments file.

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

Properties

Name Value
cvs:description Extended segments functions.