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 1347 - (show annotations) (download) (as text)
Mon May 27 17:36:11 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 28768 byte(s)
Redistributed error log messages from osmparser way handling.

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 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" in way %"Pway_t" is duplicated.\n",logerror_node(segmentx.node1),logerror_node(segmentx.node2),logerror_way(segmentx.way));
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.