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 1166 - (hide annotations) (download) (as text)
Tue Nov 20 16:12:08 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 31524 byte(s)
Replace all assert statements with a custom error message that explains the
cause and suggests a solution.

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

Properties

Name Value
cvs:description Extended segments functions.