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 1153 - (show annotations) (download) (as text)
Sun Nov 18 17:30:44 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 30728 byte(s)
When sorting segments use the distance flags as the tie-breaker so that
duplicated segments with different flags get sorted into the same order when
applying changes as when not applying changes.

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

Properties

Name Value
cvs:description Extended segments functions.