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 612 - (show annotations) (download) (as text)
Sat Jan 29 19:23:15 2011 UTC (14 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 19691 byte(s)
Ensure that record of closed file descriptors are erased.

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

Properties

Name Value
cvs:description Extended nodes functions.