Routino SVN Repository Browser

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

ViewVC logotype

Contents of /trunk/src/nodesx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1784 - (show annotations) (download) (as text)
Sat Aug 15 13:08:37 2015 UTC (9 years, 7 months ago) by amb
File MIME type: text/x-csrc
File size: 22105 byte(s)
Merge libroutino branch back into the trunk.

1 /***************************************
2 Extented Node data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2015 Andrew M. Bishop
7
8 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 ***************************************/
21
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "types.h"
27 #include "nodes.h"
28
29 #include "typesx.h"
30 #include "nodesx.h"
31 #include "segmentsx.h"
32 #include "waysx.h"
33
34 #include "files.h"
35 #include "logging.h"
36 #include "sorting.h"
37
38
39 /* Global variables */
40
41 /*+ The command line '--tmpdir' option or its default value. +*/
42 extern char *option_tmpdirname;
43
44 /* Local variables */
45
46 /*+ Temporary file-local variables for use by the sort functions (re-initialised for each sort). +*/
47 static NodesX *sortnodesx;
48 static latlong_t lat_min,lat_max,lon_min,lon_max;
49
50 /* Local functions */
51
52 static int sort_by_id(NodeX *a,NodeX *b);
53 static int deduplicate_and_index_by_id(NodeX *nodex,index_t index);
54
55 static int update_id(NodeX *nodex,index_t index);
56 static int sort_by_lat_long(NodeX *a,NodeX *b);
57 static int index_by_lat_long(NodeX *nodex,index_t index);
58
59
60 /*++++++++++++++++++++++++++++++++++++++
61 Allocate a new node list (create a new file or open an existing one).
62
63 NodesX *NewNodeList Returns a pointer to the node list.
64
65 int append Set to 1 if the file is to be opened for appending.
66
67 int readonly Set to 1 if the file is to be opened for reading.
68 ++++++++++++++++++++++++++++++++++++++*/
69
70 NodesX *NewNodeList(int append,int readonly)
71 {
72 NodesX *nodesx;
73
74 nodesx=(NodesX*)calloc(1,sizeof(NodesX));
75
76 logassert(nodesx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */
77
78 nodesx->filename =(char*)malloc(strlen(option_tmpdirname)+32);
79 nodesx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+40); /* allow %p to be up to 20 bytes */
80
81 sprintf(nodesx->filename ,"%s/nodesx.parsed.mem",option_tmpdirname);
82 sprintf(nodesx->filename_tmp,"%s/nodesx.%p.tmp" ,option_tmpdirname,(void*)nodesx);
83
84 if(append || readonly)
85 if(ExistsFile(nodesx->filename))
86 {
87 offset_t size;
88
89 size=SizeFile(nodesx->filename);
90
91 nodesx->number=size/sizeof(NodeX);
92
93 RenameFile(nodesx->filename,nodesx->filename_tmp);
94 }
95
96 if(append)
97 nodesx->fd=OpenFileBufferedAppend(nodesx->filename_tmp);
98 else if(!readonly)
99 nodesx->fd=OpenFileBufferedNew(nodesx->filename_tmp);
100 else
101 nodesx->fd=-1;
102
103 #if SLIM
104 nodesx->cache=NewNodeXCache();
105 log_malloc(nodesx->cache,sizeof(*nodesx->cache));
106 #endif
107
108 return(nodesx);
109 }
110
111
112 /*++++++++++++++++++++++++++++++++++++++
113 Free a node list.
114
115 NodesX *nodesx The set of nodes to be freed.
116
117 int keep If set then the results file is to be kept.
118 ++++++++++++++++++++++++++++++++++++++*/
119
120 void FreeNodeList(NodesX *nodesx,int keep)
121 {
122 if(keep)
123 RenameFile(nodesx->filename_tmp,nodesx->filename);
124 else
125 DeleteFile(nodesx->filename_tmp);
126
127 free(nodesx->filename);
128 free(nodesx->filename_tmp);
129
130 if(nodesx->idata)
131 {
132 log_free(nodesx->idata);
133 free(nodesx->idata);
134 }
135
136 if(nodesx->gdata)
137 {
138 log_free(nodesx->gdata);
139 free(nodesx->gdata);
140 }
141
142 if(nodesx->pdata)
143 {
144 log_free(nodesx->pdata);
145 free(nodesx->pdata);
146 }
147
148 if(nodesx->super)
149 {
150 log_free(nodesx->super);
151 free(nodesx->super);
152 }
153
154 #if SLIM
155 log_free(nodesx->cache);
156 DeleteNodeXCache(nodesx->cache);
157 #endif
158
159 free(nodesx);
160 }
161
162
163 /*++++++++++++++++++++++++++++++++++++++
164 Append a single node to an unsorted node list.
165
166 NodesX *nodesx The set of nodes to modify.
167
168 node_t id The node identifier from the original OSM data.
169
170 double latitude The latitude of the node.
171
172 double longitude The longitude of the node.
173
174 transports_t allow The allowed traffic types through the node.
175
176 nodeflags_t flags The flags to set for this node.
177 ++++++++++++++++++++++++++++++++++++++*/
178
179 void AppendNodeList(NodesX *nodesx,node_t id,double latitude,double longitude,transports_t allow,nodeflags_t flags)
180 {
181 NodeX nodex;
182
183 nodex.id=id;
184 nodex.latitude =radians_to_latlong(latitude);
185 nodex.longitude=radians_to_latlong(longitude);
186 nodex.allow=allow;
187 nodex.flags=flags;
188
189 WriteFileBuffered(nodesx->fd,&nodex,sizeof(NodeX));
190
191 nodesx->number++;
192
193 logassert(nodesx->number<NODE_FAKE,"Too many nodes (change index_t to 64-bits?)"); /* NODE_FAKE marks the high-water mark for real nodes. */
194 }
195
196
197 /*++++++++++++++++++++++++++++++++++++++
198 Finish appending nodes and change the filename over.
199
200 NodesX *nodesx The nodes that have been appended.
201 ++++++++++++++++++++++++++++++++++++++*/
202
203 void FinishNodeList(NodesX *nodesx)
204 {
205 if(nodesx->fd!=-1)
206 nodesx->fd=CloseFileBuffered(nodesx->fd);
207 }
208
209
210 /*++++++++++++++++++++++++++++++++++++++
211 Find a particular node index.
212
213 index_t IndexNodeX Returns the index of the extended node with the specified id.
214
215 NodesX *nodesx The set of nodes to use.
216
217 node_t id The node id to look for.
218 ++++++++++++++++++++++++++++++++++++++*/
219
220 index_t IndexNodeX(NodesX *nodesx,node_t id)
221 {
222 index_t start=0;
223 index_t end=nodesx->number-1;
224 index_t mid;
225
226 if(nodesx->number==0) /* No nodes */
227 return(NO_NODE);
228
229 if(id<nodesx->idata[start]) /* Key is before start */
230 return(NO_NODE);
231
232 if(id>nodesx->idata[end]) /* Key is after end */
233 return(NO_NODE);
234
235 /* Binary search - search key exact match only is required.
236 *
237 * # <- start | Check mid and move start or end if it doesn't match
238 * # |
239 * # | Since an exact match is wanted we can set end=mid-1
240 * # <- mid | or start=mid+1 because we know that mid doesn't match.
241 * # |
242 * # | Eventually either end=start or end=start+1 and one of
243 * # <- end | start or end is the wanted one.
244 */
245
246 do
247 {
248 mid=(start+end)/2; /* Choose mid point */
249
250 if(nodesx->idata[mid]<id) /* Mid point is too low */
251 start=mid+1;
252 else if(nodesx->idata[mid]>id) /* Mid point is too high */
253 end=mid?(mid-1):mid;
254 else /* Mid point is correct */
255 return(mid);
256 }
257 while((end-start)>1);
258
259 if(nodesx->idata[start]==id) /* Start is correct */
260 return(start);
261
262 if(nodesx->idata[end]==id) /* End is correct */
263 return(end);
264
265 return(NO_NODE);
266 }
267
268
269 /*++++++++++++++++++++++++++++++++++++++
270 Sort the node list.
271
272 NodesX *nodesx The set of nodes to modify.
273 ++++++++++++++++++++++++++++++++++++++*/
274
275 void SortNodeList(NodesX *nodesx)
276 {
277 int fd;
278 index_t xnumber;
279
280 /* Print the start message */
281
282 printf_first("Sorting Nodes");
283
284 /* Re-open the file read-only and a new file writeable */
285
286 fd=ReplaceFileBuffered(nodesx->filename_tmp,&nodesx->fd);
287
288 /* Allocate the array of indexes */
289
290 nodesx->idata=(node_t*)malloc(nodesx->number*sizeof(node_t));
291 log_malloc(nodesx->idata,nodesx->number*sizeof(node_t));
292
293 logassert(nodesx->idata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
294
295 /* Sort the nodes by ID and index them */
296
297 xnumber=nodesx->number;
298
299 sortnodesx=nodesx;
300
301 nodesx->number=filesort_fixed(nodesx->fd,fd,sizeof(NodeX),NULL,
302 (int (*)(const void*,const void*))sort_by_id,
303 (int (*)(void*,index_t))deduplicate_and_index_by_id);
304
305 nodesx->knumber=nodesx->number;
306
307 /* Close the files */
308
309 nodesx->fd=CloseFileBuffered(nodesx->fd);
310 CloseFileBuffered(fd);
311
312 /* Print the final message */
313
314 printf_last("Sorted Nodes: Nodes=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-nodesx->number);
315 }
316
317
318 /*++++++++++++++++++++++++++++++++++++++
319 Sort the nodes into id order.
320
321 int sort_by_id Returns the comparison of the id fields.
322
323 NodeX *a The first extended node.
324
325 NodeX *b The second extended node.
326 ++++++++++++++++++++++++++++++++++++++*/
327
328 static int sort_by_id(NodeX *a,NodeX *b)
329 {
330 node_t a_id=a->id;
331 node_t b_id=b->id;
332
333 if(a_id<b_id)
334 return(-1);
335 else if(a_id>b_id)
336 return(1);
337 else
338 return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */
339 }
340
341
342 /*++++++++++++++++++++++++++++++++++++++
343 Create the index of identifiers and discard duplicate nodes.
344
345 int deduplicate_and_index_by_id Return 1 if the value is to be kept, otherwise 0.
346
347 NodeX *nodex The extended node.
348
349 index_t index The number of sorted nodes that have already been written to the output file.
350 ++++++++++++++++++++++++++++++++++++++*/
351
352 static int deduplicate_and_index_by_id(NodeX *nodex,index_t index)
353 {
354 static node_t previd; /* internal variable (reset by first call in each sort; index==0) */
355
356 if(index==0 || nodex->id!=previd)
357 {
358 previd=nodex->id;
359
360 if(nodex->flags&NODE_DELETED)
361 return(0);
362 else
363 {
364 sortnodesx->idata[index]=nodex->id;
365
366 return(1);
367 }
368 }
369 else
370 return(0);
371 }
372
373
374 /*++++++++++++++++++++++++++++++++++++++
375 Remove any nodes that are not part of a highway.
376
377 NodesX *nodesx The set of nodes to modify.
378
379 WaysX *waysx The set of ways to use.
380
381 int keep If set to 1 then keep the old data file otherwise delete it.
382 ++++++++++++++++++++++++++++++++++++++*/
383
384 void RemoveNonHighwayNodes(NodesX *nodesx,WaysX *waysx,int keep)
385 {
386 BitMask *usednode;
387 NodeX nodex;
388 index_t i,total=0,highway=0,nothighway=0;
389 int fd;
390
391 /* Print the start message */
392
393 printf_first("Checking Ways for unused Nodes: Ways=0 Highway Nodes=0");
394
395 /* Allocate the node usage bitmask */
396
397 usednode=AllocBitMask(nodesx->number);
398 log_malloc(usednode,LengthBitMask(nodesx->number)*sizeof(BitMask));
399
400 logassert(usednode,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
401
402 /* Re-open the file read-only */
403
404 waysx->fd=ReOpenFileBuffered(waysx->filename_tmp);
405
406 /* Loop through the ways and mark the used nodes */
407
408 for(i=0;i<waysx->number;i++)
409 {
410 WayX wayx;
411 FILESORT_VARINT waysize;
412 node_t node;
413
414 ReadFileBuffered(waysx->fd,&waysize,FILESORT_VARSIZE);
415
416 ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX));
417
418 while(!ReadFileBuffered(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID)
419 {
420 index_t index=IndexNodeX(nodesx,node);
421
422 waysize-=sizeof(node_t);
423
424 if(index!=NO_NODE)
425 {
426 if(!IsBitSet(usednode,index))
427 highway++;
428
429 SetBit(usednode,index);
430 }
431 }
432
433 waysize-=sizeof(node_t)+sizeof(WayX);
434
435 SkipFileBuffered(waysx->fd,waysize);
436
437 if(!((i+1)%1000))
438 printf_middle("Checking Ways for unused Nodes: Ways=%"Pindex_t" Highway Nodes=%"Pindex_t,i+1,highway);
439 }
440
441 /* Free the now-unneeded index */
442
443 log_free(nodesx->idata);
444 free(nodesx->idata);
445 nodesx->idata=NULL;
446
447 /* Close the file */
448
449 waysx->fd=CloseFileBuffered(waysx->fd);
450
451 /* Print the final message */
452
453 printf_last("Checked Ways for unused Nodes: Ways=%"Pindex_t" Highway Nodes=%"Pindex_t,waysx->number,highway);
454
455
456 /* Print the start message */
457
458 printf_first("Removing unused Nodes: Nodes=0");
459
460 /* Allocate the array of indexes */
461
462 nodesx->idata=(node_t*)malloc(highway*sizeof(node_t));
463 log_malloc(nodesx->idata,highway*sizeof(node_t));
464
465 logassert(nodesx->idata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
466
467 highway=0;
468
469 /* Re-open the file read-only and a new file writeable */
470
471 if(keep)
472 {
473 RenameFile(nodesx->filename_tmp,nodesx->filename);
474
475 nodesx->fd=ReOpenFileBuffered(nodesx->filename);
476
477 fd=OpenFileBufferedNew(nodesx->filename_tmp);
478 }
479 else
480 fd=ReplaceFileBuffered(nodesx->filename_tmp,&nodesx->fd);
481
482 /* Modify the on-disk image */
483
484 while(!ReadFileBuffered(nodesx->fd,&nodex,sizeof(NodeX)))
485 {
486 if(!IsBitSet(usednode,total))
487 nothighway++;
488 else
489 {
490 nodesx->idata[highway]=nodex.id;
491
492 WriteFileBuffered(fd,&nodex,sizeof(NodeX));
493
494 highway++;
495 }
496
497 total++;
498
499 if(!(total%10000))
500 printf_middle("Removing unused Nodes: Nodes=%"Pindex_t" Highway=%"Pindex_t" not-Highway=%"Pindex_t,total,highway,nothighway);
501 }
502
503 nodesx->number=highway;
504
505 /* Close the files */
506
507 nodesx->fd=CloseFileBuffered(nodesx->fd);
508 CloseFileBuffered(fd);
509
510 /* Free the now-unneeded index */
511
512 log_free(usednode);
513 free(usednode);
514
515 /* Print the final message */
516
517 printf_last("Removed unused Nodes: Nodes=%"Pindex_t" Highway=%"Pindex_t" not-Highway=%"Pindex_t,total,highway,nothighway);
518 }
519
520
521 /*++++++++++++++++++++++++++++++++++++++
522 Remove any nodes that have been pruned.
523
524 NodesX *nodesx The set of nodes to prune.
525
526 SegmentsX *segmentsx The set of segments to use.
527 ++++++++++++++++++++++++++++++++++++++*/
528
529 void RemovePrunedNodes(NodesX *nodesx,SegmentsX *segmentsx)
530 {
531 NodeX nodex;
532 index_t total=0,pruned=0,notpruned=0;
533 int fd;
534
535 if(nodesx->number==0)
536 return;
537
538 /* Print the start message */
539
540 printf_first("Deleting Pruned Nodes: Nodes=0 Pruned=0");
541
542 /* Allocate the array of indexes */
543
544 nodesx->pdata=(index_t*)malloc(nodesx->number*sizeof(index_t));
545 log_malloc(nodesx->pdata,nodesx->number*sizeof(index_t));
546
547 logassert(nodesx->pdata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
548
549 /* Re-open the file read-only and a new file writeable */
550
551 fd=ReplaceFileBuffered(nodesx->filename_tmp,&nodesx->fd);
552
553 /* Modify the on-disk image */
554
555 while(!ReadFileBuffered(nodesx->fd,&nodex,sizeof(NodeX)))
556 {
557 if(segmentsx->firstnode[total]==NO_SEGMENT)
558 {
559 pruned++;
560
561 nodesx->pdata[total]=NO_NODE;
562 }
563 else
564 {
565 nodesx->pdata[total]=notpruned;
566
567 WriteFileBuffered(fd,&nodex,sizeof(NodeX));
568
569 notpruned++;
570 }
571
572 total++;
573
574 if(!(total%10000))
575 printf_middle("Deleting Pruned Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
576 }
577
578 nodesx->number=notpruned;
579
580 /* Close the files */
581
582 nodesx->fd=CloseFileBuffered(nodesx->fd);
583 CloseFileBuffered(fd);
584
585 /* Free the no-longer required memory */
586
587 if(segmentsx->firstnode)
588 {
589 log_free(segmentsx->firstnode);
590 free(segmentsx->firstnode);
591 segmentsx->firstnode=NULL;
592 }
593
594 /* Print the final message */
595
596 printf_last("Deleted Pruned Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
597 }
598
599
600 /*++++++++++++++++++++++++++++++++++++++
601 Sort the node list geographically.
602
603 NodesX *nodesx The set of nodes to modify.
604 ++++++++++++++++++++++++++++++++++++++*/
605
606 void SortNodeListGeographically(NodesX *nodesx)
607 {
608 int fd;
609 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
610
611 if(nodesx->number==0)
612 return;
613
614 /* Print the start message */
615
616 printf_first("Sorting Nodes Geographically");
617
618 /* Work out the range of data */
619
620 lat_min=radians_to_latlong( 2);
621 lat_max=radians_to_latlong(-2);
622 lon_min=radians_to_latlong( 4);
623 lon_max=radians_to_latlong(-4);
624
625 /* Allocate the memory for the geographical index array */
626
627 nodesx->gdata=(index_t*)malloc(nodesx->number*sizeof(index_t));
628 log_malloc(nodesx->gdata,nodesx->number*sizeof(index_t));
629
630 logassert(nodesx->gdata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
631
632 /* Re-open the file read-only and a new file writeable */
633
634 fd=ReplaceFileBuffered(nodesx->filename_tmp,&nodesx->fd);
635
636 /* Sort nodes geographically and index them */
637
638 sortnodesx=nodesx;
639
640 filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(void*,index_t))update_id,
641 (int (*)(const void*,const void*))sort_by_lat_long,
642 (int (*)(void*,index_t))index_by_lat_long);
643
644 /* Close the files */
645
646 nodesx->fd=CloseFileBuffered(nodesx->fd);
647 CloseFileBuffered(fd);
648
649 /* Work out the number of bins */
650
651 if(nodesx->super)
652 {
653 lat_min_bin=latlong_to_bin(lat_min);
654 lon_min_bin=latlong_to_bin(lon_min);
655 lat_max_bin=latlong_to_bin(lat_max);
656 lon_max_bin=latlong_to_bin(lon_max);
657
658 nodesx->latzero=lat_min_bin;
659 nodesx->lonzero=lon_min_bin;
660
661 nodesx->latbins=(lat_max_bin-lat_min_bin)+1;
662 nodesx->lonbins=(lon_max_bin-lon_min_bin)+1;
663 }
664
665 /* Free the memory */
666
667 if(nodesx->super)
668 {
669 log_free(nodesx->super);
670 free(nodesx->super);
671 nodesx->super=NULL;
672 }
673
674 /* Print the final message */
675
676 printf_last("Sorted Nodes Geographically: Nodes=%"Pindex_t,nodesx->number);
677 }
678
679
680 /*++++++++++++++++++++++++++++++++++++++
681 Update the node ids.
682
683 int update_id Return 1 if the value is to be kept, otherwise 0.
684
685 NodeX *nodex The extended node.
686
687 index_t index The number of unsorted nodes that have been read from the input file.
688 ++++++++++++++++++++++++++++++++++++++*/
689
690 static int update_id(NodeX *nodex,index_t index)
691 {
692 nodex->id=index;
693
694 if(sortnodesx->super && IsBitSet(sortnodesx->super,index))
695 nodex->flags|=NODE_SUPER;
696
697 return(1);
698 }
699
700
701 /*++++++++++++++++++++++++++++++++++++++
702 Sort the nodes into latitude and longitude order (first by longitude bin
703 number, then by latitude bin number and then by exact longitude and then by
704 exact latitude).
705
706 int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
707
708 NodeX *a The first extended node.
709
710 NodeX *b The second extended node.
711 ++++++++++++++++++++++++++++++++++++++*/
712
713 static int sort_by_lat_long(NodeX *a,NodeX *b)
714 {
715 ll_bin_t a_lon=latlong_to_bin(a->longitude);
716 ll_bin_t b_lon=latlong_to_bin(b->longitude);
717
718 if(a_lon<b_lon)
719 return(-1);
720 else if(a_lon>b_lon)
721 return(1);
722 else
723 {
724 ll_bin_t a_lat=latlong_to_bin(a->latitude);
725 ll_bin_t b_lat=latlong_to_bin(b->latitude);
726
727 if(a_lat<b_lat)
728 return(-1);
729 else if(a_lat>b_lat)
730 return(1);
731 else
732 {
733 if(a->longitude<b->longitude)
734 return(-1);
735 else if(a->longitude>b->longitude)
736 return(1);
737 else
738 {
739 if(a->latitude<b->latitude)
740 return(-1);
741 else if(a->latitude>b->latitude)
742 return(1);
743 }
744
745 return(FILESORT_PRESERVE_ORDER(a,b));
746 }
747 }
748 }
749
750
751 /*++++++++++++++++++++++++++++++++++++++
752 Create the index between the sorted and unsorted nodes.
753
754 int index_by_lat_long Return 1 if the value is to be kept, otherwise 0.
755
756 NodeX *nodex The extended node.
757
758 index_t index The number of sorted nodes that have already been written to the output file.
759 ++++++++++++++++++++++++++++++++++++++*/
760
761 static int index_by_lat_long(NodeX *nodex,index_t index)
762 {
763 sortnodesx->gdata[nodex->id]=index;
764
765 if(sortnodesx->super)
766 {
767 if(nodex->latitude<lat_min)
768 lat_min=nodex->latitude;
769 if(nodex->latitude>lat_max)
770 lat_max=nodex->latitude;
771 if(nodex->longitude<lon_min)
772 lon_min=nodex->longitude;
773 if(nodex->longitude>lon_max)
774 lon_max=nodex->longitude;
775 }
776
777 return(1);
778 }
779
780
781 /*++++++++++++++++++++++++++++++++++++++
782 Save the final node list database to a file.
783
784 NodesX *nodesx The set of nodes to save.
785
786 const char *filename The name of the file to save.
787
788 SegmentsX *segmentsx The set of segments to use.
789 ++++++++++++++++++++++++++++++++++++++*/
790
791 void SaveNodeList(NodesX *nodesx,const char *filename,SegmentsX *segmentsx)
792 {
793 index_t i;
794 int fd;
795 NodesFile nodesfile={0};
796 index_t super_number=0;
797 ll_bin2_t latlonbin=0,maxlatlonbins;
798 index_t *offsets;
799
800 /* Print the start message */
801
802 printf_first("Writing Nodes: Nodes=0");
803
804 /* Allocate the memory for the geographical offsets array */
805
806 offsets=(index_t*)malloc((nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
807
808 logassert(offsets,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
809
810 latlonbin=0;
811
812 /* Re-open the file */
813
814 nodesx->fd=ReOpenFileBuffered(nodesx->filename_tmp);
815
816 /* Write out the nodes data */
817
818 fd=OpenFileBufferedNew(filename);
819
820 SeekFileBuffered(fd,sizeof(NodesFile)+(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
821
822 for(i=0;i<nodesx->number;i++)
823 {
824 NodeX nodex;
825 Node node={0};
826 ll_bin_t latbin,lonbin;
827 ll_bin2_t llbin;
828
829 ReadFileBuffered(nodesx->fd,&nodex,sizeof(NodeX));
830
831 /* Create the Node */
832
833 node.latoffset=latlong_to_off(nodex.latitude);
834 node.lonoffset=latlong_to_off(nodex.longitude);
835 node.firstseg=segmentsx->firstnode[i];
836 node.allow=nodex.allow;
837 node.flags=nodex.flags;
838
839 if(node.flags&NODE_SUPER)
840 super_number++;
841
842 /* Work out the offsets */
843
844 latbin=latlong_to_bin(nodex.latitude )-nodesx->latzero;
845 lonbin=latlong_to_bin(nodex.longitude)-nodesx->lonzero;
846 llbin=lonbin*nodesx->latbins+latbin;
847
848 for(;latlonbin<=llbin;latlonbin++)
849 offsets[latlonbin]=i;
850
851 /* Write the data */
852
853 WriteFileBuffered(fd,&node,sizeof(Node));
854
855 if(!((i+1)%10000))
856 printf_middle("Writing Nodes: Nodes=%"Pindex_t,i+1);
857 }
858
859 /* Close the file */
860
861 nodesx->fd=CloseFileBuffered(nodesx->fd);
862
863 /* Finish off the offset indexing and write them out */
864
865 maxlatlonbins=nodesx->latbins*nodesx->lonbins;
866
867 for(;latlonbin<=maxlatlonbins;latlonbin++)
868 offsets[latlonbin]=nodesx->number;
869
870 SeekFileBuffered(fd,sizeof(NodesFile));
871 WriteFileBuffered(fd,offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
872
873 free(offsets);
874
875 /* Write out the header structure */
876
877 nodesfile.number=nodesx->number;
878 nodesfile.snumber=super_number;
879
880 nodesfile.latbins=nodesx->latbins;
881 nodesfile.lonbins=nodesx->lonbins;
882
883 nodesfile.latzero=nodesx->latzero;
884 nodesfile.lonzero=nodesx->lonzero;
885
886 SeekFileBuffered(fd,0);
887 WriteFileBuffered(fd,&nodesfile,sizeof(NodesFile));
888
889 CloseFileBuffered(fd);
890
891 /* Free the memory in the segments */
892
893 log_free(segmentsx->firstnode);
894 free(segmentsx->firstnode);
895 segmentsx->firstnode=NULL;
896
897 /* Print the final message */
898
899 printf_last("Wrote Nodes: Nodes=%"Pindex_t,nodesx->number);
900 }

Properties

Name Value
cvs:description Extended nodes functions.