/*! \file read_nat.c \brief Vector library - reading data (native format) Higher level functions for reading/writing/manipulating vectors. The action of this routine can be modified by: - Vect_read_constraint_region() - Vect_read_constraint_type() - Vect_remove_constraints() (C) 2001-2009 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. \author Original author CERL, probably Dave Gerdes or Mike Higgins. \author Update to GRASS 5.7 Radim Blazek and David D. Gray. */ #include #include #include #include #include static int Vect__Read_line_nat(struct Map_info *, struct line_pnts *, struct line_cats *, off_t); /*! * \brief Read line from coor file on given offset. * * \param Map vector map * \param[out] Points container used to store line points within * \param[out] Cats container used to store line categories within * \param offset given offset * * \return line type * \return 0 dead line * \return -2 end of table (last row) * \return -1 out of memory */ int V1_read_line_nat(struct Map_info *Map, struct line_pnts *Points, struct line_cats *Cats, off_t offset) { return Vect__Read_line_nat(Map, Points, Cats, offset); } /*! * \brief Read next line from coor file. * * \param Map vector map layer * \param[out] line_p container used to store line points within * \param[out] line_c container used to store line categories within * * \return line type * \return 0 dead line * \return -2 end of table (last row) * \return -1 out of memory */ int V1_read_next_line_nat(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c) { int itype; off_t offset; struct bound_box lbox, mbox; G_debug(3, "V1_read_next_line_nat()"); if (Map->Constraint_region_flag) Vect_get_constraint_box(Map, &mbox); while (1) { offset = dig_ftell(&(Map->dig_fp)); itype = Vect__Read_line_nat(Map, line_p, line_c, offset); if (itype < 0) return (itype); if (itype == 0) /* is it DEAD? */ continue; /* Constraint on Type of line * Default is all of Point, Line, Area and whatever else comes along */ if (Map->Constraint_type_flag) { if (!(itype & Map->Constraint_type)) continue; } /* Constraint on specified region */ if (Map->Constraint_region_flag) { Vect_line_box(line_p, &lbox); if (!Vect_box_overlap(&lbox, &mbox)) continue; } return (itype); } /* NOTREACHED */ } /*! * \brief Reads any specified line, this is NOT affected by constraints * * \param Map vector map layer * \param[out] line_p container used to store line points within * \param[out] line_c container used to store line categories within * \param line line id * * \return line type ( > 0 ) * \return 0 dead line * \return -1 out of memory * \return -2 end of file */ int V2_read_line_nat(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line) { struct P_line *Line; G_debug(3, "V2_read_line_nat(): line = %d", line); Line = Map->plus.Line[line]; if (Line == NULL) G_fatal_error("V2_read_line_nat(): %s %d", _("Attempt to read dead line"), line); return Vect__Read_line_nat(Map, line_p, line_c, Line->offset); } /*! * \brief Reads next unread line each time called. Use Vect_rewind to reset. * * \param Map vector map layer * \param[out] line_p container used to store line points within * \param[out] line_c container used to store line categories within * * \return line type ( > 0 ) * \return 0 dead line * \return -1 out of memory * \return -2 end of file */ int V2_read_next_line_nat(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c) { register int line; register struct P_line *Line; struct bound_box lbox, mbox; G_debug(3, "V2_read_next_line_nat()"); if (Map->Constraint_region_flag) Vect_get_constraint_box(Map, &mbox); while (1) { line = Map->next_line; if (line > Map->plus.n_lines) return (-2); Line = Map->plus.Line[line]; if (Line == NULL) { /* Dead line */ Map->next_line++; continue; } if ((Map->Constraint_type_flag && !(Line->type & Map->Constraint_type))) { Map->next_line++; continue; } if (Map->Constraint_region_flag) { Vect_get_line_box(Map, line, &lbox); if (!Vect_box_overlap(&lbox, &mbox)) { Map->next_line++; continue; } } return V2_read_line_nat(Map, line_p, line_c, Map->next_line++); } /* NOTREACHED */ } /*! * \brief Read line from coor file * * \param Map vector map layer * \param[out] p container used to store line points within * \param[out] c container used to store line categories within * \param offset given offset * * \return line type ( > 0 ) * \return 0 dead line * \return -1 out of memory * \return -2 end of file */ int Vect__Read_line_nat(struct Map_info *Map, struct line_pnts *p, struct line_cats *c, off_t offset) { int i, dead = 0; int n_points; off_t size; int n_cats, do_cats; int type; char rhead, nc; short field; G_debug(3, "Vect__Read_line_nat: offset = %lu", (unsigned long) offset); Map->head.last_offset = offset; /* reads must set in_head, but writes use default */ dig_set_cur_port(&(Map->head.port)); dig_fseek(&(Map->dig_fp), offset, 0); if (0 >= dig__fread_port_C(&rhead, 1, &(Map->dig_fp))) return (-2); if (!(rhead & 0x01)) /* dead line */ dead = 1; if (rhead & 0x02) /* categories exists */ do_cats = 1; /* do not return here let file offset moves forward to next */ else /* line */ do_cats = 0; rhead >>= 2; type = dig_type_from_store((int)rhead); G_debug(3, " type = %d, do_cats = %d dead = %d", type, do_cats, dead); if (c != NULL) c->n_cats = 0; if (do_cats) { if (Map->head.Version_Minor == 1) { /* coor format 5.1 */ if (0 >= dig__fread_port_I(&n_cats, 1, &(Map->dig_fp))) return (-2); } else { /* coor format 5.0 */ if (0 >= dig__fread_port_C(&nc, 1, &(Map->dig_fp))) return (-2); n_cats = (int)nc; } G_debug(3, " n_cats = %d", n_cats); if (c != NULL) { c->n_cats = n_cats; if (n_cats > 0) { if (0 > dig_alloc_cats(c, (int)n_cats + 1)) return (-1); if (Map->head.Version_Minor == 1) { /* coor format 5.1 */ if (0 >= dig__fread_port_I(c->field, n_cats, &(Map->dig_fp))) return (-2); } else { /* coor format 5.0 */ for (i = 0; i < n_cats; i++) { if (0 >= dig__fread_port_S(&field, 1, &(Map->dig_fp))) return (-2); c->field[i] = (int)field; } } if (0 >= dig__fread_port_I(c->cat, n_cats, &(Map->dig_fp))) return (-2); } } else { if (Map->head.Version_Minor == 1) { /* coor format 5.1 */ size = (off_t) (2 * PORT_INT) * n_cats; } else { /* coor format 5.0 */ size = (off_t) (PORT_SHORT + PORT_INT) * n_cats; } dig_fseek(&(Map->dig_fp), size, SEEK_CUR); } } if (type & GV_POINTS) { n_points = 1; } else { if (0 >= dig__fread_port_I(&n_points, 1, &(Map->dig_fp))) return (-2); } G_debug(3, " n_points = %d", n_points); if (p != NULL) { if (0 > dig_alloc_points(p, n_points + 1)) return (-1); p->n_points = n_points; if (0 >= dig__fread_port_D(p->x, n_points, &(Map->dig_fp))) return (-2); if (0 >= dig__fread_port_D(p->y, n_points, &(Map->dig_fp))) return (-2); if (Map->head.with_z) { if (0 >= dig__fread_port_D(p->z, n_points, &(Map->dig_fp))) return (-2); } else { for (i = 0; i < n_points; i++) p->z[i] = 0.0; } } else { if (Map->head.with_z) size = (off_t) n_points * 3 * PORT_DOUBLE; else size = (off_t) n_points * 2 * PORT_DOUBLE; dig_fseek(&(Map->dig_fp), size, SEEK_CUR); } G_debug(3, " off = %lu", (unsigned long) dig_ftell(&(Map->dig_fp))); if (dead) return 0; return (type); }