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 1110 - (show annotations) (download) (as text)
Mon Oct 22 07:41:55 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 25671 byte(s)
Change the message after sorting geographically to be consistent with others.

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

Properties

Name Value
cvs:description Extended segments functions.