Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /branches/destination-access/src/segmentsx.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
cvs:description Extended segments functions.