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 1349 - (hide annotations) (download) (as text)
Wed May 29 17:33:26 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 28105 byte(s)
Simplify the segments by using the node and way index instead of node and way id
which avoids lots of IndexNodeX() lookups.  Move some other code around to cope
with it.

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 1349 index_t way The index of the way that the segment belongs to.
130 amb 285
131 amb 1349 index_t node1 The index of the first node in the segment.
132 amb 285
133 amb 1349 index_t node2 The index of the second node in the segment.
134 amb 285
135 amb 1168 distance_t distance The distance between the nodes (or just the flags).
136 amb 110 ++++++++++++++++++++++++++++++++++++++*/
137    
138 amb 1349 void AppendSegmentList(SegmentsX *segmentsx,index_t way,index_t node1,index_t node2,distance_t distance)
139 amb 110 {
140 amb 285 SegmentX segmentx;
141 amb 110
142 amb 643 if(node1>node2)
143     {
144 amb 1349 index_t temp;
145 amb 643
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 1349 index_t a_id1=a->node1;
326     index_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 1349 index_t a_id2=a->node2;
335     index_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 amb 1349 static index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
380     static index_t prevway=NO_WAY;
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 1349 index_t duplicate=0,good=0,total=0;
410     index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
411     index_t prevway=NO_WAY;
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 1349 printf_first("Checking Segments: Segments=0 Duplicate=0");
419 amb 227
420 amb 1349 /* Map into memory / open the file */
421    
422     #if !SLIM
423     nodesx->data=MapFile(nodesx->filename_tmp);
424     waysx->data=MapFile(waysx->filename_tmp);
425     #else
426     nodesx->fd=ReOpenFile(nodesx->filename_tmp);
427     waysx->fd=ReOpenFile(waysx->filename_tmp);
428    
429     InvalidateNodeXCache(nodesx->cache);
430     InvalidateWayXCache(waysx->cache);
431     #endif
432    
433 amb 1100 /* Allocate the node usage bitmask */
434 amb 643
435 amb 950 segmentsx->usednode=AllocBitMask(nodesx->number);
436 amb 643
437 amb 1166 logassert(segmentsx->usednode,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
438 amb 643
439 amb 555 /* Re-open the file read-only and a new file writeable */
440 amb 275
441 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
442 amb 555
443 amb 1339 DeleteFile(segmentsx->filename_tmp);
444 amb 275
445 amb 1317 segmentsx->knumber=segmentsx->number;
446    
447 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
448 amb 275
449 amb 555 /* Modify the on-disk image */
450    
451 amb 275 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
452 amb 110 {
453 amb 1349 if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2)
454 amb 812 {
455 amb 1349 NodeX *nodex1=LookupNodeX(nodesx,segmentx.node1,1);
456     NodeX *nodex2=LookupNodeX(nodesx,segmentx.node2,2);
457 amb 1140
458 amb 1349 if(prevway==segmentx.way)
459     {
460     WayX *wayx=LookupWayX(waysx,segmentx.way,1);
461 amb 812
462 amb 1349 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" in way %"Pway_t" is duplicated.\n",logerror_node(nodex1->id),logerror_node(nodex2->id),logerror_way(wayx->id));
463     }
464 amb 1173 else
465     {
466     if(!(prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA))
467 amb 1349 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated.\n",logerror_node(nodex1->id),logerror_node(nodex2->id));
468 amb 1155
469 amb 1173 if(!(prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA))
470 amb 1349 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the area).\n",logerror_node(nodex1->id),logerror_node(nodex2->id));
471 amb 1155
472 amb 1173 if((prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA))
473 amb 1349 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the non-area).\n",logerror_node(nodex1->id),logerror_node(nodex2->id));
474 amb 1155
475 amb 1173 if((prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA))
476 amb 1349 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (both are areas).\n",logerror_node(nodex1->id),logerror_node(nodex2->id));
477 amb 1173 }
478 amb 1155
479     duplicate++;
480     }
481 amb 275 else
482 amb 257 {
483 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
484    
485 amb 1349 SetBit(segmentsx->usednode,segmentx.node1);
486     SetBit(segmentsx->usednode,segmentx.node2);
487 amb 643
488 amb 1155 prevnode1=segmentx.node1;
489     prevnode2=segmentx.node2;
490 amb 1173 prevway=segmentx.way;
491 amb 1168 prevdist=DISTANCE(segmentx.distance);
492 amb 1155
493 amb 275 good++;
494 amb 110 }
495    
496 amb 275 total++;
497 amb 256
498 amb 275 if(!(total%10000))
499 amb 1349 printf_middle("Checking Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t,total,duplicate);
500 amb 110 }
501    
502 amb 555 segmentsx->number=good;
503 amb 275
504 amb 555 /* Close the files */
505    
506 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
507 amb 275 CloseFile(fd);
508    
509 amb 1349 /* Unmap from memory / close the file */
510    
511     #if !SLIM
512     nodesx->data=UnmapFile(nodesx->data);
513     waysx->data=UnmapFile(waysx->data);
514     #else
515     nodesx->fd=CloseFile(nodesx->fd);
516     waysx->fd=CloseFile(waysx->fd);
517     #endif
518    
519 amb 275 /* Print the final message */
520    
521 amb 1349 printf_last("Checked Segments: Segments=%"Pindex_t" Duplicate=%"Pindex_t,total,duplicate);
522 amb 110 }
523    
524    
525     /*++++++++++++++++++++++++++++++++++++++
526 amb 285 Measure the segments and replace node/way ids with indexes.
527 amb 110
528 amb 681 SegmentsX *segmentsx The set of segments to process.
529 amb 110
530 amb 680 NodesX *nodesx The set of nodes to use.
531 amb 279
532 amb 680 WaysX *waysx The set of ways to use.
533 amb 110 ++++++++++++++++++++++++++++++++++++++*/
534    
535 amb 681 void MeasureSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
536 amb 110 {
537 amb 279 index_t index=0;
538 amb 643 int fd;
539 amb 256 SegmentX segmentx;
540 amb 110
541 amb 1208 if(segmentsx->number==0)
542     return;
543    
544 amb 275 /* Print the start message */
545    
546 amb 519 printf_first("Measuring Segments: Segments=0");
547 amb 227
548 amb 555 /* Map into memory / open the file */
549 amb 257
550 amb 452 #if !SLIM
551 amb 1120 nodesx->data=MapFile(nodesx->filename_tmp);
552 amb 555 #else
553 amb 1120 nodesx->fd=ReOpenFile(nodesx->filename_tmp);
554 amb 1297
555     InvalidateNodeXCache(nodesx->cache);
556 amb 452 #endif
557 amb 258
558 amb 1100 /* Allocate the way usage bitmask */
559    
560     segmentsx->usedway=AllocBitMask(waysx->number);
561    
562 amb 1166 logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
563 amb 1100
564 amb 555 /* Re-open the file read-only and a new file writeable */
565 amb 275
566 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
567 amb 555
568 amb 1120 DeleteFile(segmentsx->filename_tmp);
569 amb 256
570 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
571 amb 256
572 amb 555 /* Modify the on-disk image */
573    
574 amb 256 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
575 amb 110 {
576 amb 1349 NodeX *nodex1,*nodex2;
577 amb 110
578 amb 1349 /* Update segment node indexes now that non-highway nodes have been removed */
579 amb 279
580 amb 1349 segmentx.node1=nodesx->idata[segmentx.node1];
581     segmentx.node2=nodesx->idata[segmentx.node2];
582 amb 279
583 amb 1349 nodex1=LookupNodeX(nodesx,segmentx.node1,1);
584     nodex2=LookupNodeX(nodesx,segmentx.node2,2);
585 amb 279
586 amb 1349 /* Mark the ways which are used */
587    
588 amb 1100 SetBit(segmentsx->usedway,segmentx.way);
589    
590 amb 1167 /* Set the distance but keep the other flags except for area */
591 amb 275
592 amb 1168 segmentx.distance=DISTANCE(DistanceX(nodex1,nodex2))|DISTFLAG(segmentx.distance);
593 amb 1169 segmentx.distance&=~SEGMENT_AREA;
594 amb 275
595 amb 279 /* Write the modified segment */
596    
597 amb 275 WriteFile(fd,&segmentx,sizeof(SegmentX));
598    
599 amb 279 index++;
600 amb 275
601 amb 279 if(!(index%10000))
602 amb 790 printf_middle("Measuring Segments: Segments=%"Pindex_t,index);
603 amb 275 }
604 amb 110
605 amb 555 /* Close the files */
606 amb 257
607 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
608 amb 275 CloseFile(fd);
609    
610 amb 555 /* Unmap from memory / close the file */
611 amb 275
612 amb 452 #if !SLIM
613 amb 1122 nodesx->data=UnmapFile(nodesx->data);
614 amb 555 #else
615 amb 612 nodesx->fd=CloseFile(nodesx->fd);
616 amb 452 #endif
617 amb 275
618     /* Print the final message */
619    
620 amb 790 printf_last("Measured Segments: Segments=%"Pindex_t,segmentsx->number);
621 amb 275 }
622    
623    
624     /*++++++++++++++++++++++++++++++++++++++
625 amb 1160 Index the segments by creating the firstnode index and filling in the segment next2 parameter.
626    
627     SegmentsX *segmentsx The set of segments to modify.
628    
629     NodesX *nodesx The set of nodes to use.
630    
631     WaysX *waysx The set of ways to use.
632     ++++++++++++++++++++++++++++++++++++++*/
633    
634     void IndexSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
635     {
636     index_t index,i;
637    
638     if(segmentsx->number==0)
639     return;
640    
641     /* Print the start message */
642    
643     printf_first("Indexing Segments: Segments=0");
644    
645     /* Allocate the array of indexes */
646    
647     if(segmentsx->firstnode)
648     free(segmentsx->firstnode);
649    
650     segmentsx->firstnode=(index_t*)malloc(nodesx->number*sizeof(index_t));
651    
652 amb 1166 logassert(segmentsx->firstnode,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
653 amb 1160
654     for(i=0;i<nodesx->number;i++)
655     segmentsx->firstnode[i]=NO_SEGMENT;
656    
657     /* Map into memory / open the files */
658    
659     #if !SLIM
660     segmentsx->data=MapFileWriteable(segmentsx->filename_tmp);
661     #else
662     segmentsx->fd=ReOpenFileWriteable(segmentsx->filename_tmp);
663 amb 1297
664     InvalidateSegmentXCache(segmentsx->cache);
665 amb 1160 #endif
666    
667     /* Read through the segments in reverse order */
668    
669     for(index=segmentsx->number-1;index!=NO_SEGMENT;index--)
670     {
671     SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
672    
673     if(nodesx->pdata)
674     {
675     segmentx->node1=nodesx->pdata[segmentx->node1];
676     segmentx->node2=nodesx->pdata[segmentx->node2];
677     }
678    
679     if(waysx->cdata)
680     segmentx->way=waysx->cdata[segmentx->way];
681    
682     segmentx->next2=segmentsx->firstnode[segmentx->node2];
683    
684     PutBackSegmentX(segmentsx,segmentx);
685    
686     segmentsx->firstnode[segmentx->node1]=index;
687     segmentsx->firstnode[segmentx->node2]=index;
688    
689     if(!(index%10000))
690     printf_middle("Indexing Segments: Segments=%"Pindex_t,segmentsx->number-index);
691     }
692    
693     /* Unmap from memory / close the files */
694    
695     #if !SLIM
696     segmentsx->data=UnmapFile(segmentsx->data);
697     #else
698     segmentsx->fd=CloseFile(segmentsx->fd);
699     #endif
700    
701     /* Free the memory */
702    
703     if(nodesx->pdata)
704     {
705     free(nodesx->pdata);
706     nodesx->pdata=NULL;
707     }
708    
709     if(waysx->cdata)
710     {
711     free(waysx->cdata);
712     waysx->cdata=NULL;
713     }
714    
715     /* Print the final message */
716    
717     printf_last("Indexed Segments: Segments=%"Pindex_t,segmentsx->number);
718     }
719    
720    
721     /*++++++++++++++++++++++++++++++++++++++
722     Prune the deleted segments while resorting the list.
723    
724     SegmentsX *segmentsx The set of segments to sort and modify.
725    
726     WaysX *waysx The set of ways to check.
727     ++++++++++++++++++++++++++++++++++++++*/
728    
729     void RemovePrunedSegments(SegmentsX *segmentsx,WaysX *waysx)
730     {
731     int fd;
732     index_t xnumber;
733    
734 amb 1208 if(segmentsx->number==0)
735     return;
736    
737 amb 1160 /* Print the start message */
738    
739     printf_first("Sorting and Pruning Segments");
740    
741     /* Allocate the way usage bitmask */
742    
743     segmentsx->usedway=AllocBitMask(waysx->number);
744    
745 amb 1166 logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
746 amb 1160
747     /* Re-open the file read-only and a new file writeable */
748    
749     segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
750    
751     DeleteFile(segmentsx->filename_tmp);
752    
753     fd=OpenFileNew(segmentsx->filename_tmp);
754    
755     /* Sort by node indexes */
756    
757     xnumber=segmentsx->number;
758    
759     sortsegmentsx=segmentsx;
760    
761     segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))delete_pruned,
762     (int (*)(const void*,const void*))sort_by_id,
763     NULL);
764    
765     /* Close the files */
766    
767     segmentsx->fd=CloseFile(segmentsx->fd);
768     CloseFile(fd);
769    
770     /* Print the final message */
771    
772     printf_last("Sorted and Pruned Segments: Segments=%"Pindex_t" Deleted=%"Pindex_t,xnumber,xnumber-segmentsx->number);
773     }
774    
775    
776     /*++++++++++++++++++++++++++++++++++++++
777     Delete the pruned segments.
778    
779     int delete_pruned Return 1 if the value is to be kept, otherwise 0.
780    
781     SegmentX *segmentx The extended segment.
782    
783     index_t index The number of unsorted segments that have been read from the input file.
784     ++++++++++++++++++++++++++++++++++++++*/
785    
786     static int delete_pruned(SegmentX *segmentx,index_t index)
787     {
788     if(IsPrunedSegmentX(segmentx))
789     return(0);
790    
791     SetBit(sortsegmentsx->usedway,segmentx->way);
792    
793     return(1);
794     }
795    
796    
797     /*++++++++++++++++++++++++++++++++++++++
798 amb 1132 Remove the duplicate super-segments.
799 amb 110
800 amb 1132 SegmentsX *segmentsx The set of super-segments to modify.
801 amb 110
802 amb 680 WaysX *waysx The set of ways to use.
803 amb 110 ++++++++++++++++++++++++++++++++++++++*/
804    
805 amb 1132 void DeduplicateSuperSegments(SegmentsX *segmentsx,WaysX *waysx)
806 amb 110 {
807 amb 1132 int fd;
808     index_t xnumber;
809 amb 110
810 amb 1208 if(waysx->number==0)
811     return;
812    
813 amb 275 /* Print the start message */
814    
815 amb 1132 printf_first("Sorting and Deduplicating Super-Segments");
816 amb 227
817 amb 555 /* Map into memory / open the file */
818 amb 256
819 amb 452 #if !SLIM
820 amb 1120 waysx->data=MapFile(waysx->filename_tmp);
821 amb 555 #else
822 amb 1120 waysx->fd=ReOpenFile(waysx->filename_tmp);
823 amb 1297
824     InvalidateWayXCache(waysx->cache);
825 amb 452 #endif
826 amb 275
827 amb 555 /* Re-open the file read-only and a new file writeable */
828 amb 275
829 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
830 amb 555
831 amb 1120 DeleteFile(segmentsx->filename_tmp);
832 amb 275
833 amb 1120 fd=OpenFileNew(segmentsx->filename_tmp);
834 amb 275
835 amb 1132 /* Sort by node indexes */
836 amb 555
837 amb 1132 xnumber=segmentsx->number;
838 amb 256
839 amb 1132 sortsegmentsx=segmentsx;
840     sortwaysx=waysx;
841 amb 110
842 amb 1132 segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL,
843     (int (*)(const void*,const void*))sort_by_id,
844     (int (*)(void*,index_t))deduplicate_super);
845 amb 264
846 amb 555 /* Close the files */
847    
848 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
849 amb 275 CloseFile(fd);
850    
851 amb 555 /* Unmap from memory / close the file */
852 amb 275
853 amb 452 #if !SLIM
854 amb 1122 waysx->data=UnmapFile(waysx->data);
855 amb 555 #else
856 amb 612 waysx->fd=CloseFile(waysx->fd);
857 amb 452 #endif
858 amb 275
859     /* Print the final message */
860    
861 amb 1132 printf_last("Sorted and Deduplicated Super-Segments: Super-Segments=%"Pindex_t" Duplicate=%"Pindex_t,xnumber,xnumber-segmentsx->number);
862 amb 110 }
863    
864    
865     /*++++++++++++++++++++++++++++++++++++++
866 amb 1132 De-duplicate super-segments.
867    
868     int deduplicate_super Return 1 if the value is to be kept, otherwise 0.
869    
870     SegmentX *segmentx The extended super-segment.
871    
872     index_t index The number of sorted super-segments that have already been written to the output file.
873     ++++++++++++++++++++++++++++++++++++++*/
874    
875     static int deduplicate_super(SegmentX *segmentx,index_t index)
876     {
877     static int nprev=0;
878     static index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
879     static SegmentX prevsegx[MAX_SEG_PER_NODE];
880     static Way prevway[MAX_SEG_PER_NODE];
881    
882     WayX *wayx=LookupWayX(sortwaysx,segmentx->way,1);
883     int isduplicate=0;
884    
885     if(index==0 || segmentx->node1!=prevnode1 || segmentx->node2!=prevnode2)
886     {
887     nprev=1;
888     prevnode1=segmentx->node1;
889     prevnode2=segmentx->node2;
890     prevsegx[0]=*segmentx;
891     prevway[0] =wayx->way;
892     }
893     else
894     {
895     int offset;
896    
897     for(offset=0;offset<nprev;offset++)
898     {
899 amb 1168 if(DISTFLAG(segmentx->distance)==DISTFLAG(prevsegx[offset].distance))
900 amb 1132 if(!WaysCompare(&prevway[offset],&wayx->way))
901     {
902     isduplicate=1;
903     break;
904     }
905     }
906    
907     if(isduplicate)
908     {
909     nprev--;
910    
911     for(;offset<nprev;offset++)
912     {
913     prevsegx[offset]=prevsegx[offset+1];
914     prevway[offset] =prevway[offset+1];
915     }
916     }
917     else
918     {
919 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. */
920 amb 1132
921     prevsegx[nprev]=*segmentx;
922     prevway[nprev] =wayx->way;
923    
924     nprev++;
925     }
926     }
927    
928     return(!isduplicate);
929     }
930    
931    
932     /*++++++++++++++++++++++++++++++++++++++
933 amb 1160 Sort the segments geographically after updating the node indexes.
934 amb 209
935 amb 681 SegmentsX *segmentsx The set of segments to modify.
936 amb 209
937 amb 1100 NodesX *nodesx The set of nodes to use.
938 amb 209 ++++++++++++++++++++++++++++++++++++++*/
939    
940 amb 1160 void SortSegmentListGeographically(SegmentsX *segmentsx,NodesX *nodesx)
941 amb 209 {
942 amb 1160 int fd;
943 amb 209
944 amb 1208 if(segmentsx->number==0)
945     return;
946    
947 amb 275 /* Print the start message */
948    
949 amb 1160 printf_first("Sorting Segments Geographically");
950 amb 227
951 amb 1160 /* Re-open the file read-only and a new file writeable */
952 amb 643
953 amb 1160 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
954 amb 643
955 amb 1160 DeleteFile(segmentsx->filename_tmp);
956 amb 643
957 amb 1160 fd=OpenFileNew(segmentsx->filename_tmp);
958 amb 1102
959 amb 1160 /* Update the segments with geographically sorted node indexes and sort them */
960 amb 643
961 amb 1160 sortnodesx=nodesx;
962 amb 209
963 amb 1160 filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))geographically_index,
964     (int (*)(const void*,const void*))sort_by_id,
965     NULL);
966     /* Close the files */
967 amb 275
968 amb 1160 segmentsx->fd=CloseFile(segmentsx->fd);
969     CloseFile(fd);
970 amb 280
971 amb 1160 /* Print the final message */
972 amb 209
973 amb 1160 printf_last("Sorted Segments Geographically: Segments=%"Pindex_t,segmentsx->number);
974     }
975 amb 1098
976 amb 1100
977 amb 1160 /*++++++++++++++++++++++++++++++++++++++
978     Update the segment indexes.
979 amb 209
980 amb 1160 int geographically_index Return 1 if the value is to be kept, otherwise 0.
981 amb 448
982 amb 1160 SegmentX *segmentx The extended segment.
983 amb 558
984 amb 1160 index_t index The number of unsorted segments that have been read from the input file.
985     ++++++++++++++++++++++++++++++++++++++*/
986 amb 209
987 amb 1160 static int geographically_index(SegmentX *segmentx,index_t index)
988     {
989     segmentx->node1=sortnodesx->gdata[segmentx->node1];
990     segmentx->node2=sortnodesx->gdata[segmentx->node2];
991 amb 275
992 amb 1160 if(segmentx->node1>segmentx->node2)
993     {
994     index_t temp;
995 amb 275
996 amb 1160 temp=segmentx->node1;
997     segmentx->node1=segmentx->node2;
998     segmentx->node2=temp;
999 amb 1100
1000 amb 1168 if(segmentx->distance&(ONEWAY_2TO1|ONEWAY_1TO2))
1001     segmentx->distance^=ONEWAY_2TO1|ONEWAY_1TO2;
1002 amb 1100 }
1003    
1004 amb 1160 return(1);
1005 amb 209 }
1006    
1007    
1008     /*++++++++++++++++++++++++++++++++++++++
1009 amb 285 Save the segment list to a file.
1010    
1011 amb 681 SegmentsX *segmentsx The set of segments to save.
1012 amb 285
1013     const char *filename The name of the file to save.
1014     ++++++++++++++++++++++++++++++++++++++*/
1015    
1016 amb 681 void SaveSegmentList(SegmentsX *segmentsx,const char *filename)
1017 amb 285 {
1018     index_t i;
1019     int fd;
1020 amb 500 SegmentsFile segmentsfile={0};
1021 amb 780 index_t super_number=0,normal_number=0;
1022 amb 285
1023     /* Print the start message */
1024    
1025 amb 519 printf_first("Writing Segments: Segments=0");
1026 amb 285
1027 amb 558 /* Re-open the file */
1028    
1029 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
1030 amb 558
1031 amb 461 /* Write out the segments data */
1032 amb 285
1033 amb 502 fd=OpenFileNew(filename);
1034 amb 461
1035     SeekFile(fd,sizeof(SegmentsFile));
1036    
1037 amb 285 for(i=0;i<segmentsx->number;i++)
1038     {
1039 amb 643 SegmentX segmentx;
1040 amb 944 Segment segment={0};
1041 amb 448
1042 amb 643 ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
1043 amb 558
1044 amb 1168 segment.node1 =segmentx.node1;
1045     segment.node2 =segmentx.node2;
1046     segment.next2 =segmentx.next2;
1047     segment.way =segmentx.way;
1048     segment.distance=segmentx.distance;
1049 amb 643
1050 amb 558 if(IsSuperSegment(&segment))
1051 amb 285 super_number++;
1052 amb 558 if(IsNormalSegment(&segment))
1053 amb 285 normal_number++;
1054    
1055 amb 558 WriteFile(fd,&segment,sizeof(Segment));
1056 amb 448
1057 amb 285 if(!((i+1)%10000))
1058 amb 790 printf_middle("Writing Segments: Segments=%"Pindex_t,i+1);
1059 amb 285 }
1060    
1061 amb 461 /* Write out the header structure */
1062    
1063     segmentsfile.number=segmentsx->number;
1064     segmentsfile.snumber=super_number;
1065     segmentsfile.nnumber=normal_number;
1066    
1067     SeekFile(fd,0);
1068     WriteFile(fd,&segmentsfile,sizeof(SegmentsFile));
1069    
1070 amb 285 CloseFile(fd);
1071    
1072 amb 558 /* Close the file */
1073    
1074 amb 643 segmentsx->fd=CloseFile(segmentsx->fd);
1075 amb 558
1076 amb 285 /* Print the final message */
1077    
1078 amb 790 printf_last("Wrote Segments: Segments=%"Pindex_t,segmentsx->number);
1079 amb 285 }
1080    
1081    
1082     /*++++++++++++++++++++++++++++++++++++++
1083 amb 110 Calculate the distance between two nodes.
1084    
1085 amb 1168 distance_t DistanceX Returns the distance between the extended nodes.
1086 amb 110
1087     NodeX *nodex1 The starting node.
1088    
1089     NodeX *nodex2 The end node.
1090     ++++++++++++++++++++++++++++++++++++++*/
1091    
1092 amb 1168 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
1093 amb 110 {
1094 amb 223 double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude);
1095     double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude);
1096     double lat1 = latlong_to_radians(nodex1->latitude);
1097     double lat2 = latlong_to_radians(nodex2->latitude);
1098 amb 110
1099 amb 219 double a1,a2,a,sa,c,d;
1100 amb 110
1101     if(dlon==0 && dlat==0)
1102     return 0;
1103    
1104 amb 219 a1 = sin (dlat / 2);
1105     a2 = sin (dlon / 2);
1106     a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
1107     sa = sqrt (a);
1108 amb 110 if (sa <= 1.0)
1109 amb 219 {c = 2 * asin (sa);}
1110 amb 110 else
1111 amb 219 {c = 2 * asin (1.0);}
1112 amb 110 d = 6378.137 * c;
1113    
1114     return km_to_distance(d);
1115     }

Properties

Name Value
cvs:description Extended segments functions.