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 1169 - (show annotations) (download) (as text)
Wed Nov 21 11:12:04 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 31499 byte(s)
Finally fix the segment area handling - segments that are areas are discarded in
preference to those that are not (as it was between r914 and r1136) and segments
that are areas don't have the wrong distance (as they did between r914 and
r1136).

Revision r1137 correctly changed to use a flag and fixed the distance bug but
then didn't sort using the new flag.  Revision r1153 started sorting using the
segment flags but the area was not the most significant bit so they were not
sorted last.  Revision r1164 correctly cleared the area flag when no longer
needed but didn't fix the rest.  Revision r1168 reverted r1164 so needed to be
re-applied.

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

Properties

Name Value
cvs:description Extended segments functions.