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 1137 - (show annotations) (download) (as text)
Sun Nov 11 16:05:10 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 27430 byte(s)
Mark those segments that come from ways which are areas with an explicit flag
rather than an implicit one (also fixes a bug).

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

Properties

Name Value
cvs:description Extended segments functions.