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 1208 - (hide annotations) (download) (as text)
Sat Dec 15 16:43:03 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 31797 byte(s)
Stop planetsplitter crashing out in unusual ways if there is no data.

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

Properties

Name Value
cvs:description Extended segments functions.