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 1606 - (show annotations) (download) (as text)
Sat Oct 18 12:40:57 2014 UTC (10 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 21997 byte(s)
Shrink the size of the nodesx->idata array when removing non-highway nodes.

1 /***************************************
2 Extented Node data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2014 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. +*/
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)+32);
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 off_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 nodesx->fd=ReOpenFileBuffered(nodesx->filename_tmp);
287
288 DeleteFile(nodesx->filename_tmp);
289
290 fd=OpenFileBufferedNew(nodesx->filename_tmp);
291
292 /* Allocate the array of indexes */
293
294 nodesx->idata=(node_t*)malloc(nodesx->number*sizeof(node_t));
295 log_malloc(nodesx->idata,nodesx->number*sizeof(node_t));
296
297 logassert(nodesx->idata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
298
299 /* Sort the nodes by ID and index them */
300
301 xnumber=nodesx->number;
302
303 sortnodesx=nodesx;
304
305 nodesx->number=filesort_fixed(nodesx->fd,fd,sizeof(NodeX),NULL,
306 (int (*)(const void*,const void*))sort_by_id,
307 (int (*)(void*,index_t))deduplicate_and_index_by_id);
308
309 nodesx->knumber=nodesx->number;
310
311 /* Close the files */
312
313 nodesx->fd=CloseFileBuffered(nodesx->fd);
314 CloseFileBuffered(fd);
315
316 /* Print the final message */
317
318 printf_last("Sorted Nodes: Nodes=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-nodesx->number);
319 }
320
321
322 /*++++++++++++++++++++++++++++++++++++++
323 Sort the nodes into id order.
324
325 int sort_by_id Returns the comparison of the id fields.
326
327 NodeX *a The first extended node.
328
329 NodeX *b The second extended node.
330 ++++++++++++++++++++++++++++++++++++++*/
331
332 static int sort_by_id(NodeX *a,NodeX *b)
333 {
334 node_t a_id=a->id;
335 node_t b_id=b->id;
336
337 if(a_id<b_id)
338 return(-1);
339 else if(a_id>b_id)
340 return(1);
341 else
342 return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */
343 }
344
345
346 /*++++++++++++++++++++++++++++++++++++++
347 Create the index of identifiers and discard duplicate nodes.
348
349 int deduplicate_and_index_by_id Return 1 if the value is to be kept, otherwise 0.
350
351 NodeX *nodex The extended node.
352
353 index_t index The number of sorted nodes that have already been written to the output file.
354 ++++++++++++++++++++++++++++++++++++++*/
355
356 static int deduplicate_and_index_by_id(NodeX *nodex,index_t index)
357 {
358 static node_t previd=NO_NODE_ID;
359
360 if(nodex->id!=previd)
361 {
362 previd=nodex->id;
363
364 if(nodex->flags&NODE_DELETED)
365 return(0);
366 else
367 {
368 sortnodesx->idata[index]=nodex->id;
369
370 return(1);
371 }
372 }
373 else
374 return(0);
375 }
376
377
378 /*++++++++++++++++++++++++++++++++++++++
379 Remove any nodes that are not part of a highway.
380
381 NodesX *nodesx The set of nodes to modify.
382
383 WaysX *waysx The set of ways to use.
384
385 int keep If set to 1 then keep the old data file otherwise delete it.
386 ++++++++++++++++++++++++++++++++++++++*/
387
388 void RemoveNonHighwayNodes(NodesX *nodesx,WaysX *waysx,int keep)
389 {
390 BitMask *usednode;
391 NodeX nodex;
392 index_t i,total=0,highway=0,nothighway=0;
393 int fd;
394
395 /* Print the start message */
396
397 printf_first("Checking Ways for unused Nodes: Ways=0 Highway Nodes=0");
398
399 /* Allocate the node usage bitmask */
400
401 usednode=AllocBitMask(nodesx->number);
402 log_malloc(usednode,LengthBitMask(nodesx->number)*sizeof(BitMask));
403
404 logassert(usednode,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
405
406 /* Re-open the file read-only */
407
408 waysx->fd=ReOpenFileBuffered(waysx->filename_tmp);
409
410 /* Loop through the ways and mark the used nodes */
411
412 for(i=0;i<waysx->number;i++)
413 {
414 WayX wayx;
415 FILESORT_VARINT waysize;
416 node_t node;
417
418 ReadFileBuffered(waysx->fd,&waysize,FILESORT_VARSIZE);
419
420 ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX));
421
422 while(!ReadFileBuffered(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID)
423 {
424 index_t index=IndexNodeX(nodesx,node);
425
426 waysize-=sizeof(node_t);
427
428 if(index!=NO_NODE)
429 {
430 if(!IsBitSet(usednode,index))
431 highway++;
432
433 SetBit(usednode,index);
434 }
435 }
436
437 waysize-=sizeof(node_t)+sizeof(WayX);
438
439 SkipFileBuffered(waysx->fd,waysize);
440
441 if(!((i+1)%1000))
442 printf_middle("Checking Ways for unused Nodes: Ways=%"Pindex_t" Highway Nodes=%"Pindex_t,i+1,highway);
443 }
444
445 /* Free the now-unneeded index */
446
447 log_free(nodesx->idata);
448 free(nodesx->idata);
449 nodesx->idata=NULL;
450
451 /* Close the file */
452
453 waysx->fd=CloseFileBuffered(waysx->fd);
454
455 /* Print the final message */
456
457 printf_last("Checked Ways for unused Nodes: Ways=%"Pindex_t" Highway Nodes=%"Pindex_t,waysx->number,highway);
458
459
460 /* Print the start message */
461
462 printf_first("Removing unused Nodes: Nodes=0");
463
464 /* Allocate the array of indexes */
465
466 nodesx->idata=(node_t*)malloc(highway*sizeof(node_t));
467 log_malloc(nodesx->idata,highway*sizeof(node_t));
468
469 logassert(nodesx->idata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
470
471 highway=0;
472
473 /* Re-open the file read-only and a new file writeable */
474
475 nodesx->fd=ReOpenFileBuffered(nodesx->filename_tmp);
476
477 if(keep)
478 RenameFile(nodesx->filename_tmp,nodesx->filename);
479 else
480 DeleteFile(nodesx->filename_tmp);
481
482 fd=OpenFileBufferedNew(nodesx->filename_tmp);
483
484 /* Modify the on-disk image */
485
486 while(!ReadFileBuffered(nodesx->fd,&nodex,sizeof(NodeX)))
487 {
488 if(!IsBitSet(usednode,total))
489 nothighway++;
490 else
491 {
492 nodesx->idata[highway]=nodex.id;
493
494 WriteFileBuffered(fd,&nodex,sizeof(NodeX));
495
496 highway++;
497 }
498
499 total++;
500
501 if(!(total%10000))
502 printf_middle("Removing unused Nodes: Nodes=%"Pindex_t" Highway=%"Pindex_t" not-Highway=%"Pindex_t,total,highway,nothighway);
503 }
504
505 nodesx->number=highway;
506
507 /* Close the files */
508
509 nodesx->fd=CloseFileBuffered(nodesx->fd);
510 CloseFileBuffered(fd);
511
512 /* Free the now-unneeded index */
513
514 log_free(usednode);
515 free(usednode);
516
517 /* Print the final message */
518
519 printf_last("Removed unused Nodes: Nodes=%"Pindex_t" Highway=%"Pindex_t" not-Highway=%"Pindex_t,total,highway,nothighway);
520 }
521
522
523 /*++++++++++++++++++++++++++++++++++++++
524 Remove any nodes that have been pruned.
525
526 NodesX *nodesx The set of nodes to prune.
527
528 SegmentsX *segmentsx The set of segments to use.
529 ++++++++++++++++++++++++++++++++++++++*/
530
531 void RemovePrunedNodes(NodesX *nodesx,SegmentsX *segmentsx)
532 {
533 NodeX nodex;
534 index_t total=0,pruned=0,notpruned=0;
535 int fd;
536
537 if(nodesx->number==0)
538 return;
539
540 /* Print the start message */
541
542 printf_first("Deleting Pruned Nodes: Nodes=0 Pruned=0");
543
544 /* Allocate the array of indexes */
545
546 nodesx->pdata=(index_t*)malloc(nodesx->number*sizeof(index_t));
547 log_malloc(nodesx->pdata,nodesx->number*sizeof(index_t));
548
549 logassert(nodesx->pdata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
550
551 /* Re-open the file read-only and a new file writeable */
552
553 nodesx->fd=ReOpenFileBuffered(nodesx->filename_tmp);
554
555 DeleteFile(nodesx->filename_tmp);
556
557 fd=OpenFileBufferedNew(nodesx->filename_tmp);
558
559 /* Modify the on-disk image */
560
561 while(!ReadFileBuffered(nodesx->fd,&nodex,sizeof(NodeX)))
562 {
563 if(segmentsx->firstnode[total]==NO_SEGMENT)
564 {
565 pruned++;
566
567 nodesx->pdata[total]=NO_NODE;
568 }
569 else
570 {
571 nodesx->pdata[total]=notpruned;
572
573 WriteFileBuffered(fd,&nodex,sizeof(NodeX));
574
575 notpruned++;
576 }
577
578 total++;
579
580 if(!(total%10000))
581 printf_middle("Deleting Pruned Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
582 }
583
584 nodesx->number=notpruned;
585
586 /* Close the files */
587
588 nodesx->fd=CloseFileBuffered(nodesx->fd);
589 CloseFileBuffered(fd);
590
591 /* Free the no-longer required memory */
592
593 if(segmentsx->firstnode)
594 {
595 log_free(segmentsx->firstnode);
596 free(segmentsx->firstnode);
597 segmentsx->firstnode=NULL;
598 }
599
600 /* Print the final message */
601
602 printf_last("Deleted Pruned Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
603 }
604
605
606 /*++++++++++++++++++++++++++++++++++++++
607 Sort the node list geographically.
608
609 NodesX *nodesx The set of nodes to modify.
610 ++++++++++++++++++++++++++++++++++++++*/
611
612 void SortNodeListGeographically(NodesX *nodesx)
613 {
614 int fd;
615 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
616
617 if(nodesx->number==0)
618 return;
619
620 /* Print the start message */
621
622 printf_first("Sorting Nodes Geographically");
623
624 /* Work out the range of data */
625
626 lat_min=radians_to_latlong( 2);
627 lat_max=radians_to_latlong(-2);
628 lon_min=radians_to_latlong( 4);
629 lon_max=radians_to_latlong(-4);
630
631 /* Allocate the memory for the geographical index array */
632
633 nodesx->gdata=(index_t*)malloc(nodesx->number*sizeof(index_t));
634 log_malloc(nodesx->gdata,nodesx->number*sizeof(index_t));
635
636 logassert(nodesx->gdata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
637
638 /* Re-open the file read-only and a new file writeable */
639
640 nodesx->fd=ReOpenFileBuffered(nodesx->filename_tmp);
641
642 DeleteFile(nodesx->filename_tmp);
643
644 fd=OpenFileBufferedNew(nodesx->filename_tmp);
645
646 /* Sort nodes geographically and index them */
647
648 sortnodesx=nodesx;
649
650 filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(void*,index_t))update_id,
651 (int (*)(const void*,const void*))sort_by_lat_long,
652 (int (*)(void*,index_t))index_by_lat_long);
653
654 /* Close the files */
655
656 nodesx->fd=CloseFileBuffered(nodesx->fd);
657 CloseFileBuffered(fd);
658
659 /* Free the memory */
660
661 log_free(nodesx->super);
662 free(nodesx->super);
663 nodesx->super=NULL;
664
665 /* Work out the number of bins */
666
667 lat_min_bin=latlong_to_bin(lat_min);
668 lon_min_bin=latlong_to_bin(lon_min);
669 lat_max_bin=latlong_to_bin(lat_max);
670 lon_max_bin=latlong_to_bin(lon_max);
671
672 nodesx->latzero=lat_min_bin;
673 nodesx->lonzero=lon_min_bin;
674
675 nodesx->latbins=(lat_max_bin-lat_min_bin)+1;
676 nodesx->lonbins=(lon_max_bin-lon_min_bin)+1;
677
678 /* Print the final message */
679
680 printf_last("Sorted Nodes Geographically: Nodes=%"Pindex_t,nodesx->number);
681 }
682
683
684 /*++++++++++++++++++++++++++++++++++++++
685 Update the node ids.
686
687 int update_id Return 1 if the value is to be kept, otherwise 0.
688
689 NodeX *nodex The extended node.
690
691 index_t index The number of unsorted nodes that have been read from the input file.
692 ++++++++++++++++++++++++++++++++++++++*/
693
694 static int update_id(NodeX *nodex,index_t index)
695 {
696 nodex->id=index;
697
698 if(IsBitSet(sortnodesx->super,index))
699 nodex->flags|=NODE_SUPER;
700
701 return(1);
702 }
703
704
705 /*++++++++++++++++++++++++++++++++++++++
706 Sort the nodes into latitude and longitude order (first by longitude bin
707 number, then by latitude bin number and then by exact longitude and then by
708 exact latitude).
709
710 int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
711
712 NodeX *a The first extended node.
713
714 NodeX *b The second extended node.
715 ++++++++++++++++++++++++++++++++++++++*/
716
717 static int sort_by_lat_long(NodeX *a,NodeX *b)
718 {
719 ll_bin_t a_lon=latlong_to_bin(a->longitude);
720 ll_bin_t b_lon=latlong_to_bin(b->longitude);
721
722 if(a_lon<b_lon)
723 return(-1);
724 else if(a_lon>b_lon)
725 return(1);
726 else
727 {
728 ll_bin_t a_lat=latlong_to_bin(a->latitude);
729 ll_bin_t b_lat=latlong_to_bin(b->latitude);
730
731 if(a_lat<b_lat)
732 return(-1);
733 else if(a_lat>b_lat)
734 return(1);
735 else
736 {
737 if(a->longitude<b->longitude)
738 return(-1);
739 else if(a->longitude>b->longitude)
740 return(1);
741 else
742 {
743 if(a->latitude<b->latitude)
744 return(-1);
745 else if(a->latitude>b->latitude)
746 return(1);
747 }
748
749 return(FILESORT_PRESERVE_ORDER(a,b));
750 }
751 }
752 }
753
754
755 /*++++++++++++++++++++++++++++++++++++++
756 Create the index between the sorted and unsorted nodes.
757
758 int index_by_lat_long Return 1 if the value is to be kept, otherwise 0.
759
760 NodeX *nodex The extended node.
761
762 index_t index The number of sorted nodes that have already been written to the output file.
763 ++++++++++++++++++++++++++++++++++++++*/
764
765 static int index_by_lat_long(NodeX *nodex,index_t index)
766 {
767 sortnodesx->gdata[nodex->id]=index;
768
769 if(nodex->latitude<lat_min)
770 lat_min=nodex->latitude;
771 if(nodex->latitude>lat_max)
772 lat_max=nodex->latitude;
773 if(nodex->longitude<lon_min)
774 lon_min=nodex->longitude;
775 if(nodex->longitude>lon_max)
776 lon_max=nodex->longitude;
777
778 return(1);
779 }
780
781
782 /*++++++++++++++++++++++++++++++++++++++
783 Save the final node list database to a file.
784
785 NodesX *nodesx The set of nodes to save.
786
787 const char *filename The name of the file to save.
788
789 SegmentsX *segmentsx The set of segments to use.
790 ++++++++++++++++++++++++++++++++++++++*/
791
792 void SaveNodeList(NodesX *nodesx,const char *filename,SegmentsX *segmentsx)
793 {
794 index_t i;
795 int fd;
796 NodesFile nodesfile={0};
797 index_t super_number=0;
798 ll_bin2_t latlonbin=0,maxlatlonbins;
799 index_t *offsets;
800
801 /* Print the start message */
802
803 printf_first("Writing Nodes: Nodes=0");
804
805 /* Allocate the memory for the geographical offsets array */
806
807 offsets=(index_t*)malloc((nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
808
809 logassert(offsets,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
810
811 latlonbin=0;
812
813 /* Re-open the file */
814
815 nodesx->fd=ReOpenFileBuffered(nodesx->filename_tmp);
816
817 /* Write out the nodes data */
818
819 fd=OpenFileBufferedNew(filename);
820
821 SeekFileBuffered(fd,sizeof(NodesFile)+(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
822
823 for(i=0;i<nodesx->number;i++)
824 {
825 NodeX nodex;
826 Node node={0};
827 ll_bin_t latbin,lonbin;
828 ll_bin2_t llbin;
829
830 ReadFileBuffered(nodesx->fd,&nodex,sizeof(NodeX));
831
832 /* Create the Node */
833
834 node.latoffset=latlong_to_off(nodex.latitude);
835 node.lonoffset=latlong_to_off(nodex.longitude);
836 node.firstseg=segmentsx->firstnode[i];
837 node.allow=nodex.allow;
838 node.flags=nodex.flags;
839
840 if(node.flags&NODE_SUPER)
841 super_number++;
842
843 /* Work out the offsets */
844
845 latbin=latlong_to_bin(nodex.latitude )-nodesx->latzero;
846 lonbin=latlong_to_bin(nodex.longitude)-nodesx->lonzero;
847 llbin=lonbin*nodesx->latbins+latbin;
848
849 for(;latlonbin<=llbin;latlonbin++)
850 offsets[latlonbin]=i;
851
852 /* Write the data */
853
854 WriteFileBuffered(fd,&node,sizeof(Node));
855
856 if(!((i+1)%10000))
857 printf_middle("Writing Nodes: Nodes=%"Pindex_t,i+1);
858 }
859
860 /* Close the file */
861
862 nodesx->fd=CloseFileBuffered(nodesx->fd);
863
864 /* Finish off the offset indexing and write them out */
865
866 maxlatlonbins=nodesx->latbins*nodesx->lonbins;
867
868 for(;latlonbin<=maxlatlonbins;latlonbin++)
869 offsets[latlonbin]=nodesx->number;
870
871 SeekFileBuffered(fd,sizeof(NodesFile));
872 WriteFileBuffered(fd,offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
873
874 free(offsets);
875
876 /* Write out the header structure */
877
878 nodesfile.number=nodesx->number;
879 nodesfile.snumber=super_number;
880
881 nodesfile.latbins=nodesx->latbins;
882 nodesfile.lonbins=nodesx->lonbins;
883
884 nodesfile.latzero=nodesx->latzero;
885 nodesfile.lonzero=nodesx->lonzero;
886
887 SeekFileBuffered(fd,0);
888 WriteFileBuffered(fd,&nodesfile,sizeof(NodesFile));
889
890 CloseFileBuffered(fd);
891
892 /* Free the memory in the segments */
893
894 log_free(segmentsx->firstnode);
895 free(segmentsx->firstnode);
896 segmentsx->firstnode=NULL;
897
898 /* Print the final message */
899
900 printf_last("Wrote Nodes: Nodes=%"Pindex_t,nodesx->number);
901 }

Properties

Name Value
cvs:description Extended nodes functions.