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 1431 - (show annotations) (download) (as text)
Fri Jun 28 14:39:14 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 25712 byte(s)
Revert the last three changes because r1430 didn't work and r1428+r1429 didn't
give any speed advantage and was possibly marginally slower.

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

Properties

Name Value
cvs:description Extended segments functions.