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 519 - (show annotations) (download) (as text)
Sat Nov 13 14:22:28 2010 UTC (14 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 19332 byte(s)
Add an option to make the output more suitable for a log file.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/nodesx.c,v 1.76 2010-11-13 14:22:28 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 "functions.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 allow_t allow The allowed traffic types through the node.
160 ++++++++++++++++++++++++++++++++++++++*/
161
162 void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude,allow_t allow)
163 {
164 NodeX nodex;
165
166 nodex.id=id;
167 nodex.latitude =radians_to_latlong(latitude);
168 nodex.longitude=radians_to_latlong(longitude);
169 nodex.allow=allow;
170
171 WriteFile(nodesx->fd,&nodex,sizeof(NodeX));
172
173 nodesx->xnumber++;
174
175 assert(nodesx->xnumber<NODE_FAKE); /* NODE_FAKE marks the high-water mark for real nodes. */
176 }
177
178
179 /*++++++++++++++++++++++++++++++++++++++
180 Sort the node list (i.e. create the sortable indexes).
181
182 NodesX* nodesx The set of nodes to process.
183 ++++++++++++++++++++++++++++++++++++++*/
184
185 void SortNodeList(NodesX* nodesx)
186 {
187 int fd;
188
189 /* Print the start message */
190
191 printf_first("Sorting Nodes");
192
193 /* Close the files and re-open them (finished appending) */
194
195 CloseFile(nodesx->fd);
196 nodesx->fd=ReOpenFile(nodesx->filename);
197
198 DeleteFile(nodesx->filename);
199
200 fd=OpenFileNew(nodesx->filename);
201
202 /* Allocate the array of indexes */
203
204 nodesx->idata=(node_t*)malloc(nodesx->xnumber*sizeof(node_t));
205
206 assert(nodesx->idata); /* Check malloc() worked */
207
208 /* Sort by node indexes */
209
210 sortnodesx=nodesx;
211
212 filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))index_by_id);
213
214 /* Close the files and re-open them */
215
216 CloseFile(nodesx->fd);
217 CloseFile(fd);
218
219 nodesx->fd=ReOpenFile(nodesx->filename);
220
221 /* Print the final message */
222
223 printf_last("Sorted Nodes: Nodes=%d Duplicates=%d",nodesx->xnumber,nodesx->xnumber-nodesx->number);
224 }
225
226
227 /*++++++++++++++++++++++++++++++++++++++
228 Sort the nodes into id order.
229
230 int sort_by_id Returns the comparison of the id fields.
231
232 NodeX *a The first extended node.
233
234 NodeX *b The second extended node.
235 ++++++++++++++++++++++++++++++++++++++*/
236
237 static int sort_by_id(NodeX *a,NodeX *b)
238 {
239 node_t a_id=a->id;
240 node_t b_id=b->id;
241
242 if(a_id<b_id)
243 return(-1);
244 else if(a_id>b_id)
245 return(1);
246 else
247 return(0);
248 }
249
250
251 /*++++++++++++++++++++++++++++++++++++++
252 Index the nodes after sorting.
253
254 int index_by_id Return 1 if the value is to be kept, otherwise zero.
255
256 NodeX *nodex The extended node.
257
258 index_t index The index of this node in the total.
259 ++++++++++++++++++++++++++++++++++++++*/
260
261 static int index_by_id(NodeX *nodex,index_t index)
262 {
263 if(index==0 || sortnodesx->idata[index-1]!=nodex->id)
264 {
265 sortnodesx->idata[index]=nodex->id;
266
267 sortnodesx->number++;
268
269 return(1);
270 }
271
272 return(0);
273 }
274
275
276 /*++++++++++++++++++++++++++++++++++++++
277 Sort the node list geographically.
278
279 NodesX* nodesx The set of nodes to process.
280 ++++++++++++++++++++++++++++++++++++++*/
281
282 void SortNodeListGeographically(NodesX* nodesx)
283 {
284 int fd;
285
286 /* Print the start message */
287
288 printf_first("Sorting Nodes Geographically");
289
290 /* Allocate the memory for the geographical offsets array */
291
292 nodesx->offsets=(index_t*)malloc((nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
293
294 nodesx->latlonbin=0;
295
296 /* Close the files and re-open them */
297
298 CloseFile(nodesx->fd);
299 nodesx->fd=ReOpenFile(nodesx->filename);
300
301 DeleteFile(nodesx->filename);
302
303 fd=OpenFileNew(nodesx->filename);
304
305 /* Sort geographically */
306
307 sortnodesx=nodesx;
308
309 filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(const void*,const void*))sort_by_lat_long,(int (*)(void*,index_t))index_by_lat_long);
310
311 /* Close the files and re-open them */
312
313 CloseFile(nodesx->fd);
314 CloseFile(fd);
315
316 nodesx->fd=ReOpenFile(nodesx->filename);
317
318 /* Finish off the indexing */
319
320 for(;nodesx->latlonbin<=(nodesx->latbins*nodesx->lonbins);nodesx->latlonbin++)
321 nodesx->offsets[nodesx->latlonbin]=nodesx->number;
322
323 /* Print the final message */
324
325 printf_last("Sorted Nodes Geographically");
326 }
327
328
329 /*++++++++++++++++++++++++++++++++++++++
330 Sort the nodes into latitude and longitude order.
331
332 int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
333
334 NodeX *a The first extended node.
335
336 NodeX *b The second extended node.
337 ++++++++++++++++++++++++++++++++++++++*/
338
339 static int sort_by_lat_long(NodeX *a,NodeX *b)
340 {
341 ll_bin_t a_lon=latlong_to_bin(a->longitude);
342 ll_bin_t b_lon=latlong_to_bin(b->longitude);
343
344 if(a_lon<b_lon)
345 return(-1);
346 else if(a_lon>b_lon)
347 return(1);
348 else
349 {
350 ll_bin_t a_lat=latlong_to_bin(a->latitude);
351 ll_bin_t b_lat=latlong_to_bin(b->latitude);
352
353 if(a_lat<b_lat)
354 return(-1);
355 else if(a_lat>b_lat)
356 return(1);
357 else
358 {
359 #ifdef REGRESSION_TESTING
360 // Need this for regression testing because filesort_heapsort() is not order
361 // preserving like qsort() is (or was when tested).
362
363 index_t a_id=a->id;
364 index_t b_id=b->id;
365
366 if(a_id<b_id)
367 return(-1);
368 else if(a_id>b_id)
369 return(1);
370 else
371 #endif
372 return(0);
373 }
374 }
375 }
376
377
378 /*++++++++++++++++++++++++++++++++++++++
379 Index the nodes after sorting.
380
381 int index_by_lat_long Return 1 if the value is to be kept, otherwise zero.
382
383 NodeX *nodex The extended node.
384
385 index_t index The index of this node in the total.
386 ++++++++++++++++++++++++++++++++++++++*/
387
388 static int index_by_lat_long(NodeX *nodex,index_t index)
389 {
390 /* Work out the offsets */
391
392 ll_bin_t latbin=latlong_to_bin(nodex->latitude )-sortnodesx->latzero;
393 ll_bin_t lonbin=latlong_to_bin(nodex->longitude)-sortnodesx->lonzero;
394 int llbin=lonbin*sortnodesx->latbins+latbin;
395
396 for(;sortnodesx->latlonbin<=llbin;sortnodesx->latlonbin++)
397 sortnodesx->offsets[sortnodesx->latlonbin]=index;
398
399 return(1);
400 }
401
402
403 /*++++++++++++++++++++++++++++++++++++++
404 Find a particular node index.
405
406 index_t IndexNodeX Returns the index of the extended node with the specified id.
407
408 NodesX* nodesx The set of nodes to process.
409
410 node_t id The node id to look for.
411 ++++++++++++++++++++++++++++++++++++++*/
412
413 index_t IndexNodeX(NodesX* nodesx,node_t id)
414 {
415 int start=0;
416 int end=nodesx->number-1;
417 int mid;
418
419 /* Binary search - search key exact match only is required.
420 *
421 * # <- start | Check mid and move start or end if it doesn't match
422 * # |
423 * # | Since an exact match is wanted we can set end=mid-1
424 * # <- mid | or start=mid+1 because we know that mid doesn't match.
425 * # |
426 * # | Eventually either end=start or end=start+1 and one of
427 * # <- end | start or end is the wanted one.
428 */
429
430 if(end<start) /* There are no nodes */
431 return(NO_NODE);
432 else if(id<nodesx->idata[start]) /* Check key is not before start */
433 return(NO_NODE);
434 else if(id>nodesx->idata[end]) /* Check key is not after end */
435 return(NO_NODE);
436 else
437 {
438 do
439 {
440 mid=(start+end)/2; /* Choose mid point */
441
442 if(nodesx->idata[mid]<id) /* Mid point is too low */
443 start=mid+1;
444 else if(nodesx->idata[mid]>id) /* Mid point is too high */
445 end=mid-1;
446 else /* Mid point is correct */
447 return(mid);
448 }
449 while((end-start)>1);
450
451 if(nodesx->idata[start]==id) /* Start is correct */
452 return(start);
453
454 if(nodesx->idata[end]==id) /* End is correct */
455 return(end);
456 }
457
458 return(NO_NODE);
459 }
460
461
462 /*++++++++++++++++++++++++++++++++++++++
463 Remove any nodes that are not part of a highway.
464
465 NodesX *nodesx The complete node list.
466
467 SegmentsX *segmentsx The list of segments.
468 ++++++++++++++++++++++++++++++++++++++*/
469
470 void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx)
471 {
472 NodeX nodex;
473 int total=0,highway=0,nothighway=0;
474 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
475 latlong_t lat_min,lat_max,lon_min,lon_max;
476 int fd;
477
478 /* Print the start message */
479
480 printf_first("Checking: Nodes=0");
481
482 /* While we are here we can work out the range of data */
483
484 lat_min=radians_to_latlong( 2);
485 lat_max=radians_to_latlong(-2);
486 lon_min=radians_to_latlong( 4);
487 lon_max=radians_to_latlong(-4);
488
489 /* Modify the on-disk image */
490
491 DeleteFile(nodesx->filename);
492
493 fd=OpenFileNew(nodesx->filename);
494 SeekFile(nodesx->fd,0);
495
496 while(!ReadFile(nodesx->fd,&nodex,sizeof(NodeX)))
497 {
498 if(IndexFirstSegmentX(segmentsx,nodex.id)==NO_SEGMENT)
499 nothighway++;
500 else
501 {
502 nodex.id=highway;
503
504 WriteFile(fd,&nodex,sizeof(NodeX));
505
506 nodesx->idata[highway]=nodesx->idata[total];
507 highway++;
508
509 if(nodex.latitude<lat_min)
510 lat_min=nodex.latitude;
511 if(nodex.latitude>lat_max)
512 lat_max=nodex.latitude;
513 if(nodex.longitude<lon_min)
514 lon_min=nodex.longitude;
515 if(nodex.longitude>lon_max)
516 lon_max=nodex.longitude;
517 }
518
519 total++;
520
521 if(!(total%10000))
522 printf_middle("Checking: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway);
523 }
524
525 /* Close the files and re-open them */
526
527 CloseFile(nodesx->fd);
528 CloseFile(fd);
529
530 nodesx->fd=ReOpenFile(nodesx->filename);
531
532 nodesx->number=highway;
533
534 /* Work out the number of bins */
535
536 lat_min_bin=latlong_to_bin(lat_min);
537 lon_min_bin=latlong_to_bin(lon_min);
538 lat_max_bin=latlong_to_bin(lat_max);
539 lon_max_bin=latlong_to_bin(lon_max);
540
541 nodesx->latzero=lat_min_bin;
542 nodesx->lonzero=lon_min_bin;
543
544 nodesx->latbins=(lat_max_bin-lat_min_bin)+1;
545 nodesx->lonbins=(lon_max_bin-lon_min_bin)+1;
546
547 /* Allocate and clear the super-node markers */
548
549 nodesx->super=(uint8_t*)calloc(nodesx->number,sizeof(uint8_t));
550
551 assert(nodesx->super); /* Check calloc() worked */
552
553 /* Print the final message */
554
555 printf_last("Checked: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway);
556 }
557
558
559 /*++++++++++++++++++++++++++++++++++++++
560 Create the real node data.
561
562 NodesX *nodesx The set of nodes to use.
563
564 int iteration The final super-node iteration.
565 ++++++++++++++++++++++++++++++++++++++*/
566
567 void CreateRealNodes(NodesX *nodesx,int iteration)
568 {
569 index_t i;
570
571 /* Print the start message */
572
573 printf_first("Creating Real Nodes: Nodes=0");
574
575 /* Map into memory */
576
577 #if !SLIM
578 nodesx->xdata=MapFile(nodesx->filename);
579 #endif
580
581 /* Allocate the memory (or open the file) */
582
583 #if !SLIM
584 nodesx->ndata=(Node*)malloc(nodesx->number*sizeof(Node));
585
586 assert(nodesx->ndata); /* Check malloc() worked */
587 #else
588 nodesx->nfd=OpenFileNew(nodesx->nfilename);
589 #endif
590
591 /* Loop through and allocate. */
592
593 for(i=0;i<nodesx->number;i++)
594 {
595 NodeX *nodex=LookupNodeX(nodesx,i,1);
596 Node *node =LookupNodeXNode(nodesx,nodex->id,1);
597
598 node->latoffset=latlong_to_off(nodex->latitude);
599 node->lonoffset=latlong_to_off(nodex->longitude);
600 node->firstseg=NO_SEGMENT;
601 node->allow=nodex->allow;
602 node->flags=0;
603
604 if(nodesx->super[nodex->id]==iteration)
605 node->flags|=NODE_SUPER;
606
607 #if SLIM
608 PutBackNodeXNode(nodesx,nodex->id,1);
609 #endif
610
611 if(!((i+1)%10000))
612 printf_middle("Creating Real Nodes: Nodes=%d",i+1);
613 }
614
615 /* Free the unneeded memory */
616
617 free(nodesx->super);
618 nodesx->super=NULL;
619
620 /* Unmap from memory */
621
622 #if !SLIM
623 nodesx->xdata=UnmapFile(nodesx->filename);
624 #endif
625
626 /* Print the final message */
627
628 printf_last("Creating Real Nodes: Nodes=%d",nodesx->number);
629 }
630
631
632 /*++++++++++++++++++++++++++++++++++++++
633 Assign the segment indexes to the nodes.
634
635 NodesX *nodesx The list of nodes to process.
636
637 SegmentsX* segmentsx The set of segments to use.
638 ++++++++++++++++++++++++++++++++++++++*/
639
640 void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx)
641 {
642 index_t i;
643
644 if(nodesx->number==0 || segmentsx->number==0)
645 return;
646
647 /* Print the start message */
648
649 printf_first("Indexing Segments: Segments=0");
650
651 /* Map into memory */
652
653 #if !SLIM
654 nodesx->xdata=MapFile(nodesx->filename);
655 segmentsx->xdata=MapFile(segmentsx->filename);
656 #endif
657
658 /* Index the nodes */
659
660 for(i=0;i<segmentsx->number;i++)
661 {
662 SegmentX *segmentx=LookupSegmentX(segmentsx,i,1);
663 node_t id1=segmentx->node1;
664 node_t id2=segmentx->node2;
665 Node *node1=LookupNodeXNode(nodesx,id1,1);
666 Node *node2=LookupNodeXNode(nodesx,id2,2);
667
668 /* Check node1 */
669
670 if(node1->firstseg==NO_SEGMENT)
671 {
672 node1->firstseg=i;
673
674 #if SLIM
675 PutBackNodeXNode(nodesx,id1,1);
676 #endif
677 }
678 else
679 {
680 index_t index=node1->firstseg;
681
682 do
683 {
684 segmentx=LookupSegmentX(segmentsx,index,1);
685
686 if(segmentx->node1==id1)
687 {
688 index++;
689
690 if(index>=segmentsx->number)
691 break;
692
693 segmentx=LookupSegmentX(segmentsx,index,1);
694
695 if(segmentx->node1!=id1)
696 break;
697 }
698 else
699 {
700 Segment *segment=LookupSegmentXSegment(segmentsx,index,1);
701
702 if(segment->next2==NO_NODE)
703 {
704 segment->next2=i;
705
706 #if SLIM
707 PutBackSegmentXSegment(segmentsx,index,1);
708 #endif
709
710 break;
711 }
712 else
713 index=segment->next2;
714 }
715 }
716 while(1);
717 }
718
719 /* Check node2 */
720
721 if(node2->firstseg==NO_SEGMENT)
722 {
723 node2->firstseg=i;
724
725 #if SLIM
726 PutBackNodeXNode(nodesx,id2,2);
727 #endif
728 }
729 else
730 {
731 index_t index=node2->firstseg;
732
733 do
734 {
735 segmentx=LookupSegmentX(segmentsx,index,1);
736
737 if(segmentx->node1==id2)
738 {
739 index++;
740
741 if(index>=segmentsx->number)
742 break;
743
744 segmentx=LookupSegmentX(segmentsx,index,1);
745
746 if(segmentx->node1!=id2)
747 break;
748 }
749 else
750 {
751 Segment *segment=LookupSegmentXSegment(segmentsx,index,1);
752
753 if(segment->next2==NO_NODE)
754 {
755 segment->next2=i;
756
757 #if SLIM
758 PutBackSegmentXSegment(segmentsx,index,1);
759 #endif
760
761 break;
762 }
763 else
764 index=segment->next2;
765 }
766 }
767 while(1);
768 }
769
770 if(!((i+1)%10000))
771 printf_middle("Indexing Segments: Segments=%d",i+1);
772 }
773
774 /* Unmap from memory */
775
776 #if !SLIM
777 nodesx->xdata=UnmapFile(nodesx->filename);
778 segmentsx->xdata=UnmapFile(segmentsx->filename);
779 #endif
780
781 /* Print the final message */
782
783 printf_last("Indexed Segments: Segments=%d ",segmentsx->number);
784 }
785
786
787 /*++++++++++++++++++++++++++++++++++++++
788 Save the node list to a file.
789
790 NodesX* nodesx The set of nodes to save.
791
792 const char *filename The name of the file to save.
793 ++++++++++++++++++++++++++++++++++++++*/
794
795 void SaveNodeList(NodesX* nodesx,const char *filename)
796 {
797 index_t i;
798 int fd;
799 NodesFile nodesfile={0};
800 int super_number=0;
801
802 /* Print the start message */
803
804 printf_first("Writing Nodes: Nodes=0");
805
806 /* Map into memory */
807
808 #if !SLIM
809 nodesx->xdata=MapFile(nodesx->filename);
810 #endif
811
812 /* Write out the nodes data */
813
814 fd=OpenFileNew(filename);
815
816 SeekFile(fd,sizeof(NodesFile));
817 WriteFile(fd,nodesx->offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t));
818
819 for(i=0;i<nodesx->number;i++)
820 {
821 NodeX *nodex=LookupNodeX(nodesx,i,1);
822 Node *node=LookupNodeXNode(nodesx,nodex->id,1);
823
824 if(node->flags&NODE_SUPER)
825 super_number++;
826
827 WriteFile(fd,node,sizeof(Node));
828
829 if(!((i+1)%10000))
830 printf_middle("Writing Nodes: Nodes=%d",i+1);
831 }
832
833 /* Write out the header structure */
834
835 nodesfile.number=nodesx->number;
836 nodesfile.snumber=super_number;
837
838 nodesfile.latbins=nodesx->latbins;
839 nodesfile.lonbins=nodesx->lonbins;
840
841 nodesfile.latzero=nodesx->latzero;
842 nodesfile.lonzero=nodesx->lonzero;
843
844 SeekFile(fd,0);
845 WriteFile(fd,&nodesfile,sizeof(NodesFile));
846
847 CloseFile(fd);
848
849 /* Unmap from memory */
850
851 #if !SLIM
852 nodesx->xdata=UnmapFile(nodesx->filename);
853 #endif
854
855 /* Print the final message */
856
857 printf_last("Wrote Nodes: Nodes=%d",nodesx->number);
858 }

Properties

Name Value
cvs:description Extended nodes functions.