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 1429 - (show annotations) (download) (as text)
Thu Jun 27 19:02:48 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 25168 byte(s)
Fixed error with last checkin.

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

Properties

Name Value
cvs:description Extended segments functions.