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 1339 - (show annotations) (download) (as text)
Thu May 23 17:47:16 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 28682 byte(s)
Don't create segments when parsing input file but create the segments later
using the nodes stored in the ways file.  This makes applying changes simpler
(segments file is not kept with the --keep option) and handling changed ways is
simpler than changed segments.

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

Properties

Name Value
cvs:description Extended segments functions.