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 1339 - (hide annotations) (download) (as text)
Thu May 23 17:47:16 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 28682 byte(s)
Don't create segments when parsing input file but create the segments later
using the nodes stored in the ways file.  This makes applying changes simpler
(segments file is not kept with the --keep option) and handling changed ways is
simpler than changed segments.

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

Properties

Name Value
cvs:description Extended segments functions.