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 1608 - (show annotations) (download) (as text)
Sat Oct 18 12:50:40 2014 UTC (10 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 26026 byte(s)
Use the waysx->idata array when logging duplicate segments rather than looking
up the wayx and using its id, also saves mapping the ways into memory.

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

Properties

Name Value
cvs:description Extended segments functions.