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 538 - (show annotations) (download) (as text)
Sat Dec 4 14:54:53 2010 UTC (14 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 19436 byte(s)
Improved version of previous change.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/nodesx.c,v 1.80 2010-12-04 14:54:53 amb Exp $
3
4 Extented Node data type functions.
5
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008-2010 Andrew M. Bishop
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
19
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 ***************************************/
23
24
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/stat.h>
30
31 #include "types.h"
32 #include "nodes.h"
33 #include "segments.h"
34
35 #include "nodesx.h"
36 #include "segmentsx.h"
37 #include "waysx.h"
38
39 #include "types.h"
40
41 #include "files.h"
42 #include "logging.h"
43 #include "sorting.h"
44
45
46 /* Variables */
47
48 /*+ The command line '--tmpdir' option or its default value. +*/
49 extern char *option_tmpdirname;
50
51 /*+ A temporary file-local variable for use by the sort functions. +*/
52 static NodesX *sortnodesx;
53
54 /* Functions */
55
56 static int sort_by_id(NodeX *a,NodeX *b);
57 static int index_by_id(NodeX *nodex,index_t index);
58
59 static int sort_by_lat_long(NodeX *a,NodeX *b);
60 static int index_by_lat_long(NodeX *nodex,index_t index);
61
62
63 /*++++++++++++++++++++++++++++++++++++++
64 Allocate a new node list (create a new file or open an existing one).
65
66 NodesX *NewNodeList Returns the node list.
67
68 int append Set to 1 if the file is to be opened for appending (now or later).
69 ++++++++++++++++++++++++++++++++++++++*/
70
71 NodesX *NewNodeList(int append)
72 {
73 NodesX *nodesx;
74
75 nodesx=(NodesX*)calloc(1,sizeof(NodesX));
76
77 assert(nodesx); /* Check calloc() worked */
78
79 nodesx->filename=(char*)malloc(strlen(option_tmpdirname)+32);
80
81 if(append)
82 sprintf(nodesx->filename,"%s/nodesx.input.tmp",option_tmpdirname);
83 else
84 sprintf(nodesx->filename,"%s/nodesx.%p.tmp",option_tmpdirname,nodesx);
85
86 #if SLIM
87 nodesx->nfilename=(char*)malloc(strlen(option_tmpdirname)+32);
88
89 sprintf(nodesx->nfilename,"%s/nodes.%p.tmp",option_tmpdirname,nodesx);
90 #endif
91
92 if(append)
93 {
94 off_t size;
95
96 nodesx->fd=OpenFileAppend(nodesx->filename);
97
98 size=SizeFile(nodesx->filename);
99
100 nodesx->xnumber=size/sizeof(NodeX);
101 }
102 else
103 nodesx->fd=OpenFileNew(nodesx->filename);
104
105 return(nodesx);
106 }
107
108
109 /*++++++++++++++++++++++++++++++++++++++
110 Free a node list.
111
112 NodesX *nodesx The list to be freed.
113
114 int keep Set to 1 if the file is to be kept.
115 ++++++++++++++++++++++++++++++++++++++*/
116
117 void FreeNodeList(NodesX *nodesx,int keep)
118 {
119 if(!keep)
120 DeleteFile(nodesx->filename);
121
122 free(nodesx->filename);
123
124 if(nodesx->idata)
125 free(nodesx->idata);
126
127 #if !SLIM
128 if(nodesx->ndata)
129 free(nodesx->ndata);
130 #endif
131
132 #if SLIM
133 DeleteFile(nodesx->nfilename);
134
135 free(nodesx->nfilename);
136 #endif
137
138 if(nodesx->super)
139 free(nodesx->super);
140
141 if(nodesx->offsets)
142 free(nodesx->offsets);
143
144 free(nodesx);
145 }
146
147
148 /*++++++++++++++++++++++++++++++++++++++
149 Append a single node to an unsorted node list.
150
151 NodesX* nodesx The set of nodes to process.
152
153 node_t id The node identification.
154
155 double latitude The latitude of the node.
156
157 double longitude The longitude of the node.
158
159 transports_t allow The allowed traffic types through the node.
160
161 uint16_t flags The flags to set for this node.
162 ++++++++++++++++++++++++++++++++++++++*/
163
164 void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude,transports_t allow,uint16_t flags)
165 {
166 NodeX nodex;
167
168 nodex.id=id;
169 nodex.latitude =radians_to_latlong(latitude);
170 nodex.longitude=radians_to_latlong(longitude);
171 nodex.allow=allow;
172 nodex.flags=flags;
173
174 WriteFile(nodesx->fd,&nodex,sizeof(NodeX));
175
176 nodesx->xnumber++;
177
178 assert(nodesx->xnumber<NODE_FAKE); /* NODE_FAKE marks the high-water mark for real nodes. */
179 }
180
181
182 /*++++++++++++++++++++++++++++++++++++++
183 Sort the node list (i.e. create the sortable indexes).
184
185 NodesX* nodesx The set of nodes to process.
186 ++++++++++++++++++++++++++++++++++++++*/
187
188 void SortNodeList(NodesX* nodesx)
189 {
190 int fd;
191
192 /* Print the start message */
193
194 printf_first("Sorting Nodes");
195
196 /* Close the files and re-open them (finished appending) */
197
198 CloseFile(nodesx->fd);
199 nodesx->fd=ReOpenFile(nodesx->filename);
200
201 DeleteFile(nodesx->filename);
202
203 fd=OpenFileNew(nodesx->filename);
204
205 /* Allocate the array of indexes */
206
207 nodesx->idata=(node_t*)malloc(nodesx->xnumber*sizeof(node_t));
208
209 assert(nodesx->idata); /* Check malloc() worked */
210
211 /* Sort by node indexes */
212
213 sortnodesx=nodesx;
214
215 filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))index_by_id);
216
217 /* Close the files and re-open them */
218
219 CloseFile(nodesx->fd);
220 CloseFile(fd);
221
222 nodesx->fd=ReOpenFile(nodesx->filename);
223
224 /* Print the final message */
225
226 printf_last("Sorted Nodes: Nodes=%d Duplicates=%d",nodesx->xnumber,nodesx->xnumber-nodesx->number);
227 }
228
229
230 /*++++++++++++++++++++++++++++++++++++++
231 Sort the nodes into id order.
232
233 int sort_by_id Returns the comparison of the id fields.
234
235 NodeX *a The first extended node.
236
237 NodeX *b The second extended node.
238 ++++++++++++++++++++++++++++++++++++++*/
239
240 static int sort_by_id(NodeX *a,NodeX *b)
241 {
242 node_t a_id=a->id;
243 node_t b_id=b->id;
244
245 if(a_id<b_id)
246 return(-1);
247 else if(a_id>b_id)
248 return(1);
249 else
250 return(0);
251 }
252
253
254 /*++++++++++++++++++++++++++++++++++++++
255 Index the nodes after sorting.
256
257 int index_by_id Return 1 if the value is to be kept, otherwise zero.
258
259 NodeX *nodex The extended node.
260
261 index_t index The index of this node in the total.
262 ++++++++++++++++++++++++++++++++++++++*/
263
264 static int index_by_id(NodeX *nodex,index_t index)
265 {
266 if(index==0 || sortnodesx->idata[index-1]!=nodex->id)
267 {
268 sortnodesx->idata[index]=nodex->id;
269
270 sortnodesx->number++;
271
272 return(1);
273 }
274
275 return(0);
276 }
277
278
279 /*++++++++++++++++++++++++++++++++++++++
280 Sort the node list geographically.
281
282 NodesX* nodesx The set of nodes to process.
283 ++++++++++++++++++++++++++++++++++++++*/
284
285 void SortNodeListGeographically(NodesX* nodesx)
286 {
287 int fd;
288
289 /* Print the start message */
290
291 printf_first("Sorting Nodes Geographically");
292
293 /* Allocate the memory for the geographical offsets array */
294
295 nodesx->offsets=(index_t*)malloc((nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
296
297 nodesx->latlonbin=0;
298
299 /* Close the files and re-open them */
300
301 CloseFile(nodesx->fd);
302 nodesx->fd=ReOpenFile(nodesx->filename);
303
304 DeleteFile(nodesx->filename);
305
306 fd=OpenFileNew(nodesx->filename);
307
308 /* Sort geographically */
309
310 sortnodesx=nodesx;
311
312 filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(const void*,const void*))sort_by_lat_long,(int (*)(void*,index_t))index_by_lat_long);
313
314 /* Close the files and re-open them */
315
316 CloseFile(nodesx->fd);
317 CloseFile(fd);
318
319 nodesx->fd=ReOpenFile(nodesx->filename);
320
321 /* Finish off the indexing */
322
323 for(;nodesx->latlonbin<=(nodesx->latbins*nodesx->lonbins);nodesx->latlonbin++)
324 nodesx->offsets[nodesx->latlonbin]=nodesx->number;
325
326 /* Print the final message */
327
328 printf_last("Sorted Nodes Geographically");
329 }
330
331
332 /*++++++++++++++++++++++++++++++++++++++
333 Sort the nodes into latitude and longitude order.
334
335 int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
336
337 NodeX *a The first extended node.
338
339 NodeX *b The second extended node.
340 ++++++++++++++++++++++++++++++++++++++*/
341
342 static int sort_by_lat_long(NodeX *a,NodeX *b)
343 {
344 ll_bin_t a_lon=latlong_to_bin(a->longitude);
345 ll_bin_t b_lon=latlong_to_bin(b->longitude);
346
347 if(a_lon<b_lon)
348 return(-1);
349 else if(a_lon>b_lon)
350 return(1);
351 else
352 {
353 ll_bin_t a_lat=latlong_to_bin(a->latitude);
354 ll_bin_t b_lat=latlong_to_bin(b->latitude);
355
356 if(a_lat<b_lat)
357 return(-1);
358 else if(a_lat>b_lat)
359 return(1);
360 else
361 {
362 #ifdef REGRESSION_TESTING
363 // Need this for regression testing because filesort_heapsort() is not order
364 // preserving like qsort() is (or was when tested).
365
366 index_t a_id=a->id;
367 index_t b_id=b->id;
368
369 if(a_id<b_id)
370 return(-1);
371 else if(a_id>b_id)
372 return(1);
373 else
374 #endif
375 return(0);
376 }
377 }
378 }
379
380
381 /*++++++++++++++++++++++++++++++++++++++
382 Index the nodes after sorting.
383
384 int index_by_lat_long Return 1 if the value is to be kept, otherwise zero.
385
386 NodeX *nodex The extended node.
387
388 index_t index The index of this node in the total.
389 ++++++++++++++++++++++++++++++++++++++*/
390
391 static int index_by_lat_long(NodeX *nodex,index_t index)
392 {
393 /* Work out the offsets */
394
395 ll_bin_t latbin=latlong_to_bin(nodex->latitude )-sortnodesx->latzero;
396 ll_bin_t lonbin=latlong_to_bin(nodex->longitude)-sortnodesx->lonzero;
397 int llbin=lonbin*sortnodesx->latbins+latbin;
398
399 for(;sortnodesx->latlonbin<=llbin;sortnodesx->latlonbin++)
400 sortnodesx->offsets[sortnodesx->latlonbin]=index;
401
402 return(1);
403 }
404
405
406 /*++++++++++++++++++++++++++++++++++++++
407 Find a particular node index.
408
409 index_t IndexNodeX Returns the index of the extended node with the specified id.
410
411 NodesX* nodesx The set of nodes to process.
412
413 node_t id The node id to look for.
414 ++++++++++++++++++++++++++++++++++++++*/
415
416 index_t IndexNodeX(NodesX* nodesx,node_t id)
417 {
418 int start=0;
419 int end=nodesx->number-1;
420 int mid;
421
422 /* Binary search - search key exact match only is required.
423 *
424 * # <- start | Check mid and move start or end if it doesn't match
425 * # |
426 * # | Since an exact match is wanted we can set end=mid-1
427 * # <- mid | or start=mid+1 because we know that mid doesn't match.
428 * # |
429 * # | Eventually either end=start or end=start+1 and one of
430 * # <- end | start or end is the wanted one.
431 */
432
433 if(end<start) /* There are no nodes */
434 return(NO_NODE);
435 else if(id<nodesx->idata[start]) /* Check key is not before start */
436 return(NO_NODE);
437 else if(id>nodesx->idata[end]) /* Check key is not after end */
438 return(NO_NODE);
439 else
440 {
441 do
442 {
443 mid=(start+end)/2; /* Choose mid point */
444
445 if(nodesx->idata[mid]<id) /* Mid point is too low */
446 start=mid+1;
447 else if(nodesx->idata[mid]>id) /* Mid point is too high */
448 end=mid-1;
449 else /* Mid point is correct */
450 return(mid);
451 }
452 while((end-start)>1);
453
454 if(nodesx->idata[start]==id) /* Start is correct */
455 return(start);
456
457 if(nodesx->idata[end]==id) /* End is correct */
458 return(end);
459 }
460
461 return(NO_NODE);
462 }
463
464
465 /*++++++++++++++++++++++++++++++++++++++
466 Remove any nodes that are not part of a highway.
467
468 NodesX *nodesx The complete node list.
469
470 SegmentsX *segmentsx The list of segments.
471 ++++++++++++++++++++++++++++++++++++++*/
472
473 void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx)
474 {
475 NodeX nodex;
476 int total=0,highway=0,nothighway=0;
477 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
478 latlong_t lat_min,lat_max,lon_min,lon_max;
479 int fd;
480
481 /* Print the start message */
482
483 printf_first("Checking: Nodes=0");
484
485 /* While we are here we can work out the range of data */
486
487 lat_min=radians_to_latlong( 2);
488 lat_max=radians_to_latlong(-2);
489 lon_min=radians_to_latlong( 4);
490 lon_max=radians_to_latlong(-4);
491
492 /* Modify the on-disk image */
493
494 DeleteFile(nodesx->filename);
495
496 fd=OpenFileNew(nodesx->filename);
497 SeekFile(nodesx->fd,0);
498
499 while(!ReadFile(nodesx->fd,&nodex,sizeof(NodeX)))
500 {
501 if(IndexFirstSegmentX(segmentsx,nodex.id)==NO_SEGMENT)
502 nothighway++;
503 else
504 {
505 nodex.id=highway;
506
507 WriteFile(fd,&nodex,sizeof(NodeX));
508
509 nodesx->idata[highway]=nodesx->idata[total];
510 highway++;
511
512 if(nodex.latitude<lat_min)
513 lat_min=nodex.latitude;
514 if(nodex.latitude>lat_max)
515 lat_max=nodex.latitude;
516 if(nodex.longitude<lon_min)
517 lon_min=nodex.longitude;
518 if(nodex.longitude>lon_max)
519 lon_max=nodex.longitude;
520 }
521
522 total++;
523
524 if(!(total%10000))
525 printf_middle("Checking: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway);
526 }
527
528 /* Close the files and re-open them */
529
530 CloseFile(nodesx->fd);
531 CloseFile(fd);
532
533 nodesx->fd=ReOpenFile(nodesx->filename);
534
535 nodesx->number=highway;
536
537 /* Work out the number of bins */
538
539 lat_min_bin=latlong_to_bin(lat_min);
540 lon_min_bin=latlong_to_bin(lon_min);
541 lat_max_bin=latlong_to_bin(lat_max);
542 lon_max_bin=latlong_to_bin(lon_max);
543
544 nodesx->latzero=lat_min_bin;
545 nodesx->lonzero=lon_min_bin;
546
547 nodesx->latbins=(lat_max_bin-lat_min_bin)+1;
548 nodesx->lonbins=(lon_max_bin-lon_min_bin)+1;
549
550 /* Allocate and clear the super-node markers */
551
552 nodesx->super=(uint8_t*)calloc(nodesx->number,sizeof(uint8_t));
553
554 assert(nodesx->super); /* Check calloc() worked */
555
556 /* Print the final message */
557
558 printf_last("Checked: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway);
559 }
560
561
562 /*++++++++++++++++++++++++++++++++++++++
563 Create the real node data.
564
565 NodesX *nodesx The set of nodes to use.
566
567 int iteration The final super-node iteration.
568 ++++++++++++++++++++++++++++++++++++++*/
569
570 void CreateRealNodes(NodesX *nodesx,int iteration)
571 {
572 index_t i;
573
574 /* Print the start message */
575
576 printf_first("Creating Real Nodes: Nodes=0");
577
578 /* Map into memory */
579
580 #if !SLIM
581 nodesx->xdata=MapFile(nodesx->filename);
582 #endif
583
584 /* Allocate the memory (or open the file) */
585
586 #if !SLIM
587 nodesx->ndata=(Node*)malloc(nodesx->number*sizeof(Node));
588
589 assert(nodesx->ndata); /* Check malloc() worked */
590 #else
591 nodesx->nfd=OpenFileNew(nodesx->nfilename);
592 #endif
593
594 /* Loop through and allocate. */
595
596 for(i=0;i<nodesx->number;i++)
597 {
598 NodeX *nodex=LookupNodeX(nodesx,i,1);
599 Node *node =LookupNodeXNode(nodesx,nodex->id,1);
600
601 node->latoffset=latlong_to_off(nodex->latitude);
602 node->lonoffset=latlong_to_off(nodex->longitude);
603 node->firstseg=NO_SEGMENT;
604 node->allow=nodex->allow;
605 node->flags=nodex->flags;
606
607 if(nodesx->super[nodex->id]==iteration)
608 node->flags|=NODE_SUPER;
609
610 #if SLIM
611 PutBackNodeXNode(nodesx,nodex->id,1);
612 #endif
613
614 if(!((i+1)%10000))
615 printf_middle("Creating Real Nodes: Nodes=%d",i+1);
616 }
617
618 /* Free the unneeded memory */
619
620 free(nodesx->super);
621 nodesx->super=NULL;
622
623 /* Unmap from memory */
624
625 #if !SLIM
626 nodesx->xdata=UnmapFile(nodesx->filename);
627 #endif
628
629 /* Print the final message */
630
631 printf_last("Creating Real Nodes: Nodes=%d",nodesx->number);
632 }
633
634
635 /*++++++++++++++++++++++++++++++++++++++
636 Assign the segment indexes to the nodes.
637
638 NodesX *nodesx The list of nodes to process.
639
640 SegmentsX* segmentsx The set of segments to use.
641 ++++++++++++++++++++++++++++++++++++++*/
642
643 void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx)
644 {
645 index_t i;
646
647 if(nodesx->number==0 || segmentsx->number==0)
648 return;
649
650 /* Print the start message */
651
652 printf_first("Indexing Segments: Segments=0");
653
654 /* Map into memory */
655
656 #if !SLIM
657 nodesx->xdata=MapFile(nodesx->filename);
658 segmentsx->xdata=MapFile(segmentsx->filename);
659 #endif
660
661 /* Index the nodes */
662
663 for(i=0;i<segmentsx->number;i++)
664 {
665 SegmentX *segmentx=LookupSegmentX(segmentsx,i,1);
666 node_t id1=segmentx->node1;
667 node_t id2=segmentx->node2;
668 Node *node1=LookupNodeXNode(nodesx,id1,1);
669 Node *node2=LookupNodeXNode(nodesx,id2,2);
670
671 /* Check node1 */
672
673 if(node1->firstseg==NO_SEGMENT)
674 {
675 node1->firstseg=i;
676
677 #if SLIM
678 PutBackNodeXNode(nodesx,id1,1);
679 #endif
680 }
681 else
682 {
683 index_t index=node1->firstseg;
684
685 do
686 {
687 segmentx=LookupSegmentX(segmentsx,index,1);
688
689 if(segmentx->node1==id1)
690 {
691 index++;
692
693 if(index>=segmentsx->number)
694 break;
695
696 segmentx=LookupSegmentX(segmentsx,index,1);
697
698 if(segmentx->node1!=id1)
699 break;
700 }
701 else
702 {
703 Segment *segment=LookupSegmentXSegment(segmentsx,index,1);
704
705 if(segment->next2==NO_NODE)
706 {
707 segment->next2=i;
708
709 #if SLIM
710 PutBackSegmentXSegment(segmentsx,index,1);
711 #endif
712
713 break;
714 }
715 else
716 index=segment->next2;
717 }
718 }
719 while(1);
720 }
721
722 /* Check node2 */
723
724 if(node2->firstseg==NO_SEGMENT)
725 {
726 node2->firstseg=i;
727
728 #if SLIM
729 PutBackNodeXNode(nodesx,id2,2);
730 #endif
731 }
732 else
733 {
734 index_t index=node2->firstseg;
735
736 do
737 {
738 segmentx=LookupSegmentX(segmentsx,index,1);
739
740 if(segmentx->node1==id2)
741 {
742 index++;
743
744 if(index>=segmentsx->number)
745 break;
746
747 segmentx=LookupSegmentX(segmentsx,index,1);
748
749 if(segmentx->node1!=id2)
750 break;
751 }
752 else
753 {
754 Segment *segment=LookupSegmentXSegment(segmentsx,index,1);
755
756 if(segment->next2==NO_NODE)
757 {
758 segment->next2=i;
759
760 #if SLIM
761 PutBackSegmentXSegment(segmentsx,index,1);
762 #endif
763
764 break;
765 }
766 else
767 index=segment->next2;
768 }
769 }
770 while(1);
771 }
772
773 if(!((i+1)%10000))
774 printf_middle("Indexing Segments: Segments=%d",i+1);
775 }
776
777 /* Unmap from memory */
778
779 #if !SLIM
780 nodesx->xdata=UnmapFile(nodesx->filename);
781 segmentsx->xdata=UnmapFile(segmentsx->filename);
782 #endif
783
784 /* Print the final message */
785
786 printf_last("Indexed Segments: Segments=%d ",segmentsx->number);
787 }
788
789
790 /*++++++++++++++++++++++++++++++++++++++
791 Save the node list to a file.
792
793 NodesX* nodesx The set of nodes to save.
794
795 const char *filename The name of the file to save.
796 ++++++++++++++++++++++++++++++++++++++*/
797
798 void SaveNodeList(NodesX* nodesx,const char *filename)
799 {
800 index_t i;
801 int fd;
802 NodesFile nodesfile={0};
803 int super_number=0;
804
805 /* Print the start message */
806
807 printf_first("Writing Nodes: Nodes=0");
808
809 /* Map into memory */
810
811 #if !SLIM
812 nodesx->xdata=MapFile(nodesx->filename);
813 #endif
814
815 /* Write out the nodes data */
816
817 fd=OpenFileNew(filename);
818
819 SeekFile(fd,sizeof(NodesFile));
820 WriteFile(fd,nodesx->offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
821
822 for(i=0;i<nodesx->number;i++)
823 {
824 NodeX *nodex=LookupNodeX(nodesx,i,1);
825 Node *node=LookupNodeXNode(nodesx,nodex->id,1);
826
827 if(node->flags&NODE_SUPER)
828 super_number++;
829
830 WriteFile(fd,node,sizeof(Node));
831
832 if(!((i+1)%10000))
833 printf_middle("Writing Nodes: Nodes=%d",i+1);
834 }
835
836 /* Write out the header structure */
837
838 nodesfile.number=nodesx->number;
839 nodesfile.snumber=super_number;
840
841 nodesfile.latbins=nodesx->latbins;
842 nodesfile.lonbins=nodesx->lonbins;
843
844 nodesfile.latzero=nodesx->latzero;
845 nodesfile.lonzero=nodesx->lonzero;
846
847 SeekFile(fd,0);
848 WriteFile(fd,&nodesfile,sizeof(NodesFile));
849
850 CloseFile(fd);
851
852 /* Unmap from memory */
853
854 #if !SLIM
855 nodesx->xdata=UnmapFile(nodesx->filename);
856 #endif
857
858 /* Print the final message */
859
860 printf_last("Wrote Nodes: Nodes=%d",nodesx->number);
861 }

Properties

Name Value
cvs:description Extended nodes functions.