GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
plus_struct.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * MODULE: Vector library
4 *
5 * AUTHOR(S): Dave Gerdes, CERL.
6 * Update to GRASS 5.7 Radim Blazek.
7 *
8 * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
9 *
10 * COPYRIGHT: (C) 2001 by the GRASS Development Team
11 *
12 * This program is free software under the GNU General Public
13 * License (>=v2). Read the file COPYING that comes with GRASS
14 * for details.
15 *
16 *****************************************************************************/
17
18#include <inttypes.h>
19#include <sys/types.h>
20#include <string.h>
21#include <grass/vector.h>
22#include <grass/glocale.h>
23#include <grass/version.h>
24
25/*
26 * Routines for reading and writing Dig+ structures.
27 * return 0 on success, -1 on failure of whatever kind
28 * if you don't want it written out, then don't call these routines
29 * ie check for deleted status before calling a write routine
30 * in as much as it would be nice to hide that code in here,
31 * this is a library routine and we chose to make it dependent on
32 * as few external files as possible
33 */
34
35/* These routines assume ptr->alloc_lines is valid
36 * Make sure it is initialized before calling
37 */
38
39/*
40 * Internally, my default variables for lines/areas/nodes/isles are type
41 * plus_t which is typedefed as short. This limits the current version
42 * to no more than 32K lines, nodes etc. (excluding points)
43 * All in the name of future expansion, I have converted these values to
44 * longs in the dig_plus data file.
45 *
46 * NOTE: 3.10 changes plus_t to ints.
47 * This assumes that any reasonable machine will use 4 bytes to
48 * store an int. The mapdev code is not guaranteed to work if
49 * plus_t is changed to a type that is larger than an int.
50 */
51int dig_Rd_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
52{
53 int cnt, n_edges;
54 struct P_node *ptr;
55
56 G_debug(4, "dig_Rd_P_node()");
57
58 if (0 >= dig__fread_port_P(&cnt, 1, fp))
59 return (-1);
60
61 if (cnt == 0) { /* dead */
62 G_debug(4, " node is dead");
63 Plus->Node[n] = NULL;
64 return 0;
65 }
66
67 ptr = dig_alloc_node();
68 ptr->n_lines = cnt;
69
70 if (dig_node_alloc_line(ptr, ptr->n_lines) == -1) {
71 dig_free_node(ptr);
72 return -1;
73 }
74
75 if (ptr->n_lines) {
76 if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
77 dig_free_node(ptr);
78 return (-1);
79 }
80 if (0 >= dig__fread_port_F(ptr->angles, ptr->n_lines, fp)) {
81 dig_free_node(ptr);
82 return (-1);
83 }
84 }
85
86 if (Plus->with_z) {
87 if (0 >= dig__fread_port_P(&n_edges, 1, fp)) { /* reserved for edges */
88 dig_free_node(ptr);
89 return (-1);
90 }
91 }
92 /* here will be edges */
93
94 if (0 >= dig__fread_port_D(&(ptr->x), 1, fp)) {
95 dig_free_node(ptr);
96 return (-1);
97 }
98 if (0 >= dig__fread_port_D(&(ptr->y), 1, fp)) {
99 dig_free_node(ptr);
100 return (-1);
101 }
102
103 if (Plus->with_z) {
104 if (0 >= dig__fread_port_D(&(ptr->z), 1, fp)) {
105 dig_free_node(ptr);
106 return (-1);
107 }
108 }
109 else
110 ptr->z = 0;
111
112 Plus->Node[n] = ptr;
113
114 return (0);
115}
116
117int dig_Wr_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
118{
119 int i, n_edges = 0;
120 struct P_node *ptr;
121
122 G_debug(4, "dig_Wr_P_node()");
123 ptr = Plus->Node[n];
124
125 /* If NULL i.e. dead write just 0 instead of number of lines */
126 if (ptr == NULL) {
127 G_debug(4, " node is dead -> write 0 only");
128 i = 0;
129 if (0 >= dig__fwrite_port_P(&i, 1, fp))
130 return (-1);
131 return 0;
132 }
133
134 if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
135 return (-1);
136
137 if (ptr->n_lines) {
138 if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
139 return (-1);
140 if (0 >= dig__fwrite_port_F(ptr->angles, ptr->n_lines, fp))
141 return (-1);
142 }
143
144 if (Plus->with_z)
145 if (0 >= dig__fwrite_port_P(&n_edges, 1, fp)) /* reserved for edges */
146 return (-1);
147
148 /* here will be edges */
149
150 if (0 >= dig__fwrite_port_D(&(ptr->x), 1, fp))
151 return (-1);
152 if (0 >= dig__fwrite_port_D(&(ptr->y), 1, fp))
153 return (-1);
154
155 if (Plus->with_z)
156 if (0 >= dig__fwrite_port_D(&(ptr->z), 1, fp))
157 return (-1);
158
159 return (0);
160}
161
162int dig_Rd_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
163{
164 int n_edges;
165 char tp;
166 struct P_line *ptr;
167
168 G_debug(4, "dig_Rd_P_line()");
169
170 if (0 >= dig__fread_port_C(&tp, 1, fp))
171 return (-1);
172
173 if (tp == 0) { /* dead */
174 G_debug(4, " line is dead");
175 Plus->Line[n] = NULL;
176 return 0;
177 }
178
179 ptr = dig_alloc_line();
180
181 /* type */
183 G_debug(5, " line type %d -> %d", tp, ptr->type);
184
185 /* offset */
186 if (0 >= dig__fread_port_O(&(ptr->offset), 1, fp, Plus->off_t_size))
188
189 if (ptr->type == GV_POINT) {
190 ptr->topo = NULL;
191 }
192 else {
193 ptr->topo = dig_alloc_topo(ptr->type);
194 }
195
196 /* centroids */
197 if (ptr->type & GV_CENTROID) {
198 struct P_topo_c *topo = (struct P_topo_c *)ptr->topo;
199
200 if (0 >= dig__fread_port_P(&(topo->area), 1, fp))
202 }
203 /* lines */
204 else if (ptr->type & GV_LINE) {
205 struct P_topo_l *topo = (struct P_topo_l *)ptr->topo;
206
207 if (0 >= dig__fread_port_P(&(topo->N1), 1, fp))
209 if (0 >= dig__fread_port_P(&(topo->N2), 1, fp))
211 }
212 /* boundaries */
213 else if (ptr->type & GV_BOUNDARY) {
214 struct P_topo_b *topo = (struct P_topo_b *)ptr->topo;
215
216 if (0 >= dig__fread_port_P(&(topo->N1), 1, fp))
218 if (0 >= dig__fread_port_P(&(topo->N2), 1, fp))
220 if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
222 if (0 >= dig__fread_port_P(&(topo->right), 1, fp))
224 }
225 /* faces */
226 else if ((ptr->type & GV_FACE) &&
227 Plus->with_z) { /* reserved for face edges */
228 struct P_topo_f *topo = (struct P_topo_f *)ptr->topo;
229
230 if (0 >= dig__fread_port_I(&n_edges, 1, fp))
232
233 /* here will be list of edges */
234
235 /* left / right volume */
236 if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
238 if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
240 }
241 /* kernels */
242 else if ((ptr->type & GV_KERNEL) &&
243 Plus->with_z) { /* reserved for kernel (volume number) */
244 struct P_topo_k *topo = (struct P_topo_k *)ptr->topo;
245
246 if (0 >= dig__fread_port_P(&(topo->volume), 1, fp))
248 }
249
250 Plus->Line[n] = ptr;
251
252 return (0);
253
255 dig_free_line(ptr);
256 return -1;
257}
258
259int dig_Wr_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
260{
261 int n_edges = 0;
262 char ch;
263 struct P_line *ptr;
264
265 G_debug(4, "dig_Wr_P_line() line = %d", n);
266
267 ptr = Plus->Line[n];
268
269 /* if NULL i.e. dead write just 0 instead of type */
270 if (ptr == NULL) {
271 G_debug(4, " line is dead -> write 0 only");
272 ch = 0;
273 if (0 >= dig__fwrite_port_C(&ch, 1, fp))
274 return (-1);
275 return 0;
276 }
277
278 /* type */
279 ch = (char)dig_type_to_store(ptr->type);
280 G_debug(5, " line type %d -> %d", ptr->type, ch);
281 if (0 >= dig__fwrite_port_C(&ch, 1, fp))
282 return (-1);
283
284 /* offset */
285 if (0 >= dig__fwrite_port_O(&(ptr->offset), 1, fp, Plus->off_t_size))
286 return (-1);
287
288 if (!ptr->topo)
289 return (0);
290
291 /* nothing else for points */
292
293 /* centroids */
294 if (ptr->type & GV_CENTROID) {
295 struct P_topo_c *topo = (struct P_topo_c *)ptr->topo;
296
297 if (0 >= dig__fwrite_port_P(&(topo->area), 1, fp))
298 return (-1);
299 }
300 /* lines */
301 else if (ptr->type & GV_LINE) {
302 struct P_topo_l *topo = (struct P_topo_l *)ptr->topo;
303
304 if (0 >= dig__fwrite_port_P(&(topo->N1), 1, fp))
305 return (-1);
306 if (0 >= dig__fwrite_port_P(&(topo->N2), 1, fp))
307 return (-1);
308 }
309 /* boundaries */
310 else if (ptr->type & GV_BOUNDARY) {
311 struct P_topo_b *topo = (struct P_topo_b *)ptr->topo;
312
313 if (0 >= dig__fwrite_port_P(&(topo->N1), 1, fp))
314 return (-1);
315 if (0 >= dig__fwrite_port_P(&(topo->N2), 1, fp))
316 return (-1);
317 if (0 >= dig__fwrite_port_P(&(topo->left), 1, fp))
318 return (-1);
319 if (0 >= dig__fwrite_port_P(&(topo->right), 1, fp))
320 return (-1);
321 }
322 /* faces */
323 else if ((ptr->type & GV_FACE) && Plus->with_z) { /* reserved for face */
324 struct P_topo_f *topo = (struct P_topo_f *)ptr->topo;
325
326 if (0 >= dig__fwrite_port_I(&n_edges, 1, fp))
327 return (-1);
328
329 /* here will be list of edges */
330
331 /* left / right volume / hole */
332 if (0 >= dig__fwrite_port_P(&(topo->left), 1, fp))
333 return (-1);
334 if (0 >= dig__fwrite_port_P(&(topo->right), 1, fp))
335 return (-1);
336 }
337 /* kernels */
338 else if ((ptr->type & GV_KERNEL) &&
339 Plus->with_z) { /* reserved for kernel (volume number) */
340 struct P_topo_k *topo = (struct P_topo_k *)ptr->topo;
341
342 /* volume */
343 if (0 >= dig__fwrite_port_P(&(topo->volume), 1, fp))
344 return (-1);
345 }
346
347 return (0);
348}
349
350int dig_Rd_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
351{
352 int cnt;
353 struct P_area *ptr;
354
355 G_debug(4, "dig_Rd_P_area(): n = %d", n);
356
357 if (0 >= dig__fread_port_P(&cnt, 1, fp))
358 return (-1);
359
360 if (cnt == 0) { /* dead */
361 Plus->Area[n] = NULL;
362 return 0;
363 }
364
365 ptr = dig_alloc_area();
366
367 /* boundaries */
368 ptr->n_lines = cnt;
369
370 if (dig_area_alloc_line(ptr, ptr->n_lines) == -1) {
371 dig_free_area(ptr);
372 return -1;
373 }
374
375 if (ptr->n_lines) {
376 if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
377 dig_free_area(ptr);
378 return -1;
379 }
380 }
381
382 /* isles */
383 if (0 >= dig__fread_port_P(&(ptr->n_isles), 1, fp)) {
384 dig_free_area(ptr);
385 return -1;
386 }
387
388 if (dig_area_alloc_isle(ptr, ptr->n_isles) == -1) {
389 dig_free_area(ptr);
390 return -1;
391 }
392
393 if (ptr->n_isles) {
394 if (0 >= dig__fread_port_P(ptr->isles, ptr->n_isles, fp)) {
395 dig_free_area(ptr);
396 return -1;
397 }
398 }
399 /* centroid */
400 if (0 >= dig__fread_port_P(&(ptr->centroid), 1, fp)) {
401 dig_free_area(ptr);
402 return -1;
403 }
404
405 Plus->Area[n] = ptr;
406
407 return (0);
408}
409
410int dig_Wr_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
411{
412 int i;
413 struct P_area *ptr;
414
415 ptr = Plus->Area[n];
416
417 /* If NULL i.e. dead write just 0 instead of number of lines */
418 if (ptr == NULL) {
419 i = 0;
420 if (0 >= dig__fwrite_port_P(&i, 1, fp))
421 return (-1);
422 return 0;
423 }
424
425 /* boundaries */
426 if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
427 return (-1);
428
429 if (ptr->n_lines)
430 if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
431 return -1;
432
433 /* isles */
434 if (0 >= dig__fwrite_port_P(&(ptr->n_isles), 1, fp))
435 return (-1);
436
437 if (ptr->n_isles)
438 if (0 >= dig__fwrite_port_P(ptr->isles, ptr->n_isles, fp))
439 return -1;
440
441 /* centroid */
442 if (0 >= dig__fwrite_port_P(&(ptr->centroid), 1, fp))
443 return (-1);
444
445 return (0);
446}
447
448int dig_Rd_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
449{
450 int cnt;
451 struct P_isle *ptr;
452
453 G_debug(4, "dig_Rd_P_isle()");
454
455 if (0 >= dig__fread_port_P(&cnt, 1, fp))
456 return (-1);
457
458 if (cnt == 0) { /* dead */
459 Plus->Isle[n] = NULL;
460 return 0;
461 }
462
463 ptr = dig_alloc_isle();
464
465 /* boundaries */
466 ptr->n_lines = cnt;
467
468 if (dig_isle_alloc_line(ptr, ptr->n_lines) == -1) {
469 dig_free_isle(ptr);
470 return -1;
471 }
472
473 if (ptr->n_lines) {
474 if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
475 dig_free_isle(ptr);
476 return -1;
477 }
478 }
479
480 /* area */
481 if (0 >= dig__fread_port_P(&(ptr->area), 1, fp)) {
482 dig_free_isle(ptr);
483 return -1;
484 }
485
486 Plus->Isle[n] = ptr;
487
488 return (0);
489}
490
491int dig_Wr_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
492{
493 int i;
494 struct P_isle *ptr;
495
496 ptr = Plus->Isle[n];
497
498 /* If NULL i.e. dead write just 0 instead of number of lines */
499 if (ptr == NULL) {
500 i = 0;
501 if (0 >= dig__fwrite_port_P(&i, 1, fp))
502 return (-1);
503 return 0;
504 }
505
506 /* lines */
507 if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
508 return (-1);
509
510 if (ptr->n_lines)
511 if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
512 return -1;
513
514 /* area */
515 if (0 >= dig__fwrite_port_P(&(ptr->area), 1, fp))
516 return (-1);
517
518 return (0);
519}
520
521/*!
522 \brief Read Plus_head from file
523
524 \param fp pointer to gvfile structure
525 \param[in,out] ptr pointer to Plus_head structure
526
527 \return -1 error
528 \return 0 OK
529 */
530int dig_Rd_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
531{
532 unsigned char buf[5];
533 int byte_order;
534
535 dig_rewind(fp);
536
537 /* bytes 1 - 5 */
538 if (0 >= dig__fread_port_C((char *)buf, 5, fp))
539 return (-1);
540 ptr->version.topo.major = buf[0];
541 ptr->version.topo.minor = buf[1];
542 ptr->version.topo.back_major = buf[2];
543 ptr->version.topo.back_minor = buf[3];
544 byte_order = buf[4];
545
546 G_debug(
547 2,
548 "Topo header: file version %d.%d , supported from GRASS version %d.%d",
549 ptr->version.topo.major, ptr->version.topo.minor,
550 ptr->version.topo.back_major, ptr->version.topo.back_minor);
551
552 G_debug(2, " byte order %d", byte_order);
553
554 /* check version numbers */
555 if (ptr->version.topo.major > GV_TOPO_VER_MAJOR ||
556 ptr->version.topo.minor > GV_TOPO_VER_MINOR) {
557 /* The file was created by GRASS library with higher version than this
558 * one */
559
560 if (ptr->version.topo.back_major > GV_TOPO_VER_MAJOR ||
561 ptr->version.topo.back_minor > GV_TOPO_VER_MINOR) {
562 /* This version of GRASS lib is lower than the oldest which can read
563 * this format */
564 G_debug(1, "Topology format version %d.%d", ptr->version.topo.major,
565 ptr->version.topo.minor);
566 G_fatal_error(_("This version of GRASS (%d.%d) is too old to read "
567 "this topology format."
568 " Try to rebuild topology or upgrade GRASS to at "
569 "least version %d."),
572 return (-1);
573 }
574
575 G_warning(_("Your GRASS version does not fully support topology format "
576 "%d.%d of the vector."
577 " Consider to rebuild topology or upgrade GRASS."),
578 ptr->version.topo.major, ptr->version.topo.minor);
579 }
580 if (ptr->version.topo.major < GV_TOPO_VER_MAJOR ||
581 (ptr->version.topo.major == GV_TOPO_VER_MAJOR &&
582 ptr->version.topo.minor < GV_TOPO_VER_MINOR)) {
583 /* The file was created by GRASS library with lower version than this
584 * one */
585
586 /* This version of GRASS lib can not read this old format */
587 G_warning(
588 _("Old topology format version %d.%d is not supported by this "
589 "release."
590 " Try to rebuild topology using v.build or v.build.all module."),
591 ptr->version.topo.major, ptr->version.topo.minor);
592 return (-1);
593 }
594
595 /* init Port_info structure and set as default */
596 dig_init_portable(&(ptr->port), byte_order);
597 dig_set_cur_port(&(ptr->port));
598
599 /* bytes 6 - 9 : header size */
600 if (0 >= dig__fread_port_L(&(ptr->head_size), 1, fp))
601 return (-1);
602 G_debug(2, " header size %ld", ptr->head_size);
603
604 /* determine required offset size from header size */
605 /* this is not safe in case new fields get added in later versions */
606 /* better: add a new field with off_t_size after byte_order? */
607 if (ptr->head_size >= 142 + 32) /* keep in sync with dig_Wr_Plus_head() */
608 ptr->off_t_size = 8;
609 else
610 ptr->off_t_size = 4;
611
612 if (sizeof(off_t) < (size_t)ptr->off_t_size) {
613 G_warning(_("Vector exceeds supported file size limit"));
614 return (-1);
615 }
616
617 G_debug(2, "topo off_t size = %d", ptr->off_t_size);
618
619 /* byte 10 : dimension 2D or 3D */
620 if (0 >= dig__fread_port_C((char *)buf, 1, fp))
621 return (-1);
622 ptr->with_z = buf[0];
623 G_debug(2, " with_z %d", ptr->with_z);
624
625 /* bytes 11 - 58 : bound box */
626 if (0 >= dig__fread_port_D(&(ptr->box.N), 1, fp))
627 return (-1);
628 if (0 >= dig__fread_port_D(&(ptr->box.S), 1, fp))
629 return (-1);
630 if (0 >= dig__fread_port_D(&(ptr->box.E), 1, fp))
631 return (-1);
632 if (0 >= dig__fread_port_D(&(ptr->box.W), 1, fp))
633 return (-1);
634 if (0 >= dig__fread_port_D(&(ptr->box.T), 1, fp))
635 return (-1);
636 if (0 >= dig__fread_port_D(&(ptr->box.B), 1, fp))
637 return (-1);
638
639 /* bytes 59 - 86 : number of structures */
640 if (0 >= dig__fread_port_P(&(ptr->n_nodes), 1, fp))
641 return (-1);
642 if (0 >= dig__fread_port_P(&(ptr->n_edges), 1, fp))
643 return (-1);
644 if (0 >= dig__fread_port_P(&(ptr->n_lines), 1, fp))
645 return (-1);
646 if (0 >= dig__fread_port_P(&(ptr->n_areas), 1, fp))
647 return (-1);
648 if (0 >= dig__fread_port_P(&(ptr->n_isles), 1, fp))
649 return (-1);
650 if (0 >= dig__fread_port_P(&(ptr->n_volumes), 1, fp))
651 return (-1);
652 if (0 >= dig__fread_port_P(&(ptr->n_holes), 1, fp))
653 return (-1);
654
655 /* bytes 87 - 110 : number of line types */
656 if (0 >= dig__fread_port_P(&(ptr->n_plines), 1, fp))
657 return (-1);
658 if (0 >= dig__fread_port_P(&(ptr->n_llines), 1, fp))
659 return (-1);
660 if (0 >= dig__fread_port_P(&(ptr->n_blines), 1, fp))
661 return (-1);
662 if (0 >= dig__fread_port_P(&(ptr->n_clines), 1, fp))
663 return (-1);
664 if (0 >= dig__fread_port_P(&(ptr->n_flines), 1, fp))
665 return (-1);
666 if (0 >= dig__fread_port_P(&(ptr->n_klines), 1, fp))
667 return (-1);
668
669 /* bytes 111 - 138 : Offset */
670 if (0 >= dig__fread_port_O(&(ptr->Node_offset), 1, fp, ptr->off_t_size))
671 return (-1);
672 if (0 >= dig__fread_port_O(&(ptr->Edge_offset), 1, fp, ptr->off_t_size))
673 return (-1);
674 if (0 >= dig__fread_port_O(&(ptr->Line_offset), 1, fp, ptr->off_t_size))
675 return (-1);
676 if (0 >= dig__fread_port_O(&(ptr->Area_offset), 1, fp, ptr->off_t_size))
677 return (-1);
678 if (0 >= dig__fread_port_O(&(ptr->Isle_offset), 1, fp, ptr->off_t_size))
679 return (-1);
680 if (0 >= dig__fread_port_O(&(ptr->Volume_offset), 1, fp, ptr->off_t_size))
681 return (-1);
682 if (0 >= dig__fread_port_O(&(ptr->Hole_offset), 1, fp, ptr->off_t_size))
683 return (-1);
684
685 /* bytes 139 - 142 : Coor size and time */
686 if (0 >= dig__fread_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
687 return (-1);
688
689 G_debug(2, " coor size %" PRId64, ptr->coor_size);
690
691 dig_fseek(fp, ptr->head_size, SEEK_SET);
692
693 return (0);
694}
695
696/*!
697 \brief Write Plus_head to file
698
699 ptr->off_t_size is used for both coor and topo files, but their sizes
700 (ptr->coor_size for coor and no variable for topo) can be different. If
701 either file is greater than PORT_LONG_MAX, ptr->off_t_size must be 8. This
702 function determines this value of ptr->off_t_size and writes it to the file.
703
704 \param fp pointer to gvfile structure
705 \param[in,out] ptr pointer to Plus_head structure
706
707 \return -1 error
708 \return 0 OK
709 */
710int dig_Wr_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
711{
712 unsigned char buf[10];
713 long length = 142;
714
715 dig_rewind(fp);
716 dig_set_cur_port(&(ptr->port));
717
718 /* bytes 1 - 5 */
719 buf[0] = GV_TOPO_VER_MAJOR;
720 buf[1] = GV_TOPO_VER_MINOR;
721 buf[2] = GV_TOPO_EARLIEST_MAJOR;
722 buf[3] = GV_TOPO_EARLIEST_MINOR;
723 buf[4] = ptr->port.byte_order;
724 if (0 >= dig__fwrite_port_C((char *)buf, 5, fp))
725 return (-1);
726
727 /* determine required offset size from coor file size */
728 if (ptr->coor_size > (off_t)PORT_LONG_MAX) {
729 /* can only happen when sizeof(off_t) == 8 */
730 ptr->off_t_size = 8;
731 }
732 else if (ptr->off_t_size == 0) {
733 /* calculate the total size of topo file to get the correct off_t_size
734 * if coor file is less than PORT_LONG_MAX */
735 off_t size = length;
736 int i;
737
738 for (i = 1; i <= ptr->n_nodes; i++) {
739 /* from dig_Wr_P_node() */
740 struct P_node *p = ptr->Node[i];
741
742 if (p == NULL)
743 size += 4;
744 else {
745 size += 20 + 8 * p->n_lines;
746 if (ptr->with_z)
747 size += 12;
748 }
749 }
750
751 for (i = 1; i <= ptr->n_lines; i++) {
752 /* from dig_Wr_P_line() */
753 struct P_line *p = ptr->Line[i];
754
755 if (p == NULL)
756 size += 1;
757 else {
758 /* for now, off_t_size = 4 */
759 size += 5;
760 if (p->type & GV_CENTROID)
761 size += 4;
762 else if (p->type & GV_LINE)
763 size += 8;
764 else if (p->type & GV_BOUNDARY)
765 size += 16;
766 else if ((p->type & GV_FACE) && ptr->with_z)
767 size += 12;
768 else if ((p->type & GV_KERNEL) && ptr->with_z)
769 size += 4;
770 }
771 }
772
773 for (i = 1; i <= ptr->n_areas; i++) {
774 /* from dig_Wr_P_area() */
775 struct P_area *p = ptr->Area[i];
776
777 if (p == NULL)
778 size += 4;
779 else
780 size += 12 + 4 * p->n_lines + 4 * p->n_isles;
781 }
782
783 for (i = 1; i <= ptr->n_isles; i++) {
784 /* from dig_Wr_P_isle() */
785 struct P_isle *p = ptr->Isle[i];
786
787 if (p == NULL)
788 size += 4;
789 else
790 size += 8 + 4 * p->n_lines;
791 }
792
793 ptr->off_t_size = size > (off_t)PORT_LONG_MAX ? 8 : 4;
794 }
795
796 /* add a new field with off_t_size after byte_order? */
797
798 /* adjust header size for large files */
799 if (ptr->off_t_size == 8) {
800 /* 7 offset values and coor file size: add 8 * 4 */
801 length += 32;
802 }
803
804 /* bytes 6 - 9 : header size */
805 if (0 >= dig__fwrite_port_L(&length, 1, fp))
806 return (0);
807
808 /* byte 10 : dimension 2D or 3D */
809 buf[0] = ptr->with_z;
810 if (0 >= dig__fwrite_port_C((char *)buf, 1, fp))
811 return (0);
812
813 /* bytes 11 - 58 : bound box */
814 if (0 >= dig__fwrite_port_D(&(ptr->box.N), 1, fp))
815 return (-1);
816 if (0 >= dig__fwrite_port_D(&(ptr->box.S), 1, fp))
817 return (-1);
818 if (0 >= dig__fwrite_port_D(&(ptr->box.E), 1, fp))
819 return (-1);
820 if (0 >= dig__fwrite_port_D(&(ptr->box.W), 1, fp))
821 return (-1);
822 if (0 >= dig__fwrite_port_D(&(ptr->box.T), 1, fp))
823 return (-1);
824 if (0 >= dig__fwrite_port_D(&(ptr->box.B), 1, fp))
825 return (-1);
826
827 /* bytes 59 - 86 : number of structures */
828 if (0 >= dig__fwrite_port_P(&(ptr->n_nodes), 1, fp))
829 return (-1);
830 if (0 >= dig__fwrite_port_P(&(ptr->n_edges), 1, fp))
831 return (-1);
832 if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
833 return (-1);
834 if (0 >= dig__fwrite_port_P(&(ptr->n_areas), 1, fp))
835 return (-1);
836 if (0 >= dig__fwrite_port_P(&(ptr->n_isles), 1, fp))
837 return (-1);
838 if (0 >= dig__fwrite_port_P(&(ptr->n_volumes), 1, fp))
839 return (-1);
840 if (0 >= dig__fwrite_port_P(&(ptr->n_holes), 1, fp))
841 return (-1);
842
843 /* bytes 87 - 110 : number of line types */
844 if (0 >= dig__fwrite_port_P(&(ptr->n_plines), 1, fp))
845 return (-1);
846 if (0 >= dig__fwrite_port_P(&(ptr->n_llines), 1, fp))
847 return (-1);
848 if (0 >= dig__fwrite_port_P(&(ptr->n_blines), 1, fp))
849 return (-1);
850 if (0 >= dig__fwrite_port_P(&(ptr->n_clines), 1, fp))
851 return (-1);
852 if (0 >= dig__fwrite_port_P(&(ptr->n_flines), 1, fp))
853 return (-1);
854 if (0 >= dig__fwrite_port_P(&(ptr->n_klines), 1, fp))
855 return (-1);
856
857 /* bytes 111 - 138 : Offset */
858 if (0 >= dig__fwrite_port_O(&(ptr->Node_offset), 1, fp, ptr->off_t_size))
859 return (-1);
860 if (0 >= dig__fwrite_port_O(&(ptr->Edge_offset), 1, fp, ptr->off_t_size))
861 return (-1);
862 if (0 >= dig__fwrite_port_O(&(ptr->Line_offset), 1, fp, ptr->off_t_size))
863 return (-1);
864 if (0 >= dig__fwrite_port_O(&(ptr->Area_offset), 1, fp, ptr->off_t_size))
865 return (-1);
866 if (0 >= dig__fwrite_port_O(&(ptr->Isle_offset), 1, fp, ptr->off_t_size))
867 return (-1);
868 if (0 >= dig__fwrite_port_O(&(ptr->Volume_offset), 1, fp, ptr->off_t_size))
869 return (-1);
870 if (0 >= dig__fwrite_port_O(&(ptr->Hole_offset), 1, fp, ptr->off_t_size))
871 return (-1);
872
873 /* bytes 139 - 142 : Coor size and time */
874 if (0 >= dig__fwrite_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
875 return (-1);
876
877 G_debug(2, "topo body offset %" PRId64, dig_ftell(fp));
878
879 return (0);
880}
#define NULL
Definition ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_TOPO_EARLIEST_MAJOR
#define GV_TOPO_EARLIEST_MINOR
#define GV_CENTROID
#define GV_TOPO_VER_MINOR
#define GV_LINE
#define GV_POINT
Feature types used in memory on run time (may change)
#define PORT_LONG_MAX
Definition dig_defines.h:70
#define GV_BOUNDARY
#define GV_TOPO_VER_MAJOR
#define GV_FACE
#define GV_KERNEL
int dig__fread_port_D(double *, size_t, struct gvfile *)
Read doubles from the Portable Vector Format.
Definition portable.c:79
int dig__fread_port_O(off_t *, size_t, struct gvfile *, size_t)
Read off_ts from the Portable Vector Format.
Definition portable.c:167
void dig_free_line(struct P_line *)
Free line structure.
void dig_free_node(struct P_node *)
Free node structure.
int dig__fwrite_port_C(const char *, size_t, struct gvfile *)
Write chars to the Portable Vector Format.
Definition portable.c:886
struct P_node * dig_alloc_node(void)
Allocate new node structure.
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
Definition portable.c:900
int dig__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
Definition portable.c:262
int dig__fread_port_F(float *, size_t, struct gvfile *)
Read floats from the Portable Vector Format.
Definition portable.c:123
int dig__fwrite_port_L(const long *, size_t, struct gvfile *)
Write longs to the Portable Vector Format.
Definition portable.c:703
int dig__fwrite_port_I(const int *, size_t, struct gvfile *)
Write integers to the Portable Vector Format.
Definition portable.c:758
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition file.c:36
int dig__fwrite_port_F(const float *, size_t, struct gvfile *)
Write floats to the Portable Vector Format.
Definition portable.c:597
void * dig_alloc_topo(char)
Allocate new topo struct.
struct P_line * dig_alloc_line(void)
Allocate new line structure.
int dig_area_alloc_isle(struct P_area *, int)
Allocate space in P_area for add new isles.
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition portable.c:996
int dig__fwrite_port_D(const double *, size_t, struct gvfile *)
Write doubles to the Portable Vector Format.
Definition portable.c:559
void dig_rewind(struct gvfile *file)
Rewind file position.
Definition file.c:87
int dig_node_alloc_line(struct P_node *, int)
Allocate space in P_node struct.
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition portable.c:511
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition portable.c:345
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition file.c:60
void dig_free_area(struct P_area *)
Free area structure.
int dig_type_from_store(int)
Convert type from store type.
struct P_isle * dig_alloc_isle(void)
Allocate new isle structure.
struct P_area * dig_alloc_area(void)
Allocate new area structure.
int dig__fread_port_P(plus_t *, size_t, struct gvfile *)
Read plus_t from the Portable Vector Format.
Definition portable.c:537
int dig_isle_alloc_line(struct P_isle *, int)
Allocate space in P_isle for add new lines.
int dig_area_alloc_line(struct P_area *, int)
allocate space in P_area for add new lines
void dig_free_isle(struct P_isle *)
Free isle structure.
int dig__fwrite_port_O(const off_t *, size_t, struct gvfile *, size_t)
Write off_ts to the Portable Vector Format.
Definition portable.c:636
int dig__fwrite_port_P(const plus_t *, size_t, struct gvfile *)
Write plus_t to the Portable Vector Format.
Definition portable.c:868
int dig_type_to_store(int)
Convert type to store type.
#define _(str)
Definition glocale.h:10
int dig_Rd_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
Read Plus_head from file.
int dig_Rd_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition plus_struct.c:51
int dig_Wr_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
int dig_Rd_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
int dig_Wr_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
int dig_Rd_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
int dig_Rd_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
int dig_Wr_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
Write Plus_head to file.
int dig_Wr_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
int dig_Wr_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
Area (topology) info.
plus_t n_isles
Number of islands inside.
plus_t * isles
1st generation interior islands
plus_t n_lines
Number of boundary lines.
plus_t * lines
List of boundary lines.
plus_t centroid
Number of first centroid within area.
Isle (topology) info.
plus_t * lines
List of boundary lines.
plus_t n_lines
Number of boundary lines.
plus_t area
Area it exists w/in, if any.
Vector geometry.
char type
Line type.
off_t offset
Offset in coor file for line.
void * topo
Topology info.
Topological feature - node.
double x
X coordinate.
plus_t n_lines
Number of attached lines (size of lines, angle)
float * angles
List of angles of connected lines.
plus_t * lines
List of connected lines.
double z
Z coordinate (used only for 3D data)
double y
Y coordinate.
Boundary topology.
plus_t left
Area number to the left, negative for isle.
plus_t N1
Start node.
plus_t N2
End node.
plus_t right
Area number to the right, negative for isle.
Centroid topology.
plus_t area
Area number, negative for duplicate centroid.
Face topology.
plus_t left
Volume number to the left, negative for hole.
plus_t right
Volume number to the right, negative for hole.
Kernel topology.
plus_t volume
Volume number, negative for duplicate kernel.
Line topology.
plus_t N1
Start node.
plus_t N2
End node.
Basic topology-related info.
off_t Hole_offset
Offset of array of holes in topo file.
plus_t n_klines
Current number of kernels.
off_t Isle_offset
Offset of array of isles in topo file.
off_t Node_offset
Offset of array of nodes in topo file.
int with_z
2D/3D vector data
off_t coor_size
Size of coor file.
struct Plus_head::@9 version
Backward compatibility version info.
struct P_line ** Line
Array of vector geometries.
plus_t n_lines
Current number of lines.
off_t Volume_offset
Offset of array of volumes in topo file.
plus_t n_plines
Current number of points.
off_t Area_offset
Offset of array of areas in topo file.
int off_t_size
Offset size.
plus_t n_nodes
Current number of topological features derived from vector geometries.
plus_t n_volumes
Current number of volumes.
plus_t n_blines
Current number of boundaries.
struct P_area ** Area
Array of areas.
long head_size
Topo header size.
plus_t n_clines
Current number of centroids.
plus_t n_isles
Current number of isles.
plus_t n_holes
Current number of holes.
off_t Edge_offset
Offset of array of edges in topo file.
struct bound_box box
Bounding box of features.
plus_t n_edges
Current number of edges.
struct P_isle ** Isle
Array of isles.
struct P_node ** Node
Array of nodes.
struct Port_info port
Portability information.
plus_t n_areas
Current number of areas.
plus_t n_flines
Current number of faces.
off_t Line_offset
Offset of array of vector geometries in topo file.
plus_t n_llines
Current number of lines.
File definition.
Definition dig_structs.h:92
#define GRASS_VERSION_MINOR
Definition version.h:3
#define GRASS_VERSION_MAJOR
Definition version.h:2