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 1427 - (hide annotations) (download) (as text)
Thu Jun 27 18:01:14 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 25712 byte(s)
Revert the last change because, paradoxically, it was faster to create the
database (as expected) but slower to route.

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

Properties

Name Value
cvs:description Extended segments functions.