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 1426 - (hide annotations) (download) (as text)
Wed Jun 26 18:26:27 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 23597 byte(s)
Sort the nodes geographically at the beginning rather than at the end.

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 1100 static SegmentsX *sortsegmentsx;
50 amb 1132 static WaysX *sortwaysx;
51 amb 1100
52 amb 680 /* Local functions */
53 amb 110
54 amb 275 static int sort_by_id(SegmentX *a,SegmentX *b);
55 amb 1160
56 amb 949 static int delete_pruned(SegmentX *segmentx,index_t index);
57 amb 1160
58 amb 1132 static int deduplicate_super(SegmentX *segmentx,index_t index);
59 amb 275
60 amb 1168 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2);
61 amb 110
62    
63     /*++++++++++++++++++++++++++++++++++++++
64 amb 326 Allocate a new segment list (create a new file or open an existing one).
65 amb 110
66     SegmentsX *NewSegmentList Returns the segment list.
67     ++++++++++++++++++++++++++++++++++++++*/
68    
69 amb 1339 SegmentsX *NewSegmentList(void)
70 amb 110 {
71     SegmentsX *segmentsx;
72    
73 amb 213 segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX));
74 amb 110
75 amb 1166 logassert(segmentsx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */
76 amb 243
77 amb 1120 segmentsx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
78 amb 216
79 amb 1339 sprintf(segmentsx->filename_tmp,"%s/segmentsx.%p.tmp",option_tmpdirname,(void*)segmentsx);
80 amb 256
81 amb 1402 segmentsx->fd=OpenFileBufferedNew(segmentsx->filename_tmp);
82 amb 326
83 amb 1297 #if SLIM
84     segmentsx->cache=NewSegmentXCache();
85     #endif
86    
87 amb 110 return(segmentsx);
88     }
89    
90    
91     /*++++++++++++++++++++++++++++++++++++++
92 amb 226 Free a segment list.
93 amb 110
94 amb 681 SegmentsX *segmentsx The set of segments to be freed.
95 amb 110 ++++++++++++++++++++++++++++++++++++++*/
96    
97 amb 1339 void FreeSegmentList(SegmentsX *segmentsx)
98 amb 110 {
99 amb 1339 DeleteFile(segmentsx->filename_tmp);
100 amb 1120
101     free(segmentsx->filename_tmp);
102 amb 256
103 amb 949 if(segmentsx->firstnode)
104     free(segmentsx->firstnode);
105    
106     if(segmentsx->next1)
107     free(segmentsx->next1);
108    
109 amb 1297 #if SLIM
110     DeleteSegmentXCache(segmentsx->cache);
111     #endif
112    
113 amb 110 free(segmentsx);
114     }
115    
116    
117     /*++++++++++++++++++++++++++++++++++++++
118 amb 493 Append a single segment to an unsorted segment list.
119 amb 110
120 amb 681 SegmentsX *segmentsx The set of segments to modify.
121 amb 110
122 amb 1349 index_t way The index of the way that the segment belongs to.
123 amb 285
124 amb 1349 index_t node1 The index of the first node in the segment.
125 amb 285
126 amb 1349 index_t node2 The index of the second node in the segment.
127 amb 285
128 amb 1168 distance_t distance The distance between the nodes (or just the flags).
129 amb 110 ++++++++++++++++++++++++++++++++++++++*/
130    
131 amb 1349 void AppendSegmentList(SegmentsX *segmentsx,index_t way,index_t node1,index_t node2,distance_t distance)
132 amb 110 {
133 amb 285 SegmentX segmentx;
134 amb 110
135 amb 643 if(node1>node2)
136     {
137 amb 1349 index_t temp;
138 amb 643
139     temp=node1;
140     node1=node2;
141     node2=temp;
142    
143 amb 1168 if(distance&(ONEWAY_2TO1|ONEWAY_1TO2))
144     distance^=ONEWAY_2TO1|ONEWAY_1TO2;
145 amb 643 }
146    
147 amb 285 segmentx.node1=node1;
148     segmentx.node2=node2;
149 amb 643 segmentx.next2=NO_SEGMENT;
150 amb 285 segmentx.way=way;
151 amb 1168 segmentx.distance=distance;
152 amb 110
153 amb 1402 WriteFileBuffered(segmentsx->fd,&segmentx,sizeof(SegmentX));
154 amb 281
155 amb 650 segmentsx->number++;
156 amb 466
157 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. */
158 amb 285 }
159 amb 227
160 amb 281
161 amb 285 /*++++++++++++++++++++++++++++++++++++++
162 amb 1120 Finish appending segments and change the filename over.
163    
164     SegmentsX *segmentsx The segments that have been appended.
165     ++++++++++++++++++++++++++++++++++++++*/
166    
167 amb 1151 void FinishSegmentList(SegmentsX *segmentsx)
168 amb 1120 {
169 amb 1136 if(segmentsx->fd!=-1)
170 amb 1402 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
171 amb 1120 }
172    
173    
174     /*++++++++++++++++++++++++++++++++++++++
175 amb 1160 Find the first extended segment with a particular starting node index.
176    
177     SegmentX *FirstSegmentX Returns a pointer to the first extended segment with the specified id.
178    
179     SegmentsX *segmentsx The set of segments to use.
180    
181     index_t nodeindex The node index to look for.
182    
183     int position A flag to pass through.
184     ++++++++++++++++++++++++++++++++++++++*/
185    
186     SegmentX *FirstSegmentX(SegmentsX *segmentsx,index_t nodeindex,int position)
187     {
188     index_t index=segmentsx->firstnode[nodeindex];
189     SegmentX *segmentx;
190    
191     if(index==NO_SEGMENT)
192     return(NULL);
193    
194     segmentx=LookupSegmentX(segmentsx,index,position);
195    
196     return(segmentx);
197     }
198    
199    
200     /*++++++++++++++++++++++++++++++++++++++
201     Find the next segment with a particular starting node index.
202    
203     SegmentX *NextSegmentX Returns a pointer to the next segment with the same id.
204    
205     SegmentsX *segmentsx The set of segments to use.
206    
207     SegmentX *segmentx The current segment.
208    
209     index_t nodeindex The node index.
210     ++++++++++++++++++++++++++++++++++++++*/
211    
212     SegmentX *NextSegmentX(SegmentsX *segmentsx,SegmentX *segmentx,index_t nodeindex)
213     {
214     #if SLIM
215     int position=1+(segmentx-&segmentsx->cached[0]);
216     #endif
217    
218     if(segmentx->node1==nodeindex)
219     {
220     if(segmentsx->next1)
221     {
222     index_t index=IndexSegmentX(segmentsx,segmentx);
223    
224     if(segmentsx->next1[index]==NO_SEGMENT)
225     return(NULL);
226    
227     segmentx=LookupSegmentX(segmentsx,segmentsx->next1[index],position);
228    
229     return(segmentx);
230     }
231     else
232     {
233     #if SLIM
234     index_t index=IndexSegmentX(segmentsx,segmentx);
235     index++;
236    
237     if(index>=segmentsx->number)
238     return(NULL);
239    
240     segmentx=LookupSegmentX(segmentsx,index,position);
241     #else
242     segmentx++;
243    
244     if(IndexSegmentX(segmentsx,segmentx)>=segmentsx->number)
245     return(NULL);
246     #endif
247    
248     if(segmentx->node1!=nodeindex)
249     return(NULL);
250    
251     return(segmentx);
252     }
253     }
254     else
255     {
256     if(segmentx->next2==NO_SEGMENT)
257     return(NULL);
258    
259     return(LookupSegmentX(segmentsx,segmentx->next2,position));
260     }
261     }
262    
263    
264     /*++++++++++++++++++++++++++++++++++++++
265 amb 1354 Sort the segment list.
266 amb 1100
267 amb 1354 SegmentsX *segmentsx The set of segments to sort.
268 amb 285 ++++++++++++++++++++++++++++++++++++++*/
269 amb 110
270 amb 1160 void SortSegmentList(SegmentsX *segmentsx)
271 amb 285 {
272     int fd;
273 amb 243
274 amb 285 /* Print the start message */
275 amb 232
276 amb 1160 printf_first("Sorting Segments");
277 amb 110
278 amb 555 /* Re-open the file read-only and a new file writeable */
279    
280 amb 1409 segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp);
281 amb 110
282 amb 1120 DeleteFile(segmentsx->filename_tmp);
283 amb 110
284 amb 1409 fd=OpenFileBufferedNew(segmentsx->filename_tmp);
285 amb 110
286 amb 285 /* Sort by node indexes */
287 amb 132
288 amb 1160 segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL,
289 amb 1132 (int (*)(const void*,const void*))sort_by_id,
290 amb 1354 NULL);
291 amb 1100
292 amb 555 /* Close the files */
293 amb 285
294 amb 1409 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
295     CloseFileBuffered(fd);
296 amb 281
297     /* Print the final message */
298    
299 amb 1355 printf_last("Sorted Segments: Segments=%"Pindex_t,segmentsx->number);
300 amb 110 }
301    
302    
303     /*++++++++++++++++++++++++++++++++++++++
304 amb 680 Sort the segments into id order, first by node1 then by node2, finally by distance.
305 amb 110
306 amb 285 int sort_by_id Returns the comparison of the node fields.
307 amb 110
308 amb 285 SegmentX *a The first segment.
309 amb 110
310 amb 285 SegmentX *b The second segment.
311 amb 256 ++++++++++++++++++++++++++++++++++++++*/
312    
313 amb 285 static int sort_by_id(SegmentX *a,SegmentX *b)
314 amb 256 {
315 amb 1349 index_t a_id1=a->node1;
316     index_t b_id1=b->node1;
317 amb 256
318 amb 285 if(a_id1<b_id1)
319     return(-1);
320     else if(a_id1>b_id1)
321     return(1);
322     else /* if(a_id1==b_id1) */
323 amb 256 {
324 amb 1349 index_t a_id2=a->node2;
325     index_t b_id2=b->node2;
326 amb 256
327 amb 285 if(a_id2<b_id2)
328     return(-1);
329     else if(a_id2>b_id2)
330     return(1);
331     else
332     {
333 amb 1168 distance_t a_distance=DISTANCE(a->distance);
334     distance_t b_distance=DISTANCE(b->distance);
335 amb 256
336 amb 1168 if(a_distance<b_distance)
337 amb 285 return(-1);
338 amb 1168 else if(a_distance>b_distance)
339 amb 285 return(1);
340     else
341 amb 1153 {
342 amb 1168 distance_t a_distflag=DISTFLAG(a->distance);
343     distance_t b_distflag=DISTFLAG(b->distance);
344 amb 1153
345 amb 1168 if(a_distflag<b_distflag)
346 amb 1153 return(-1);
347 amb 1168 else if(a_distflag>b_distflag)
348 amb 1153 return(1);
349     else
350     return(FILESORT_PRESERVE_ORDER(a,b)); /* preserve order */
351     }
352 amb 285 }
353 amb 256 }
354     }
355    
356    
357     /*++++++++++++++++++++++++++++++++++++++
358 amb 1351 Process segments (non-trivial duplicates).
359 amb 110
360 amb 1136 SegmentsX *segmentsx The set of segments to modify.
361    
362 amb 681 NodesX *nodesx The set of nodes to use.
363 amb 195
364 amb 1140 WaysX *waysx The set of ways to use.
365 amb 110 ++++++++++++++++++++++++++++++++++++++*/
366    
367 amb 1351 void ProcessSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
368 amb 110 {
369 amb 1349 index_t duplicate=0,good=0,total=0;
370     index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
371     index_t prevway=NO_WAY;
372 amb 1168 distance_t prevdist=0;
373 amb 275 SegmentX segmentx;
374     int fd;
375 amb 110
376 amb 275 /* Print the start message */
377    
378 amb 1351 printf_first("Processing Segments: Segments=0 Duplicates=0");
379 amb 227
380 amb 1349 /* Map into memory / open the file */
381    
382     #if !SLIM
383     nodesx->data=MapFile(nodesx->filename_tmp);
384     waysx->data=MapFile(waysx->filename_tmp);
385     #else
386 amb 1414 nodesx->fd=SlimMapFile(nodesx->filename_tmp);
387     waysx->fd=SlimMapFile(waysx->filename_tmp);
388 amb 1349
389     InvalidateNodeXCache(nodesx->cache);
390     InvalidateWayXCache(waysx->cache);
391     #endif
392    
393 amb 1351 /* Allocate the way usage bitmask */
394    
395     segmentsx->usedway=AllocBitMask(waysx->number);
396    
397     logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
398    
399 amb 555 /* Re-open the file read-only and a new file writeable */
400 amb 275
401 amb 1408 segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp);
402 amb 555
403 amb 1339 DeleteFile(segmentsx->filename_tmp);
404 amb 275
405 amb 1408 fd=OpenFileBufferedNew(segmentsx->filename_tmp);
406 amb 275
407 amb 555 /* Modify the on-disk image */
408    
409 amb 1408 while(!ReadFileBuffered(segmentsx->fd,&segmentx,sizeof(SegmentX)))
410 amb 110 {
411 amb 1351 NodeX *nodex1=LookupNodeX(nodesx,segmentx.node1,1);
412     NodeX *nodex2=LookupNodeX(nodesx,segmentx.node2,2);
413    
414 amb 1349 if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2)
415 amb 812 {
416 amb 1349 if(prevway==segmentx.way)
417     {
418     WayX *wayx=LookupWayX(waysx,segmentx.way,1);
419 amb 812
420 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));
421     }
422 amb 1173 else
423     {
424     if(!(prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA))
425 amb 1349 logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated.\n",logerror_node(nodex1->id),logerror_node(nodex2->id));
426 amb 1155
427 amb 1173 if(!(prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA))
428 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));
429 amb 1155
430 amb 1173 if((prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA))
431 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));
432 amb 1155
433 amb 1173 if((prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA))
434 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));
435 amb 1173 }
436 amb 1155
437     duplicate++;
438     }
439 amb 275 else
440 amb 257 {
441 amb 1155 prevnode1=segmentx.node1;
442     prevnode2=segmentx.node2;
443 amb 1173 prevway=segmentx.way;
444 amb 1168 prevdist=DISTANCE(segmentx.distance);
445 amb 1155
446 amb 1351 /* Mark the ways which are used */
447    
448     SetBit(segmentsx->usedway,segmentx.way);
449    
450     /* Set the distance but keep the other flags except for area */
451    
452     segmentx.distance=DISTANCE(DistanceX(nodex1,nodex2))|DISTFLAG(segmentx.distance);
453     segmentx.distance&=~SEGMENT_AREA;
454    
455     /* Write the modified segment */
456    
457 amb 1408 WriteFileBuffered(fd,&segmentx,sizeof(SegmentX));
458 amb 1351
459 amb 275 good++;
460 amb 110 }
461    
462 amb 275 total++;
463 amb 256
464 amb 275 if(!(total%10000))
465 amb 1351 printf_middle("Processing Segments: Segments=%"Pindex_t" Duplicates=%"Pindex_t,total,duplicate);
466 amb 110 }
467    
468 amb 555 segmentsx->number=good;
469 amb 275
470 amb 555 /* Close the files */
471    
472 amb 1408 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
473     CloseFileBuffered(fd);
474 amb 275
475 amb 1349 /* Unmap from memory / close the file */
476    
477     #if !SLIM
478     nodesx->data=UnmapFile(nodesx->data);
479     waysx->data=UnmapFile(waysx->data);
480     #else
481 amb 1414 nodesx->fd=SlimUnmapFile(nodesx->fd);
482     waysx->fd=SlimUnmapFile(waysx->fd);
483 amb 1349 #endif
484    
485 amb 275 /* Print the final message */
486    
487 amb 1351 printf_last("Processed Segments: Segments=%"Pindex_t" Duplicates=%"Pindex_t,total,duplicate);
488 amb 110 }
489    
490    
491     /*++++++++++++++++++++++++++++++++++++++
492 amb 1160 Index the segments by creating the firstnode index and filling in the segment next2 parameter.
493    
494     SegmentsX *segmentsx The set of segments to modify.
495    
496     NodesX *nodesx The set of nodes to use.
497    
498     WaysX *waysx The set of ways to use.
499     ++++++++++++++++++++++++++++++++++++++*/
500    
501     void IndexSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx)
502     {
503 amb 1422 index_t index,start=0,i;
504     SegmentX *segmentx_list=NULL;
505     #if SLIM
506     index_t length=0;
507     #endif
508 amb 1160
509     if(segmentsx->number==0)
510     return;
511    
512     /* Print the start message */
513    
514     printf_first("Indexing Segments: Segments=0");
515    
516     /* Allocate the array of indexes */
517    
518     if(segmentsx->firstnode)
519     free(segmentsx->firstnode);
520    
521     segmentsx->firstnode=(index_t*)malloc(nodesx->number*sizeof(index_t));
522    
523 amb 1166 logassert(segmentsx->firstnode,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
524 amb 1160
525     for(i=0;i<nodesx->number;i++)
526     segmentsx->firstnode[i]=NO_SEGMENT;
527    
528     /* Map into memory / open the files */
529    
530     #if !SLIM
531     segmentsx->data=MapFileWriteable(segmentsx->filename_tmp);
532     #else
533 amb 1414 segmentsx->fd=SlimMapFileWriteable(segmentsx->filename_tmp);
534 amb 1297
535 amb 1422 segmentx_list=(SegmentX*)malloc(1024*sizeof(SegmentX));
536 amb 1160 #endif
537    
538 amb 1422 /* Read through the segments in reverse order (in chunks to help slim mode) */
539 amb 1160
540     for(index=segmentsx->number-1;index!=NO_SEGMENT;index--)
541     {
542 amb 1422 SegmentX *segmentx;
543 amb 1160
544 amb 1422 if((index%1024)==1023 || index==(segmentsx->number-1))
545     {
546     start=1024*(index/1024);
547    
548     #if !SLIM
549     segmentx_list=LookupSegmentX(segmentsx,start,1);
550     #else
551     length=index-start+1;
552    
553     SlimFetch(segmentsx->fd,segmentx_list,length*sizeof(SegmentX),start*sizeof(SegmentX));
554     #endif
555     }
556    
557     segmentx=segmentx_list+(index-start);
558    
559 amb 1160 if(nodesx->pdata)
560     {
561     segmentx->node1=nodesx->pdata[segmentx->node1];
562     segmentx->node2=nodesx->pdata[segmentx->node2];
563     }
564    
565     if(waysx->cdata)
566     segmentx->way=waysx->cdata[segmentx->way];
567    
568     segmentx->next2=segmentsx->firstnode[segmentx->node2];
569    
570     segmentsx->firstnode[segmentx->node1]=index;
571     segmentsx->firstnode[segmentx->node2]=index;
572    
573     if(!(index%10000))
574     printf_middle("Indexing Segments: Segments=%"Pindex_t,segmentsx->number-index);
575 amb 1422
576     #if SLIM
577     if(index==start)
578     SlimReplace(segmentsx->fd,segmentx_list,length*sizeof(SegmentX),start*sizeof(SegmentX));
579     #endif
580 amb 1160 }
581    
582     /* Unmap from memory / close the files */
583    
584     #if !SLIM
585     segmentsx->data=UnmapFile(segmentsx->data);
586     #else
587 amb 1414 segmentsx->fd=SlimUnmapFile(segmentsx->fd);
588 amb 1422
589     free(segmentx_list);
590 amb 1160 #endif
591    
592     /* Free the memory */
593    
594     if(nodesx->pdata)
595     {
596     free(nodesx->pdata);
597     nodesx->pdata=NULL;
598     }
599    
600     if(waysx->cdata)
601     {
602     free(waysx->cdata);
603     waysx->cdata=NULL;
604     }
605    
606     /* Print the final message */
607    
608     printf_last("Indexed Segments: Segments=%"Pindex_t,segmentsx->number);
609     }
610    
611    
612     /*++++++++++++++++++++++++++++++++++++++
613     Prune the deleted segments while resorting the list.
614    
615     SegmentsX *segmentsx The set of segments to sort and modify.
616    
617     WaysX *waysx The set of ways to check.
618     ++++++++++++++++++++++++++++++++++++++*/
619    
620     void RemovePrunedSegments(SegmentsX *segmentsx,WaysX *waysx)
621     {
622     int fd;
623     index_t xnumber;
624    
625 amb 1208 if(segmentsx->number==0)
626     return;
627    
628 amb 1160 /* Print the start message */
629    
630     printf_first("Sorting and Pruning Segments");
631    
632     /* Allocate the way usage bitmask */
633    
634     segmentsx->usedway=AllocBitMask(waysx->number);
635    
636 amb 1166 logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
637 amb 1160
638     /* Re-open the file read-only and a new file writeable */
639    
640 amb 1409 segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp);
641 amb 1160
642     DeleteFile(segmentsx->filename_tmp);
643    
644 amb 1409 fd=OpenFileBufferedNew(segmentsx->filename_tmp);
645 amb 1160
646     /* Sort by node indexes */
647    
648     xnumber=segmentsx->number;
649    
650     sortsegmentsx=segmentsx;
651    
652     segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))delete_pruned,
653     (int (*)(const void*,const void*))sort_by_id,
654     NULL);
655    
656     /* Close the files */
657    
658 amb 1409 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
659     CloseFileBuffered(fd);
660 amb 1160
661     /* Print the final message */
662    
663     printf_last("Sorted and Pruned Segments: Segments=%"Pindex_t" Deleted=%"Pindex_t,xnumber,xnumber-segmentsx->number);
664     }
665    
666    
667     /*++++++++++++++++++++++++++++++++++++++
668     Delete the pruned segments.
669    
670     int delete_pruned Return 1 if the value is to be kept, otherwise 0.
671    
672     SegmentX *segmentx The extended segment.
673    
674     index_t index The number of unsorted segments that have been read from the input file.
675     ++++++++++++++++++++++++++++++++++++++*/
676    
677     static int delete_pruned(SegmentX *segmentx,index_t index)
678     {
679     if(IsPrunedSegmentX(segmentx))
680     return(0);
681    
682     SetBit(sortsegmentsx->usedway,segmentx->way);
683    
684     return(1);
685     }
686    
687    
688     /*++++++++++++++++++++++++++++++++++++++
689 amb 1132 Remove the duplicate super-segments.
690 amb 110
691 amb 1132 SegmentsX *segmentsx The set of super-segments to modify.
692 amb 110
693 amb 680 WaysX *waysx The set of ways to use.
694 amb 110 ++++++++++++++++++++++++++++++++++++++*/
695    
696 amb 1132 void DeduplicateSuperSegments(SegmentsX *segmentsx,WaysX *waysx)
697 amb 110 {
698 amb 1132 int fd;
699     index_t xnumber;
700 amb 110
701 amb 1208 if(waysx->number==0)
702     return;
703    
704 amb 275 /* Print the start message */
705    
706 amb 1132 printf_first("Sorting and Deduplicating Super-Segments");
707 amb 227
708 amb 555 /* Map into memory / open the file */
709 amb 256
710 amb 452 #if !SLIM
711 amb 1120 waysx->data=MapFile(waysx->filename_tmp);
712 amb 555 #else
713 amb 1414 waysx->fd=SlimMapFile(waysx->filename_tmp);
714 amb 1297
715     InvalidateWayXCache(waysx->cache);
716 amb 452 #endif
717 amb 275
718 amb 555 /* Re-open the file read-only and a new file writeable */
719 amb 275
720 amb 1409 segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp);
721 amb 555
722 amb 1120 DeleteFile(segmentsx->filename_tmp);
723 amb 275
724 amb 1409 fd=OpenFileBufferedNew(segmentsx->filename_tmp);
725 amb 275
726 amb 1132 /* Sort by node indexes */
727 amb 555
728 amb 1132 xnumber=segmentsx->number;
729 amb 256
730 amb 1132 sortsegmentsx=segmentsx;
731     sortwaysx=waysx;
732 amb 110
733 amb 1132 segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL,
734     (int (*)(const void*,const void*))sort_by_id,
735     (int (*)(void*,index_t))deduplicate_super);
736 amb 264
737 amb 555 /* Close the files */
738    
739 amb 1409 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
740     CloseFileBuffered(fd);
741 amb 275
742 amb 555 /* Unmap from memory / close the file */
743 amb 275
744 amb 452 #if !SLIM
745 amb 1122 waysx->data=UnmapFile(waysx->data);
746 amb 555 #else
747 amb 1414 waysx->fd=SlimUnmapFile(waysx->fd);
748 amb 452 #endif
749 amb 275
750     /* Print the final message */
751    
752 amb 1132 printf_last("Sorted and Deduplicated Super-Segments: Super-Segments=%"Pindex_t" Duplicate=%"Pindex_t,xnumber,xnumber-segmentsx->number);
753 amb 110 }
754    
755    
756     /*++++++++++++++++++++++++++++++++++++++
757 amb 1132 De-duplicate super-segments.
758    
759     int deduplicate_super Return 1 if the value is to be kept, otherwise 0.
760    
761     SegmentX *segmentx The extended super-segment.
762    
763     index_t index The number of sorted super-segments that have already been written to the output file.
764     ++++++++++++++++++++++++++++++++++++++*/
765    
766     static int deduplicate_super(SegmentX *segmentx,index_t index)
767     {
768     static int nprev=0;
769     static index_t prevnode1=NO_NODE,prevnode2=NO_NODE;
770     static SegmentX prevsegx[MAX_SEG_PER_NODE];
771     static Way prevway[MAX_SEG_PER_NODE];
772    
773     WayX *wayx=LookupWayX(sortwaysx,segmentx->way,1);
774     int isduplicate=0;
775    
776     if(index==0 || segmentx->node1!=prevnode1 || segmentx->node2!=prevnode2)
777     {
778     nprev=1;
779     prevnode1=segmentx->node1;
780     prevnode2=segmentx->node2;
781     prevsegx[0]=*segmentx;
782     prevway[0] =wayx->way;
783     }
784     else
785     {
786     int offset;
787    
788     for(offset=0;offset<nprev;offset++)
789     {
790 amb 1168 if(DISTFLAG(segmentx->distance)==DISTFLAG(prevsegx[offset].distance))
791 amb 1132 if(!WaysCompare(&prevway[offset],&wayx->way))
792     {
793     isduplicate=1;
794     break;
795     }
796     }
797    
798     if(isduplicate)
799     {
800     nprev--;
801    
802     for(;offset<nprev;offset++)
803     {
804     prevsegx[offset]=prevsegx[offset+1];
805     prevway[offset] =prevway[offset+1];
806     }
807     }
808     else
809     {
810 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. */
811 amb 1132
812     prevsegx[nprev]=*segmentx;
813     prevway[nprev] =wayx->way;
814    
815     nprev++;
816     }
817     }
818    
819     return(!isduplicate);
820     }
821    
822    
823     /*++++++++++++++++++++++++++++++++++++++
824 amb 285 Save the segment list to a file.
825    
826 amb 681 SegmentsX *segmentsx The set of segments to save.
827 amb 285
828     const char *filename The name of the file to save.
829     ++++++++++++++++++++++++++++++++++++++*/
830    
831 amb 681 void SaveSegmentList(SegmentsX *segmentsx,const char *filename)
832 amb 285 {
833     index_t i;
834     int fd;
835 amb 500 SegmentsFile segmentsfile={0};
836 amb 780 index_t super_number=0,normal_number=0;
837 amb 285
838     /* Print the start message */
839    
840 amb 519 printf_first("Writing Segments: Segments=0");
841 amb 285
842 amb 558 /* Re-open the file */
843    
844 amb 1408 segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp);
845 amb 558
846 amb 461 /* Write out the segments data */
847 amb 285
848 amb 1408 fd=OpenFileBufferedNew(filename);
849 amb 461
850 amb 1408 SeekFileBuffered(fd,sizeof(SegmentsFile));
851 amb 461
852 amb 285 for(i=0;i<segmentsx->number;i++)
853     {
854 amb 643 SegmentX segmentx;
855 amb 944 Segment segment={0};
856 amb 448
857 amb 1408 ReadFileBuffered(segmentsx->fd,&segmentx,sizeof(SegmentX));
858 amb 558
859 amb 1168 segment.node1 =segmentx.node1;
860     segment.node2 =segmentx.node2;
861     segment.next2 =segmentx.next2;
862     segment.way =segmentx.way;
863     segment.distance=segmentx.distance;
864 amb 643
865 amb 558 if(IsSuperSegment(&segment))
866 amb 285 super_number++;
867 amb 558 if(IsNormalSegment(&segment))
868 amb 285 normal_number++;
869    
870 amb 1408 WriteFileBuffered(fd,&segment,sizeof(Segment));
871 amb 448
872 amb 285 if(!((i+1)%10000))
873 amb 790 printf_middle("Writing Segments: Segments=%"Pindex_t,i+1);
874 amb 285 }
875    
876 amb 461 /* Write out the header structure */
877    
878     segmentsfile.number=segmentsx->number;
879     segmentsfile.snumber=super_number;
880     segmentsfile.nnumber=normal_number;
881    
882 amb 1408 SeekFileBuffered(fd,0);
883     WriteFileBuffered(fd,&segmentsfile,sizeof(SegmentsFile));
884 amb 461
885 amb 1408 CloseFileBuffered(fd);
886 amb 285
887 amb 558 /* Close the file */
888    
889 amb 1408 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
890 amb 558
891 amb 285 /* Print the final message */
892    
893 amb 790 printf_last("Wrote Segments: Segments=%"Pindex_t,segmentsx->number);
894 amb 285 }
895    
896    
897     /*++++++++++++++++++++++++++++++++++++++
898 amb 110 Calculate the distance between two nodes.
899    
900 amb 1168 distance_t DistanceX Returns the distance between the extended nodes.
901 amb 110
902     NodeX *nodex1 The starting node.
903    
904     NodeX *nodex2 The end node.
905     ++++++++++++++++++++++++++++++++++++++*/
906    
907 amb 1168 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
908 amb 110 {
909 amb 223 double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude);
910     double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude);
911     double lat1 = latlong_to_radians(nodex1->latitude);
912     double lat2 = latlong_to_radians(nodex2->latitude);
913 amb 110
914 amb 219 double a1,a2,a,sa,c,d;
915 amb 110
916     if(dlon==0 && dlat==0)
917     return 0;
918    
919 amb 219 a1 = sin (dlat / 2);
920     a2 = sin (dlon / 2);
921     a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
922     sa = sqrt (a);
923 amb 110 if (sa <= 1.0)
924 amb 219 {c = 2 * asin (sa);}
925 amb 110 else
926 amb 219 {c = 2 * asin (1.0);}
927 amb 110 d = 6378.137 * c;
928    
929     return km_to_distance(d);
930     }

Properties

Name Value
cvs:description Extended segments functions.