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 1408 - (show annotations) (download) (as text)
Fri Jun 21 14:43:37 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 25011 byte(s)
Use the new functions for buffering while reading when looping through files
other than the ones already done that use the FILESORT_VARINT method of storing
data.

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=ReOpenFile(segmentsx->filename_tmp);
284
285 DeleteFile(segmentsx->filename_tmp);
286
287 fd=OpenFileNew(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=CloseFile(segmentsx->fd);
298 CloseFile(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=ReOpenFile(nodesx->filename_tmp);
390 waysx->fd=ReOpenFile(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=CloseFile(nodesx->fd);
485 waysx->fd=CloseFile(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,i;
507
508 if(segmentsx->number==0)
509 return;
510
511 /* Print the start message */
512
513 printf_first("Indexing Segments: Segments=0");
514
515 /* Allocate the array of indexes */
516
517 if(segmentsx->firstnode)
518 free(segmentsx->firstnode);
519
520 segmentsx->firstnode=(index_t*)malloc(nodesx->number*sizeof(index_t));
521
522 logassert(segmentsx->firstnode,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
523
524 for(i=0;i<nodesx->number;i++)
525 segmentsx->firstnode[i]=NO_SEGMENT;
526
527 /* Map into memory / open the files */
528
529 #if !SLIM
530 segmentsx->data=MapFileWriteable(segmentsx->filename_tmp);
531 #else
532 segmentsx->fd=ReOpenFileWriteable(segmentsx->filename_tmp);
533
534 InvalidateSegmentXCache(segmentsx->cache);
535 #endif
536
537 /* Read through the segments in reverse order */
538
539 for(index=segmentsx->number-1;index!=NO_SEGMENT;index--)
540 {
541 SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
542
543 if(nodesx->pdata)
544 {
545 segmentx->node1=nodesx->pdata[segmentx->node1];
546 segmentx->node2=nodesx->pdata[segmentx->node2];
547 }
548
549 if(waysx->cdata)
550 segmentx->way=waysx->cdata[segmentx->way];
551
552 segmentx->next2=segmentsx->firstnode[segmentx->node2];
553
554 PutBackSegmentX(segmentsx,segmentx);
555
556 segmentsx->firstnode[segmentx->node1]=index;
557 segmentsx->firstnode[segmentx->node2]=index;
558
559 if(!(index%10000))
560 printf_middle("Indexing Segments: Segments=%"Pindex_t,segmentsx->number-index);
561 }
562
563 /* Unmap from memory / close the files */
564
565 #if !SLIM
566 segmentsx->data=UnmapFile(segmentsx->data);
567 #else
568 segmentsx->fd=CloseFile(segmentsx->fd);
569 #endif
570
571 /* Free the memory */
572
573 if(nodesx->pdata)
574 {
575 free(nodesx->pdata);
576 nodesx->pdata=NULL;
577 }
578
579 if(waysx->cdata)
580 {
581 free(waysx->cdata);
582 waysx->cdata=NULL;
583 }
584
585 /* Print the final message */
586
587 printf_last("Indexed Segments: Segments=%"Pindex_t,segmentsx->number);
588 }
589
590
591 /*++++++++++++++++++++++++++++++++++++++
592 Prune the deleted segments while resorting the list.
593
594 SegmentsX *segmentsx The set of segments to sort and modify.
595
596 WaysX *waysx The set of ways to check.
597 ++++++++++++++++++++++++++++++++++++++*/
598
599 void RemovePrunedSegments(SegmentsX *segmentsx,WaysX *waysx)
600 {
601 int fd;
602 index_t xnumber;
603
604 if(segmentsx->number==0)
605 return;
606
607 /* Print the start message */
608
609 printf_first("Sorting and Pruning Segments");
610
611 /* Allocate the way usage bitmask */
612
613 segmentsx->usedway=AllocBitMask(waysx->number);
614
615 logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
616
617 /* Re-open the file read-only and a new file writeable */
618
619 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
620
621 DeleteFile(segmentsx->filename_tmp);
622
623 fd=OpenFileNew(segmentsx->filename_tmp);
624
625 /* Sort by node indexes */
626
627 xnumber=segmentsx->number;
628
629 sortsegmentsx=segmentsx;
630
631 segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))delete_pruned,
632 (int (*)(const void*,const void*))sort_by_id,
633 NULL);
634
635 /* Close the files */
636
637 segmentsx->fd=CloseFile(segmentsx->fd);
638 CloseFile(fd);
639
640 /* Print the final message */
641
642 printf_last("Sorted and Pruned Segments: Segments=%"Pindex_t" Deleted=%"Pindex_t,xnumber,xnumber-segmentsx->number);
643 }
644
645
646 /*++++++++++++++++++++++++++++++++++++++
647 Delete the pruned segments.
648
649 int delete_pruned Return 1 if the value is to be kept, otherwise 0.
650
651 SegmentX *segmentx The extended segment.
652
653 index_t index The number of unsorted segments that have been read from the input file.
654 ++++++++++++++++++++++++++++++++++++++*/
655
656 static int delete_pruned(SegmentX *segmentx,index_t index)
657 {
658 if(IsPrunedSegmentX(segmentx))
659 return(0);
660
661 SetBit(sortsegmentsx->usedway,segmentx->way);
662
663 return(1);
664 }
665
666
667 /*++++++++++++++++++++++++++++++++++++++
668 Remove the duplicate super-segments.
669
670 SegmentsX *segmentsx The set of super-segments to modify.
671
672 WaysX *waysx The set of ways to use.
673 ++++++++++++++++++++++++++++++++++++++*/
674
675 void DeduplicateSuperSegments(SegmentsX *segmentsx,WaysX *waysx)
676 {
677 int fd;
678 index_t xnumber;
679
680 if(waysx->number==0)
681 return;
682
683 /* Print the start message */
684
685 printf_first("Sorting and Deduplicating Super-Segments");
686
687 /* Map into memory / open the file */
688
689 #if !SLIM
690 waysx->data=MapFile(waysx->filename_tmp);
691 #else
692 waysx->fd=ReOpenFile(waysx->filename_tmp);
693
694 InvalidateWayXCache(waysx->cache);
695 #endif
696
697 /* Re-open the file read-only and a new file writeable */
698
699 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
700
701 DeleteFile(segmentsx->filename_tmp);
702
703 fd=OpenFileNew(segmentsx->filename_tmp);
704
705 /* Sort by node indexes */
706
707 xnumber=segmentsx->number;
708
709 sortsegmentsx=segmentsx;
710 sortwaysx=waysx;
711
712 segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL,
713 (int (*)(const void*,const void*))sort_by_id,
714 (int (*)(void*,index_t))deduplicate_super);
715
716 /* Close the files */
717
718 segmentsx->fd=CloseFile(segmentsx->fd);
719 CloseFile(fd);
720
721 /* Unmap from memory / close the file */
722
723 #if !SLIM
724 waysx->data=UnmapFile(waysx->data);
725 #else
726 waysx->fd=CloseFile(waysx->fd);
727 #endif
728
729 /* Print the final message */
730
731 printf_last("Sorted and Deduplicated Super-Segments: Super-Segments=%"Pindex_t" Duplicate=%"Pindex_t,xnumber,xnumber-segmentsx->number);
732 }
733
734
735 /*++++++++++++++++++++++++++++++++++++++
736 De-duplicate super-segments.
737
738 int deduplicate_super Return 1 if the value is to be kept, otherwise 0.
739
740 SegmentX *segmentx The extended super-segment.
741
742 index_t index The number of sorted super-segments that have already been written to the output file.
743 ++++++++++++++++++++++++++++++++++++++*/
744
745 static int deduplicate_super(SegmentX *segmentx,index_t index)
746 {
747 static int nprev=0;
748 static index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
749 static SegmentX prevsegx[MAX_SEG_PER_NODE];
750 static Way prevway[MAX_SEG_PER_NODE];
751
752 WayX *wayx=LookupWayX(sortwaysx,segmentx->way,1);
753 int isduplicate=0;
754
755 if(index==0 || segmentx->node1!=prevnode1 || segmentx->node2!=prevnode2)
756 {
757 nprev=1;
758 prevnode1=segmentx->node1;
759 prevnode2=segmentx->node2;
760 prevsegx[0]=*segmentx;
761 prevway[0] =wayx->way;
762 }
763 else
764 {
765 int offset;
766
767 for(offset=0;offset<nprev;offset++)
768 {
769 if(DISTFLAG(segmentx->distance)==DISTFLAG(prevsegx[offset].distance))
770 if(!WaysCompare(&prevway[offset],&wayx->way))
771 {
772 isduplicate=1;
773 break;
774 }
775 }
776
777 if(isduplicate)
778 {
779 nprev--;
780
781 for(;offset<nprev;offset++)
782 {
783 prevsegx[offset]=prevsegx[offset+1];
784 prevway[offset] =prevway[offset+1];
785 }
786 }
787 else
788 {
789 logassert(nprev<MAX_SEG_PER_NODE,"Too many segments for one node (increase MAX_SEG_PER_NODE?)"); /* Only a limited amount of information stored. */
790
791 prevsegx[nprev]=*segmentx;
792 prevway[nprev] =wayx->way;
793
794 nprev++;
795 }
796 }
797
798 return(!isduplicate);
799 }
800
801
802 /*++++++++++++++++++++++++++++++++++++++
803 Sort the segments geographically after updating the node indexes.
804
805 SegmentsX *segmentsx The set of segments to modify.
806
807 NodesX *nodesx The set of nodes to use.
808 ++++++++++++++++++++++++++++++++++++++*/
809
810 void SortSegmentListGeographically(SegmentsX *segmentsx,NodesX *nodesx)
811 {
812 int fd;
813
814 if(segmentsx->number==0)
815 return;
816
817 /* Print the start message */
818
819 printf_first("Sorting Segments Geographically");
820
821 /* Re-open the file read-only and a new file writeable */
822
823 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
824
825 DeleteFile(segmentsx->filename_tmp);
826
827 fd=OpenFileNew(segmentsx->filename_tmp);
828
829 /* Update the segments with geographically sorted node indexes and sort them */
830
831 sortnodesx=nodesx;
832
833 filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))geographically_index,
834 (int (*)(const void*,const void*))sort_by_id,
835 NULL);
836 /* Close the files */
837
838 segmentsx->fd=CloseFile(segmentsx->fd);
839 CloseFile(fd);
840
841 /* Print the final message */
842
843 printf_last("Sorted Segments Geographically: Segments=%"Pindex_t,segmentsx->number);
844 }
845
846
847 /*++++++++++++++++++++++++++++++++++++++
848 Update the segment indexes.
849
850 int geographically_index Return 1 if the value is to be kept, otherwise 0.
851
852 SegmentX *segmentx The extended segment.
853
854 index_t index The number of unsorted segments that have been read from the input file.
855 ++++++++++++++++++++++++++++++++++++++*/
856
857 static int geographically_index(SegmentX *segmentx,index_t index)
858 {
859 segmentx->node1=sortnodesx->gdata[segmentx->node1];
860 segmentx->node2=sortnodesx->gdata[segmentx->node2];
861
862 if(segmentx->node1>segmentx->node2)
863 {
864 index_t temp;
865
866 temp=segmentx->node1;
867 segmentx->node1=segmentx->node2;
868 segmentx->node2=temp;
869
870 if(segmentx->distance&(ONEWAY_2TO1|ONEWAY_1TO2))
871 segmentx->distance^=ONEWAY_2TO1|ONEWAY_1TO2;
872 }
873
874 return(1);
875 }
876
877
878 /*++++++++++++++++++++++++++++++++++++++
879 Save the segment list to a file.
880
881 SegmentsX *segmentsx The set of segments to save.
882
883 const char *filename The name of the file to save.
884 ++++++++++++++++++++++++++++++++++++++*/
885
886 void SaveSegmentList(SegmentsX *segmentsx,const char *filename)
887 {
888 index_t i;
889 int fd;
890 SegmentsFile segmentsfile={0};
891 index_t super_number=0,normal_number=0;
892
893 /* Print the start message */
894
895 printf_first("Writing Segments: Segments=0");
896
897 /* Re-open the file */
898
899 segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp);
900
901 /* Write out the segments data */
902
903 fd=OpenFileBufferedNew(filename);
904
905 SeekFileBuffered(fd,sizeof(SegmentsFile));
906
907 for(i=0;i<segmentsx->number;i++)
908 {
909 SegmentX segmentx;
910 Segment segment={0};
911
912 ReadFileBuffered(segmentsx->fd,&segmentx,sizeof(SegmentX));
913
914 segment.node1 =segmentx.node1;
915 segment.node2 =segmentx.node2;
916 segment.next2 =segmentx.next2;
917 segment.way =segmentx.way;
918 segment.distance=segmentx.distance;
919
920 if(IsSuperSegment(&segment))
921 super_number++;
922 if(IsNormalSegment(&segment))
923 normal_number++;
924
925 WriteFileBuffered(fd,&segment,sizeof(Segment));
926
927 if(!((i+1)%10000))
928 printf_middle("Writing Segments: Segments=%"Pindex_t,i+1);
929 }
930
931 /* Write out the header structure */
932
933 segmentsfile.number=segmentsx->number;
934 segmentsfile.snumber=super_number;
935 segmentsfile.nnumber=normal_number;
936
937 SeekFileBuffered(fd,0);
938 WriteFileBuffered(fd,&segmentsfile,sizeof(SegmentsFile));
939
940 CloseFileBuffered(fd);
941
942 /* Close the file */
943
944 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
945
946 /* Print the final message */
947
948 printf_last("Wrote Segments: Segments=%"Pindex_t,segmentsx->number);
949 }
950
951
952 /*++++++++++++++++++++++++++++++++++++++
953 Calculate the distance between two nodes.
954
955 distance_t DistanceX Returns the distance between the extended nodes.
956
957 NodeX *nodex1 The starting node.
958
959 NodeX *nodex2 The end node.
960 ++++++++++++++++++++++++++++++++++++++*/
961
962 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
963 {
964 double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude);
965 double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude);
966 double lat1 = latlong_to_radians(nodex1->latitude);
967 double lat2 = latlong_to_radians(nodex2->latitude);
968
969 double a1,a2,a,sa,c,d;
970
971 if(dlon==0 && dlat==0)
972 return 0;
973
974 a1 = sin (dlat / 2);
975 a2 = sin (dlon / 2);
976 a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
977 sa = sqrt (a);
978 if (sa <= 1.0)
979 {c = 2 * asin (sa);}
980 else
981 {c = 2 * asin (1.0);}
982 d = 6378.137 * c;
983
984 return km_to_distance(d);
985 }

Properties

Name Value
cvs:description Extended segments functions.