Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/segmentsx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1146 - (hide annotations) (download) (as text)
Sat Nov 17 14:06:57 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 30532 byte(s)
Suppress some error log messages when applying changes (false positive duplicate
detection due to modification of existing items).

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

Properties

Name Value
cvs:description Extended segments functions.