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 1231 - (show annotations) (download) (as text)
Thu Dec 27 14:00:23 2012 UTC (12 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 31670 byte(s)
Don't append segments if they are duplicates within a way or have duplicated
nodes.  Log errors for middle nodes that repeat within a way (can be non-trivial
unintentional loops).

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

Properties

Name Value
cvs:description Extended segments functions.