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 1140 - (show annotations) (download) (as text)
Fri Nov 16 18:47:07 2012 UTC (12 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 30359 byte(s)
Code to allow adding OSC change files (.osc files) to an existing set of parsed
(and preserved) data.

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

Properties

Name Value
cvs:description Extended segments functions.