Routino SVN Repository Browser

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

ViewVC logotype

Contents of /branches/destination-access/src/nodesx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2078 - (show annotations) (download) (as text)
Thu Nov 19 11:39:07 2020 UTC (4 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 21765 byte(s)
Merged source code changes from trunk [zero unused space in files, fix
library database loader, update binary search].

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

Properties

Name Value
cvs:description Extended nodes functions.