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 1169 - (hide annotations) (download) (as text)
Wed Nov 21 11:12:04 2012 UTC (12 years, 3 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 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 <math.h>
24     #include <stdlib.h>
25 amb 955 #include <string.h>
26 amb 110
27     #include "types.h"
28 amb 228 #include "segments.h"
29     #include "ways.h"
30 amb 110
31 amb 955 #include "typesx.h"
32 amb 449 #include "nodesx.h"
33     #include "segmentsx.h"
34     #include "waysx.h"
35 amb 110
36 amb 449 #include "files.h"
37 amb 519 #include "logging.h"
38 amb 532 #include "sorting.h"
39 amb 449
40    
41 amb 680 /* Global variables */
42 amb 110
43 amb 289 /*+ The command line '--tmpdir' option or its default value. +*/
44 amb 284 extern char *option_tmpdirname;
45 amb 110
46 amb 1146 /*+ The option to apply changes (needed to suppress some error log messages) +*/
47     extern int option_changes;
48    
49 amb 1100 /* Local variables */
50    
51 amb 1107 /*+ Temporary file-local variables for use by the sort functions. +*/
52 amb 1132 static NodesX *sortnodesx;
53 amb 1100 static SegmentsX *sortsegmentsx;
54 amb 1132 static WaysX *sortwaysx;
55 amb 1100
56 amb 680 /* Local functions */
57 amb 110
58 amb 1140 static int sort_by_way_id(SegmentX *a,SegmentX *b);
59     static int apply_changes(SegmentX *segmentx,index_t index);
60 amb 1160
61 amb 275 static int sort_by_id(SegmentX *a,SegmentX *b);
62 amb 1155 static int deduplicate(SegmentX *segmentx,index_t index);
63 amb 1160
64 amb 949 static int delete_pruned(SegmentX *segmentx,index_t index);
65 amb 1160
66 amb 1132 static int deduplicate_super(SegmentX *segmentx,index_t index);
67 amb 275
68 amb 1160 static int geographically_index(SegmentX *segmentx,index_t index);
69    
70 amb 1168 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2);
71 amb 110
72    
73     /*++++++++++++++++++++++++++++++++++++++
74 amb 326 Allocate a new segment list (create a new file or open an existing one).
75 amb 110
76     SegmentsX *NewSegmentList Returns the segment list.
77 amb 326
78 amb 1123 int append Set to 1 if the file is to be opened for appending.
79    
80 amb 1139 int readonly Set to 1 if the file is to be opened for reading.
81 amb 110 ++++++++++++++++++++++++++++++++++++++*/
82    
83 amb 1123 SegmentsX *NewSegmentList(int append,int readonly)
84 amb 110 {
85     SegmentsX *segmentsx;
86    
87 amb 213 segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX));
88 amb 110
89 amb 1166 logassert(segmentsx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */
90 amb 243
91 amb 1120 segmentsx->filename =(char*)malloc(strlen(option_tmpdirname)+32);
92     segmentsx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
93 amb 216
94 amb 1120 sprintf(segmentsx->filename ,"%s/segmentsx.parsed.mem",option_tmpdirname);
95     sprintf(segmentsx->filename_tmp,"%s/segmentsx.%p.tmp" ,option_tmpdirname,(void*)segmentsx);
96 amb 256
97 amb 1123 if(append || readonly)
98     if(ExistsFile(segmentsx->filename))
99     {
100     off_t size;
101 amb 326
102 amb 1123 size=SizeFile(segmentsx->filename);
103 amb 326
104 amb 1123 segmentsx->number=size/sizeof(SegmentX);
105 amb 1139
106     RenameFile(segmentsx->filename,segmentsx->filename_tmp);
107 amb 1123 }
108 amb 326
109 amb 1123 if(append)
110 amb 1139 segmentsx->fd=OpenFileAppend(segmentsx->filename_tmp);
111 amb 1123 else if(!readonly)
112 amb 1139 segmentsx->fd=OpenFileNew(segmentsx->filename_tmp);
113 amb 326 else
114 amb 1123 segmentsx->fd=-1;
115 amb 326
116 amb 110 return(segmentsx);
117     }
118    
119    
120     /*++++++++++++++++++++++++++++++++++++++
121 amb 226 Free a segment list.
122 amb 110
123 amb 681 SegmentsX *segmentsx The set of segments to be freed.
124 amb 1151
125 amb 1167 int keep If set then the results file is to be kept.
126 amb 110 ++++++++++++++++++++++++++++++++++++++*/
127    
128 amb 1167 void FreeSegmentList(SegmentsX *segmentsx,int keep)
129 amb 110 {
130 amb 1167 if(keep)
131 amb 1151 RenameFile(segmentsx->filename_tmp,segmentsx->filename);
132     else
133     DeleteFile(segmentsx->filename_tmp);
134 amb 1120
135 amb 283 free(segmentsx->filename);
136 amb 1120 free(segmentsx->filename_tmp);
137 amb 256
138 amb 949 if(segmentsx->firstnode)
139     free(segmentsx->firstnode);
140    
141     if(segmentsx->next1)
142     free(segmentsx->next1);
143    
144 amb 643 if(segmentsx->usednode)
145     free(segmentsx->usednode);
146    
147 amb 110 free(segmentsx);
148     }
149    
150    
151     /*++++++++++++++++++++++++++++++++++++++
152 amb 493 Append a single segment to an unsorted segment list.
153 amb 110
154 amb 681 SegmentsX *segmentsx The set of segments to modify.
155 amb 110
156 amb 285 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 amb 1168 distance_t distance The distance between the nodes (or just the flags).
163 amb 110 ++++++++++++++++++++++++++++++++++++++*/
164    
165 amb 1168 void AppendSegmentList(SegmentsX *segmentsx,way_t way,node_t node1,node_t node2,distance_t distance)
166 amb 110 {
167 amb 285 SegmentX segmentx;
168 amb 110
169 amb 643 if(node1>node2)
170     {
171     node_t temp;
172    
173     temp=node1;
174     node1=node2;
175     node2=temp;
176    
177 amb 1168 if(distance&(ONEWAY_2TO1|ONEWAY_1TO2))
178     distance^=ONEWAY_2TO1|ONEWAY_1TO2;
179 amb 643 }
180    
181 amb 285 segmentx.node1=node1;
182     segmentx.node2=node2;
183 amb 643 segmentx.next2=NO_SEGMENT;
184 amb 285 segmentx.way=way;
185 amb 1168 segmentx.distance=distance;
186 amb 110
187 amb 285 WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
188 amb 281
189 amb 650 segmentsx->number++;
190 amb 466
191 amb 1166 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 amb 285 }
193 amb 227
194 amb 281
195 amb 285 /*++++++++++++++++++++++++++++++++++++++
196 amb 1120 Finish appending segments and change the filename over.
197    
198     SegmentsX *segmentsx The segments that have been appended.
199     ++++++++++++++++++++++++++++++++++++++*/
200    
201 amb 1151 void FinishSegmentList(SegmentsX *segmentsx)
202 amb 1120 {
203 amb 1136 if(segmentsx->fd!=-1)
204     segmentsx->fd=CloseFile(segmentsx->fd);
205 amb 1120 }
206    
207    
208     /*++++++++++++++++++++++++++++++++++++++
209 amb 1160 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 amb 1140 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 amb 1160 Sort the segments into way id order.
342 amb 232
343 amb 1160 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 amb 1100 ++++++++++++++++++++++++++++++++++++++*/
349 amb 949
350 amb 1160 static int sort_by_way_id(SegmentX *a,SegmentX *b)
351 amb 1100 {
352 amb 1160 way_t a_id=a->way;
353     way_t b_id=b->way;
354 amb 1100
355 amb 1160 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 amb 1100
363    
364 amb 1160 /*++++++++++++++++++++++++++++++++++++++
365     Apply the changes to the segments.
366 amb 1100
367 amb 1160 int apply_changes Return 1 if the value is to be kept, otherwise 0.
368 amb 1100
369 amb 1160 SegmentX *segmentx The extended segment.
370 amb 1100
371 amb 1160 index_t index The number of sorted segments that have already been written to the output file.
372     ++++++++++++++++++++++++++++++++++++++*/
373 amb 1100
374 amb 1160 static int apply_changes(SegmentX *segmentx,index_t index)
375     {
376     static way_t prevway=NO_WAY_ID;
377     static int deleted=0;
378 amb 1100
379 amb 1160 if(prevway!=segmentx->way)
380     {
381     prevway=segmentx->way;
382     deleted=0;
383     }
384 amb 1131
385 amb 1160 if(!deleted)
386     if(segmentx->node1==NO_NODE_ID)
387     deleted=1;
388 amb 1131
389 amb 1160 if(deleted)
390     return(0);
391     else
392     return(1);
393 amb 1131 }
394    
395    
396     /*++++++++++++++++++++++++++++++++++++++
397 amb 1160 Sort the segment list and deduplicate it.
398 amb 1100
399     SegmentsX *segmentsx The set of segments to sort and modify.
400 amb 285 ++++++++++++++++++++++++++++++++++++++*/
401 amb 110
402 amb 1160 void SortSegmentList(SegmentsX *segmentsx)
403 amb 285 {
404     int fd;
405 amb 1132 index_t xnumber;
406 amb 243
407 amb 285 /* Print the start message */
408 amb 232
409 amb 1160 printf_first("Sorting Segments");
410 amb 110
411 amb 555 /* Re-open the file read-only and a new file writeable */
412    
413 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
414 amb 110
415 amb 1120 DeleteFile(segmentsx->filename_tmp);
416 amb 110
417 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
418 amb 110
419 amb 285 /* Sort by node indexes */
420 amb 132
421 amb 1132 xnumber=segmentsx->number;
422    
423 amb 1160 segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL,
424 amb 1132 (int (*)(const void*,const void*))sort_by_id,
425 amb 1160 (int (*)(void*,index_t))deduplicate);
426 amb 1100
427 amb 555 /* Close the files */
428 amb 285
429 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
430 amb 281 CloseFile(fd);
431    
432     /* Print the final message */
433    
434 amb 1160 printf_last("Sorted Segments: Segments=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-segmentsx->number);
435 amb 110 }
436    
437    
438     /*++++++++++++++++++++++++++++++++++++++
439 amb 680 Sort the segments into id order, first by node1 then by node2, finally by distance.
440 amb 110
441 amb 285 int sort_by_id Returns the comparison of the node fields.
442 amb 110
443 amb 285 SegmentX *a The first segment.
444 amb 110
445 amb 285 SegmentX *b The second segment.
446 amb 256 ++++++++++++++++++++++++++++++++++++++*/
447    
448 amb 285 static int sort_by_id(SegmentX *a,SegmentX *b)
449 amb 256 {
450 amb 285 node_t a_id1=a->node1;
451     node_t b_id1=b->node1;
452 amb 256
453 amb 285 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 amb 256 {
459 amb 285 node_t a_id2=a->node2;
460     node_t b_id2=b->node2;
461 amb 256
462 amb 285 if(a_id2<b_id2)
463     return(-1);
464     else if(a_id2>b_id2)
465     return(1);
466     else
467     {
468 amb 1168 distance_t a_distance=DISTANCE(a->distance);
469     distance_t b_distance=DISTANCE(b->distance);
470 amb 256
471 amb 1168 if(a_distance<b_distance)
472 amb 285 return(-1);
473 amb 1168 else if(a_distance>b_distance)
474 amb 285 return(1);
475     else
476 amb 1153 {
477 amb 1168 distance_t a_distflag=DISTFLAG(a->distance);
478     distance_t b_distflag=DISTFLAG(b->distance);
479 amb 1153
480 amb 1168 if(a_distflag<b_distflag)
481 amb 1153 return(-1);
482 amb 1168 else if(a_distflag>b_distflag)
483 amb 1153 return(1);
484     else
485     return(FILESORT_PRESERVE_ORDER(a,b)); /* preserve order */
486     }
487 amb 285 }
488 amb 256 }
489     }
490    
491    
492     /*++++++++++++++++++++++++++++++++++++++
493 amb 1155 Discard duplicate segments.
494 amb 1131
495 amb 1155 int deduplicate Return 1 if the value is to be kept, otherwise 0.
496 amb 1131
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 amb 1155 static int deduplicate(SegmentX *segmentx,index_t index)
503 amb 1131 {
504     static node_t prevnode1=NO_NODE_ID,prevnode2=NO_NODE_ID;
505 amb 1155 static way_t prevway=NO_WAY_ID;
506 amb 1168 static distance_t prevdist=0;
507 amb 1131
508 amb 1168 if(prevnode1!=segmentx->node1 || prevnode2!=segmentx->node2 || prevway!=segmentx->way || prevdist!=segmentx->distance)
509 amb 1131 {
510     prevnode1=segmentx->node1;
511     prevnode2=segmentx->node2;
512 amb 1155 prevway=segmentx->way;
513 amb 1168 prevdist=segmentx->distance;
514 amb 1131
515     return(1);
516     }
517     else
518     return(0);
519     }
520    
521    
522     /*++++++++++++++++++++++++++++++++++++++
523 amb 680 Remove bad segments (duplicated, zero length or with missing nodes).
524 amb 110
525 amb 1136 SegmentsX *segmentsx The set of segments to modify.
526    
527 amb 681 NodesX *nodesx The set of nodes to use.
528 amb 195
529 amb 1140 WaysX *waysx The set of ways to use.
530    
531 amb 1167 int keep If set to 1 then keep the old data file otherwise delete it.
532 amb 110 ++++++++++++++++++++++++++++++++++++++*/
533    
534 amb 1167 void RemoveBadSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx,int keep)
535 amb 110 {
536 amb 1155 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 amb 1168 distance_t prevdist=0;
539 amb 275 SegmentX segmentx;
540     int fd;
541 amb 110
542 amb 275 /* Print the start message */
543    
544 amb 1155 printf_first("Checking Segments: Segments=0 Loop=0 No-Way=0 No-Node=0 Duplicate=0");
545 amb 227
546 amb 1100 /* Allocate the node usage bitmask */
547 amb 643
548 amb 950 segmentsx->usednode=AllocBitMask(nodesx->number);
549 amb 643
550 amb 1166 logassert(segmentsx->usednode,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
551 amb 643
552 amb 555 /* Re-open the file read-only and a new file writeable */
553 amb 275
554 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
555 amb 555
556 amb 1167 if(keep)
557 amb 1136 RenameFile(segmentsx->filename_tmp,segmentsx->filename);
558     else
559     DeleteFile(segmentsx->filename_tmp);
560 amb 275
561 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
562 amb 275
563 amb 555 /* Modify the on-disk image */
564    
565 amb 275 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
566 amb 110 {
567 amb 643 index_t index1=IndexNodeX(nodesx,segmentx.node1);
568     index_t index2=IndexNodeX(nodesx,segmentx.node2);
569 amb 1140 index_t indexw=IndexWayX(waysx,segmentx.way);
570 amb 643
571 amb 1140 if(indexw==NO_WAY)
572 amb 812 {
573 amb 1140 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 amb 812 logerror("Segment connects node %"Pnode_t" to itself.\n",segmentx.node1);
580    
581 amb 257 loop++;
582 amb 812 }
583 amb 643 else if(index1==NO_NODE || index2==NO_NODE)
584 amb 812 {
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 amb 761 nonode++;
595 amb 812 }
596 amb 1155 else if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2)
597     {
598 amb 1168 if(!(prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA))
599 amb 1155 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated.\n",segmentx.node1,segmentx.node2);
600    
601 amb 1168 if(!(prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA))
602 amb 1155 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the area).\n",segmentx.node1,segmentx.node2);
603    
604 amb 1168 if((prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA))
605 amb 1155 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the non-area).\n",segmentx.node1,segmentx.node2);
606    
607 amb 1168 if((prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA))
608 amb 1155 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (both are areas).\n",segmentx.node1,segmentx.node2);
609    
610     duplicate++;
611     }
612 amb 275 else
613 amb 257 {
614 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
615    
616 amb 655 SetBit(segmentsx->usednode,index1);
617     SetBit(segmentsx->usednode,index2);
618 amb 643
619 amb 1155 prevnode1=segmentx.node1;
620     prevnode2=segmentx.node2;
621 amb 1168 prevdist=DISTANCE(segmentx.distance);
622 amb 1155
623 amb 275 good++;
624 amb 110 }
625    
626 amb 275 total++;
627 amb 256
628 amb 275 if(!(total%10000))
629 amb 1155 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 amb 110 }
631    
632 amb 555 segmentsx->number=good;
633 amb 275
634 amb 555 /* Close the files */
635    
636 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
637 amb 275 CloseFile(fd);
638    
639     /* Print the final message */
640    
641 amb 1155 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 amb 110 }
643    
644    
645     /*++++++++++++++++++++++++++++++++++++++
646 amb 285 Measure the segments and replace node/way ids with indexes.
647 amb 110
648 amb 681 SegmentsX *segmentsx The set of segments to process.
649 amb 110
650 amb 680 NodesX *nodesx The set of nodes to use.
651 amb 279
652 amb 680 WaysX *waysx The set of ways to use.
653 amb 110 ++++++++++++++++++++++++++++++++++++++*/
654    
655 amb 681 void MeasureSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
656 amb 110 {
657 amb 279 index_t index=0;
658 amb 643 int fd;
659 amb 256 SegmentX segmentx;
660 amb 110
661 amb 275 /* Print the start message */
662    
663 amb 519 printf_first("Measuring Segments: Segments=0");
664 amb 227
665 amb 555 /* Map into memory / open the file */
666 amb 257
667 amb 452 #if !SLIM
668 amb 1120 nodesx->data=MapFile(nodesx->filename_tmp);
669 amb 555 #else
670 amb 1120 nodesx->fd=ReOpenFile(nodesx->filename_tmp);
671 amb 452 #endif
672 amb 258
673 amb 1100 /* Allocate the way usage bitmask */
674    
675     segmentsx->usedway=AllocBitMask(waysx->number);
676    
677 amb 1166 logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
678 amb 1100
679 amb 555 /* Re-open the file read-only and a new file writeable */
680 amb 275
681 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
682 amb 555
683 amb 1120 DeleteFile(segmentsx->filename_tmp);
684 amb 256
685 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
686 amb 256
687 amb 555 /* Modify the on-disk image */
688    
689 amb 256 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
690 amb 110 {
691 amb 279 index_t node1=IndexNodeX(nodesx,segmentx.node1);
692     index_t node2=IndexNodeX(nodesx,segmentx.node2);
693     index_t way =IndexWayX (waysx ,segmentx.way);
694 amb 110
695 amb 279 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 amb 1100 SetBit(segmentsx->usedway,segmentx.way);
705    
706 amb 1167 /* Set the distance but keep the other flags except for area */
707 amb 275
708 amb 1168 segmentx.distance=DISTANCE(DistanceX(nodex1,nodex2))|DISTFLAG(segmentx.distance);
709 amb 1169 segmentx.distance&=~SEGMENT_AREA;
710 amb 275
711 amb 279 /* Write the modified segment */
712    
713 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
714    
715 amb 279 index++;
716 amb 275
717 amb 279 if(!(index%10000))
718 amb 790 printf_middle("Measuring Segments: Segments=%"Pindex_t,index);
719 amb 275 }
720 amb 110
721 amb 555 /* Close the files */
722 amb 257
723 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
724 amb 275 CloseFile(fd);
725    
726 amb 280 /* Free the other now-unneeded indexes */
727 amb 279
728     free(nodesx->idata);
729     nodesx->idata=NULL;
730    
731     free(waysx->idata);
732     waysx->idata=NULL;
733    
734 amb 555 /* Unmap from memory / close the file */
735 amb 275
736 amb 452 #if !SLIM
737 amb 1122 nodesx->data=UnmapFile(nodesx->data);
738 amb 555 #else
739 amb 612 nodesx->fd=CloseFile(nodesx->fd);
740 amb 452 #endif
741 amb 275
742     /* Print the final message */
743    
744 amb 790 printf_last("Measured Segments: Segments=%"Pindex_t,segmentsx->number);
745 amb 275 }
746    
747    
748     /*++++++++++++++++++++++++++++++++++++++
749 amb 1160 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 amb 1166 logassert(segmentsx->firstnode,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
777 amb 1160
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 amb 1166 logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
865 amb 1160
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 amb 1132 Remove the duplicate super-segments.
918 amb 110
919 amb 1132 SegmentsX *segmentsx The set of super-segments to modify.
920 amb 110
921 amb 680 WaysX *waysx The set of ways to use.
922 amb 110 ++++++++++++++++++++++++++++++++++++++*/
923    
924 amb 1132 void DeduplicateSuperSegments(SegmentsX *segmentsx,WaysX *waysx)
925 amb 110 {
926 amb 1132 int fd;
927     index_t xnumber;
928 amb 110
929 amb 275 /* Print the start message */
930    
931 amb 1132 printf_first("Sorting and Deduplicating Super-Segments");
932 amb 227
933 amb 555 /* Map into memory / open the file */
934 amb 256
935 amb 452 #if !SLIM
936 amb 1120 waysx->data=MapFile(waysx->filename_tmp);
937 amb 555 #else
938 amb 1120 waysx->fd=ReOpenFile(waysx->filename_tmp);
939 amb 452 #endif
940 amb 275
941 amb 555 /* Re-open the file read-only and a new file writeable */
942 amb 275
943 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
944 amb 555
945 amb 1120 DeleteFile(segmentsx->filename_tmp);
946 amb 275
947 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
948 amb 275
949 amb 1132 /* Sort by node indexes */
950 amb 555
951 amb 1132 xnumber=segmentsx->number;
952 amb 256
953 amb 1132 sortsegmentsx=segmentsx;
954     sortwaysx=waysx;
955 amb 110
956 amb 1132 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 amb 264
960 amb 555 /* Close the files */
961    
962 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
963 amb 275 CloseFile(fd);
964    
965 amb 555 /* Unmap from memory / close the file */
966 amb 275
967 amb 452 #if !SLIM
968 amb 1122 waysx->data=UnmapFile(waysx->data);
969 amb 555 #else
970 amb 612 waysx->fd=CloseFile(waysx->fd);
971 amb 452 #endif
972 amb 275
973     /* Print the final message */
974    
975 amb 1132 printf_last("Sorted and Deduplicated Super-Segments: Super-Segments=%"Pindex_t" Duplicate=%"Pindex_t,xnumber,xnumber-segmentsx->number);
976 amb 110 }
977    
978    
979     /*++++++++++++++++++++++++++++++++++++++
980 amb 1132 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 amb 1168 if(DISTFLAG(segmentx->distance)==DISTFLAG(prevsegx[offset].distance))
1014 amb 1132 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 amb 1166 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 amb 1132
1035     prevsegx[nprev]=*segmentx;
1036     prevway[nprev] =wayx->way;
1037    
1038     nprev++;
1039     }
1040     }
1041    
1042     return(!isduplicate);
1043     }
1044    
1045    
1046     /*++++++++++++++++++++++++++++++++++++++
1047 amb 1160 Sort the segments geographically after updating the node indexes.
1048 amb 209
1049 amb 681 SegmentsX *segmentsx The set of segments to modify.
1050 amb 209
1051 amb 1100 NodesX *nodesx The set of nodes to use.
1052 amb 209 ++++++++++++++++++++++++++++++++++++++*/
1053    
1054 amb 1160 void SortSegmentListGeographically(SegmentsX *segmentsx,NodesX *nodesx)
1055 amb 209 {
1056 amb 1160 int fd;
1057 amb 209
1058 amb 275 /* Print the start message */
1059    
1060 amb 1160 printf_first("Sorting Segments Geographically");
1061 amb 227
1062 amb 1160 /* Re-open the file read-only and a new file writeable */
1063 amb 643
1064 amb 1160 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
1065 amb 643
1066 amb 1160 DeleteFile(segmentsx->filename_tmp);
1067 amb 643
1068 amb 1160 fd=OpenFileNew(segmentsx->filename_tmp);
1069 amb 1102
1070 amb 1160 /* Update the segments with geographically sorted node indexes and sort them */
1071 amb 643
1072 amb 1160 sortnodesx=nodesx;
1073 amb 209
1074 amb 1160 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 amb 275
1079 amb 1160 segmentsx->fd=CloseFile(segmentsx->fd);
1080     CloseFile(fd);
1081 amb 280
1082 amb 1160 /* Print the final message */
1083 amb 209
1084 amb 1160 printf_last("Sorted Segments Geographically: Segments=%"Pindex_t,segmentsx->number);
1085     }
1086 amb 1098
1087 amb 1100
1088 amb 1160 /*++++++++++++++++++++++++++++++++++++++
1089     Update the segment indexes.
1090 amb 209
1091 amb 1160 int geographically_index Return 1 if the value is to be kept, otherwise 0.
1092 amb 448
1093 amb 1160 SegmentX *segmentx The extended segment.
1094 amb 558
1095 amb 1160 index_t index The number of unsorted segments that have been read from the input file.
1096     ++++++++++++++++++++++++++++++++++++++*/
1097 amb 209
1098 amb 1160 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 amb 275
1103 amb 1160 if(segmentx->node1>segmentx->node2)
1104     {
1105     index_t temp;
1106 amb 275
1107 amb 1160 temp=segmentx->node1;
1108     segmentx->node1=segmentx->node2;
1109     segmentx->node2=temp;
1110 amb 1100
1111 amb 1168 if(segmentx->distance&(ONEWAY_2TO1|ONEWAY_1TO2))
1112     segmentx->distance^=ONEWAY_2TO1|ONEWAY_1TO2;
1113 amb 1100 }
1114    
1115 amb 1160 return(1);
1116 amb 209 }
1117    
1118    
1119     /*++++++++++++++++++++++++++++++++++++++
1120 amb 285 Save the segment list to a file.
1121    
1122 amb 681 SegmentsX *segmentsx The set of segments to save.
1123 amb 285
1124     const char *filename The name of the file to save.
1125     ++++++++++++++++++++++++++++++++++++++*/
1126    
1127 amb 681 void SaveSegmentList(SegmentsX *segmentsx,const char *filename)
1128 amb 285 {
1129     index_t i;
1130     int fd;
1131 amb 500 SegmentsFile segmentsfile={0};
1132 amb 780 index_t super_number=0,normal_number=0;
1133 amb 285
1134     /* Print the start message */
1135    
1136 amb 519 printf_first("Writing Segments: Segments=0");
1137 amb 285
1138 amb 558 /* Re-open the file */
1139    
1140 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
1141 amb 558
1142 amb 461 /* Write out the segments data */
1143 amb 285
1144 amb 502 fd=OpenFileNew(filename);
1145 amb 461
1146     SeekFile(fd,sizeof(SegmentsFile));
1147    
1148 amb 285 for(i=0;i<segmentsx->number;i++)
1149     {
1150 amb 643 SegmentX segmentx;
1151 amb 944 Segment segment={0};
1152 amb 448
1153 amb 643 ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
1154 amb 558
1155 amb 1168 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 amb 643
1161 amb 558 if(IsSuperSegment(&segment))
1162 amb 285 super_number++;
1163 amb 558 if(IsNormalSegment(&segment))
1164 amb 285 normal_number++;
1165    
1166 amb 558 WriteFile(fd,&segment,sizeof(Segment));
1167 amb 448
1168 amb 285 if(!((i+1)%10000))
1169 amb 790 printf_middle("Writing Segments: Segments=%"Pindex_t,i+1);
1170 amb 285 }
1171    
1172 amb 461 /* 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 amb 285 CloseFile(fd);
1182    
1183 amb 558 /* Close the file */
1184    
1185 amb 643 segmentsx->fd=CloseFile(segmentsx->fd);
1186 amb 558
1187 amb 285 /* Print the final message */
1188    
1189 amb 790 printf_last("Wrote Segments: Segments=%"Pindex_t,segmentsx->number);
1190 amb 285 }
1191    
1192    
1193     /*++++++++++++++++++++++++++++++++++++++
1194 amb 110 Calculate the distance between two nodes.
1195    
1196 amb 1168 distance_t DistanceX Returns the distance between the extended nodes.
1197 amb 110
1198     NodeX *nodex1 The starting node.
1199    
1200     NodeX *nodex2 The end node.
1201     ++++++++++++++++++++++++++++++++++++++*/
1202    
1203 amb 1168 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
1204 amb 110 {
1205 amb 223 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 amb 110
1210 amb 219 double a1,a2,a,sa,c,d;
1211 amb 110
1212     if(dlon==0 && dlat==0)
1213     return 0;
1214    
1215 amb 219 a1 = sin (dlat / 2);
1216     a2 = sin (dlon / 2);
1217     a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
1218     sa = sqrt (a);
1219 amb 110 if (sa <= 1.0)
1220 amb 219 {c = 2 * asin (sa);}
1221 amb 110 else
1222 amb 219 {c = 2 * asin (1.0);}
1223 amb 110 d = 6378.137 * c;
1224    
1225     return km_to_distance(d);
1226     }

Properties

Name Value
cvs:description Extended segments functions.