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