123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- /**
- * \file plus_line.c
- *
- * \brief Vector library - update topo for lines (lower level functions)
- *
- * Lower level functions for reading/writing/manipulating vectors.
- *
- * This program is free software under the GNU General Public License
- * (>=v2). Read the file COPYING that comes with GRASS for details.
- *
- * \author CERL (probably Dave Gerdes), Radim Blazek
- *
- * \date 2001-2008
- */
- #include <sys/types.h>
- #include <stdlib.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- static int add_line(struct Plus_head *plus, int lineid, int type, const struct line_pnts *Points,
- const struct bound_box *box, off_t offset)
- {
- int node, lp, node_new;
- struct P_line *line;
- plus->Line[lineid] = dig_alloc_line();
- line = plus->Line[lineid];
- line->type = type;
- line->offset = offset;
- dig_spidx_add_line(plus, lineid, box);
- if (plus->uplist.do_uplist) {
- dig_line_add_updated(plus, lineid, offset);
- }
-
- if (type & GV_POINT) {
- line->topo = NULL;
- return (lineid);
- }
-
- line->topo = dig_alloc_topo(type);
- if (type & GV_CENTROID) {
- struct P_topo_c *topo = (struct P_topo_c *)line->topo;
- topo->area = 0;
- return (lineid);
- }
- /* Add nodes for lines */
- G_debug(3, "Register node: type = %d, %f,%f", type, Points->x[0],
- Points->y[0]);
- /* Start node */
- node = dig_find_node(plus, Points->x[0], Points->y[0], Points->z[0]);
- G_debug(3, "node = %d", node);
- if (node == 0) {
- node = dig_add_node(plus, Points->x[0], Points->y[0], Points->z[0]);
- G_debug(3, "Add new node: %d", node);
- node_new = TRUE;
- }
- else {
- G_debug(3, "Old node found: %d", node);
- node_new = FALSE;
- }
-
- if (type == GV_LINE) {
- struct P_topo_l *topo = (struct P_topo_l *)line->topo;
- topo->N1 = node;
- topo->N2 = 0;
- }
- else if (type == GV_BOUNDARY) {
- struct P_topo_b *topo = (struct P_topo_b *)line->topo;
- topo->N1 = node;
- topo->N2 = 0;
- topo->left = 0;
- topo->right = 0;
- }
- dig_node_add_line(plus, node, lineid, Points, type);
- if (plus->uplist.do_uplist)
- dig_node_add_updated(plus, node_new ? -node : node);
- /* End node */
- lp = Points->n_points - 1;
- G_debug(3, "Register node %f,%f", Points->x[lp], Points->y[lp]);
- node = dig_find_node(plus, Points->x[lp], Points->y[lp],
- Points->z[lp]);
- G_debug(3, "node = %d", node);
- if (node == 0) {
- node = dig_add_node(plus, Points->x[lp], Points->y[lp],
- Points->z[lp]);
- G_debug(3, "Add new node: %d", node);
- node_new = TRUE;
- }
- else {
- G_debug(3, "Old node found: %d", node);
- node_new = FALSE;
- }
- if (type == GV_LINE) {
- struct P_topo_l *topo = (struct P_topo_l *)line->topo;
- topo->N2 = node;
- }
- else if (type == GV_BOUNDARY) {
- struct P_topo_b *topo = (struct P_topo_b *)line->topo;
- topo->N2 = node;
- }
- dig_node_add_line(plus, node, -lineid, Points, type);
- if (plus->uplist.do_uplist)
- dig_node_add_updated(plus, node_new ? -node : node);
- return (lineid);
- }
- /*!
- * \brief Add new line to Plus_head structure.
- *
- * \param[in,out] plus pointer to Plus_head structure
- * \param type feature type
- * \param Points line geometry
- * \param box bounding box
- * \param offset line offset
- *
- * \return -1 on error
- * \return line id
- */
- int
- dig_add_line(struct Plus_head *plus, int type, const struct line_pnts *Points,
- const struct bound_box *box, off_t offset)
- {
- int ret;
-
- /* First look if we have space in array of pointers to lines
- * and reallocate if necessary */
- if (plus->n_lines >= plus->alloc_lines) { /* array is full */
- if (dig_alloc_lines(plus, 1000) == -1)
- return -1;
- }
- ret = add_line(plus, plus->n_lines + 1, type, Points, box, offset);
- if (ret == -1)
- return ret;
- plus->n_lines++;
- switch (type) {
- case GV_POINT:
- plus->n_plines++;
- break;
- case GV_LINE:
- plus->n_llines++;
- break;
- case GV_BOUNDARY:
- plus->n_blines++;
- break;
- case GV_CENTROID:
- plus->n_clines++;
- break;
- case GV_FACE:
- plus->n_flines++;
- break;
- case GV_KERNEL:
- plus->n_klines++;
- break;
- }
- return ret;
- }
- /*!
- * \brief Restore line in Plus_head structure.
- *
- * \param[in,out] plus pointer to Plus_head structure
- * \param type feature type
- * \param Points line geometry
- * \param box bounding box
- * \param offset line offset
- *
- * \return -1 on error
- * \return line id
- */
- int
- dig_restore_line(struct Plus_head *plus, int lineid,
- int type, const struct line_pnts *Points,
- const struct bound_box *box, off_t offset)
- {
- if (lineid < 1 || lineid > plus->n_lines) {
- return -1;
- }
- return add_line(plus, lineid, type, Points, box, offset);
- }
- /*!
- * \brief Delete line from Plus_head structure.
- *
- * Doesn't update area/isle references (dig_del_area() or dig_del_isle()) must be
- * run before the line is deleted if the line is part of such
- * structure). Update is info about line in nodes. If this line is
- * last in node then node is deleted.
- *
- * \param[in,out] plus pointer to Plus_head structure
- * \param[in] line line id
- * \param[in] x,y,z coordinates
- *
- * \return -1 on error
- * \return 0 OK
- *
- */
- int dig_del_line(struct Plus_head *plus, int line, double x, double y, double z)
- {
- int i;
- plus_t N1 = 0, N2 = 0;
- struct P_line *Line;
- struct P_node *Node;
- G_debug(3, "dig_del_line() line = %d", line);
- Line = plus->Line[line];
- dig_spidx_del_line(plus, line, x, y, z);
- if (plus->uplist.do_uplist) {
- dig_line_add_updated(plus, line, -Line->offset);
- }
-
- if (!(Line->type & GV_LINES)) {
- /* Delete line */
- dig_free_line(Line);
- plus->Line[line] = NULL;
- return 0;
- }
- /* Delete from nodes (and nodes) */
- if (Line->type == GV_LINE) {
- struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
- N1 = topo->N1;
- }
- else if (Line->type == GV_BOUNDARY) {
- struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
- N1 = topo->N1;
- }
- Node = plus->Node[N1];
- i = 0;
- while (i < Node->n_lines && Node->lines[i] != line)
- i++;
- if (i == Node->n_lines) {
- G_fatal_error(_("Attempt to delete not registered line %d from node %d"),
- line, N1);
- }
- i++;
- while (i < Node->n_lines) {
- Node->lines[i - 1] = Node->lines[i];
- Node->angles[i - 1] = Node->angles[i];
- i++;
- }
- Node->n_lines--;
- if (plus->uplist.do_uplist) {
- dig_node_add_updated(plus, Node->n_lines > 0 ? N1 : -N1);
- }
- if (Node->n_lines == 0) {
- G_debug(3, " node %d has 0 lines -> delete", N1);
- dig_spidx_del_node(plus, N1);
- /* free structures */
- dig_free_node(Node);
- plus->Node[N1] = NULL;
- }
-
- if (Line->type == GV_LINE) {
- struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
- N2 = topo->N2;
- }
- else if (Line->type == GV_BOUNDARY) {
- struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
- N2 = topo->N2;
- }
- Node = plus->Node[N2];
- i = 0;
- while (i < Node->n_lines && Node->lines[i] != -line)
- i++;
- if (i == Node->n_lines) {
- G_fatal_error(_("Attempt to delete not registered line %d from node %d"),
- -line, N2);
- }
- i++;
- while (i < Node->n_lines) {
- Node->lines[i - 1] = Node->lines[i];
- Node->angles[i - 1] = Node->angles[i];
- i++;
- }
- Node->n_lines--;
- if (plus->uplist.do_uplist) {
- dig_node_add_updated(plus, Node->n_lines > 0 ? N2 : -N2);
- }
- if (Node->n_lines == 0) {
- G_debug(3, " node %d has 0 lines -> delete", N2);
- dig_spidx_del_node(plus, N2);
- /* free structures */
- dig_free_node(Node);
- plus->Node[N2] = NULL;
- }
- /* Delete line */
- dig_free_line(Line);
- plus->Line[line] = NULL;
- return 0;
- }
- /*!
- * \brief Get area number on line side.
- *
- * \param[in] plus pointer Plus_head structure
- * \param[in] line line id
- * \param[in] side side id (GV_LEFT || GV_RIGHT)
- *
- * \return area number
- * \return 0 no area
- * \return -1 on error
- */
- plus_t dig_line_get_area(struct Plus_head * plus, plus_t line, int side)
- {
- struct P_line *Line;
- struct P_topo_b *topo;
- Line = plus->Line[line];
- if (!Line) /* dead */
- return -1;
-
- if (Line->type != GV_BOUNDARY)
- return -1;
- topo = (struct P_topo_b *)Line->topo;
- if (side == GV_LEFT) {
- G_debug(3,
- "dig_line_get_area(): line = %d, side = %d (left), area = %d",
- line, side, topo->left);
- return (topo->left);
- }
- if (side == GV_RIGHT) {
- G_debug(3,
- "dig_line_get_area(): line = %d, side = %d (right), area = %d",
- line, side, topo->right);
- return (topo->right);
- }
- return (-1);
- }
- /*!
- * \brief Set area number on line side
- *
- * \param[in] plus pointer Plus_head structure
- * \param[in] line line id
- * \param[in] side side id (GV_LEFT || GV_RIGHT)
- * \param[in] area area id
- *
- * \return 1
- */
- int
- dig_line_set_area(struct Plus_head *plus, plus_t line, int side, plus_t area)
- {
- struct P_line *Line;
- struct P_topo_b *topo;
- Line = plus->Line[line];
- if (Line->type != GV_BOUNDARY)
- return (0);
- topo = (struct P_topo_b *)Line->topo;
- if (side == GV_LEFT) {
- topo->left = area;
- }
- else if (side == GV_RIGHT) {
- topo->right = area;
- }
- return (1);
- }
- /*!
- * \brief Set line bounding box
- *
- * \param[in] plus pointer Plus_head structure
- * \param[in] line line id
- * \param[in] Box bounding box
- *
- * \return 1
- */
- /*
- int dig_line_set_box(struct Plus_head *plus, plus_t line, struct bound_box * Box)
- {
- struct P_line *Line;
- Line = plus->Line[line];
- Line->N = Box->N;
- Line->S = Box->S;
- Line->E = Box->E;
- Line->W = Box->W;
- Line->T = Box->T;
- Line->B = Box->B;
- return (1);
- }
- */
- /*!
- * \brief Get line bounding box saved in topo
- *
- * \param[in] plus pointer Plus_head structure
- * \param[in] line line id
- * \param[in,out] Box bounding box
- *
- * \return 1
- */
- /*
- int dig_line_get_box(struct Plus_head *plus, plus_t line, struct bound_box * Box)
- {
- struct P_line *Line;
- Line = plus->Line[line];
- Box->N = Line->N;
- Box->S = Line->S;
- Box->E = Line->E;
- Box->W = Line->W;
- Box->T = Line->T;
- Box->B = Line->B;
- return (1);
- }
- */
|