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 2133 - (show annotations) (download) (as text)
Wed May 24 17:58:26 2023 UTC (21 months, 3 weeks ago) by amb
File MIME type: text/x-csrc
File size: 25619 byte(s)
Fix error with logging about the number of duplicated segments.

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

Properties

Name Value
cvs:description Extended segments functions.