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 1297 - (show annotations) (download) (as text)
Tue May 7 14:41:11 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 31903 byte(s)
Add cache functions for NodesX, SegmentsX and WaysX to speed up the
planetsplitter in slim mode.

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

Properties

Name Value
cvs:description Extended segments functions.