Ejemplo n.º 1
0
/* Check if point is inside area with category of given field. All cats are set in 
 * Cats with original field.
 * returns number of cats.
 */
int point_area(struct Map_info *Map, int field, double x, double y,
	       struct line_cats *Cats)
{
    int i, area, centr;
    static struct line_cats *CCats = NULL;

    Vect_reset_cats(Cats);
    area = Vect_find_area(Map, x, y);
    G_debug(4, "  area = %d", area);

    if (!area)
	return 0;

    centr = Vect_get_area_centroid(Map, area);

    if (centr <= 0)
	return 0;

    if (!CCats)
	CCats = Vect_new_cats_struct();
    Vect_read_line(Map, NULL, CCats, centr);

    for (i = 0; i < CCats->n_cats; i++) {
	if (CCats->field[i] == field) {
	    Vect_cat_set(Cats, field, CCats->cat[i]);
	}
    }

    return Cats->n_cats;
}
Ejemplo n.º 2
0
/*!
   \brief Calculates z coordinate for point from TIN

   \param Map pointer to vector map
   \param tx,ty point coordinates
   \param[out] tz z-coordinate of point
   \param[out] angle angle
   \param[out] slope slope

   \return 1 on success,
   \return 0 point is not in area,
   \return -1 area has not 4 points or has island
 */
int
Vect_tin_get_z(struct Map_info *Map,
	       double tx, double ty, double *tz, double *angle, double *slope)
{
    int i, area, n_points;
    struct Plus_head *Plus;
    P_AREA *Area;
    static struct line_pnts *Points;
    static int first_time = 1;
    double *x, *y, *z;
    double vx1, vx2, vy1, vy2, vz1, vz2;
    double a, b, c, d;

    /* TODO angle, slope */

    Plus = &(Map->plus);
    if (first_time == 1) {
	Points = Vect_new_line_struct();
	first_time = 0;
    }

    area = Vect_find_area(Map, tx, ty);
    G_debug(3, "TIN: area = %d", area);
    if (area == 0)
	return 0;

    Area = Plus->Area[area];
    if (Area->n_isles > 0)
	return -1;

    Vect_get_area_points(Map, area, Points);
    n_points = Points->n_points;
    if (n_points != 4)
	return -1;

    x = Points->x;
    y = Points->y;
    z = Points->z;
    for (i = 0; i < 3; i++) {
	G_debug(3, "TIN: %d %f %f %f", i, x[i], y[i], z[i]);
    }

    vx1 = x[1] - x[0];
    vy1 = y[1] - y[0];
    vz1 = z[1] - z[0];
    vx2 = x[2] - x[0];
    vy2 = y[2] - y[0];
    vz2 = z[2] - z[0];

    a = vy1 * vz2 - vy2 * vz1;
    b = vz1 * vx2 - vz2 * vx1;
    c = vx1 * vy2 - vx2 * vy1;
    d = -a * x[0] - b * y[0] - c * z[0];

    /* OK ? */
    *tz = -(d + a * tx + b * ty) / c;
    G_debug(3, "TIN: z = %f", *tz);

    return 1;
}
Ejemplo n.º 3
0
/*!
   \brief (Re)Attach centroids in given bounding box to areas

    Warning: If map is updated on level2, it may happen that
    previously correct island becomes incorrect. In that case,
    centroid of area forming the island is reattached to outer area,
    because island polygon is not excluded.
     
    <pre>
      +-----------+     +-----------+
      |   1       |     |   1       |
      | +---+---+ |     | +---+---+ |     
      | | 2 | 3 | |     | | 2 |     |   
      | | x |   | |  -> | | x |     |  
      | |   |   | |     | |   |     | 
      | +---+---+ |     | +---+---+ |
      |           |     |           |
      +-----------+     +-----------+
      centroid is       centroid is
      attached to 2     reattached to 1
    </pre>

    Because of this, when the centroid is reattached to another area,
    it is always necessary to check if original area exist, unregister
    centroid from previous area.  To simplify code, this is
    implemented so that centroid is always first unregistered and if
    new area is found, it is registered again.

   \param Map vector map
   \param box bounding box

   \return 0
 */
int Vect_attach_centroids(struct Map_info *Map, const struct bound_box * box)
{
    int i, area, centr;
    static int first = 1;
    struct bound_box abox;
    static struct boxlist *List;
    struct P_area *Area;
    struct P_line *Line;
    struct P_topo_c *topo;
    struct Plus_head *plus;

    G_debug(3, "Vect_attach_centroids()");

    plus = &(Map->plus);

    if (first) {
	List = Vect_new_boxlist(1);
	first = 0;
    }

    Vect_select_lines_by_box(Map, box, GV_CENTROID, List);
    G_debug(3, "\tnumber of centroids to reattach = %d", List->n_values);
    for (i = 0; i < List->n_values; i++) {

	centr = List->id[i];
	Line = plus->Line[centr];
	topo = (struct P_topo_c *)Line->topo;

	area = topo->area;

	if (area > 0) {
	    /* if the area box is not fully inside the box, detach
	     * this might detach more than needed, 
	     * but all that need to be reattached and
	     * is faster than reattaching all */
	    Vect_get_area_box(Map, area, &abox);
	    if (box->W < abox.W && box->E > abox.E &&
	        box->S < abox.S && box->N > abox.N) {
		G_debug(3, "Centroid's area is fully inside search box");
	    }
	    else {
		Area = plus->Area[area];
		Area->centroid = 0;
		topo->area = 0;
		area = 0;
	    }
	}

	if (area > 0) {
	    continue;
	}

	area = Vect_find_area(Map, List->box[i].E, List->box[i].N);
	G_debug(3, "\tcentroid %d is in area %d", centr, area);
	if (area > 0) {
	    Area = plus->Area[area];
	    if (Area->centroid == 0) {	/* first centroid */
		G_debug(3, "\tfirst centroid -> attach to area");
		Area->centroid = centr;
		topo->area = area;
	    }
	    else if (Area->centroid != centr) {	/* duplicate centroid */
		/* Note: it cannot happen that Area->centroid == centr, because the centroid
		 * was not registered or a duplicate */
		G_debug(3, "\tduplicate centroid -> do not attach to area");
		topo->area = -area;
	    }
	}
    }

    return 0;
}
Ejemplo n.º 4
0
int area_area(struct Map_info *In, int *field, struct Map_info *Tmp,
	      struct Map_info *Out, struct field_info *Fi,
	      dbDriver * driver, int operator, int *ofield,
	      ATTRIBUTES * attr, struct ilist *BList, double snap)
{
    int ret, input, line, nlines, area, nareas;
    int in_area, in_centr, out_cat;
    struct line_pnts *Points;
    struct line_cats *Cats;
    CENTR *Centr;
    char buf[1000];
    dbString stmt;
    int nmodif;
    int verbose;

    verbose = G_verbose();

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    /* optional snap */
    if (snap > 0) {
	int i, j, snapped_lines = 0;
	struct bound_box box;
	struct boxlist *boxlist = Vect_new_boxlist(0);
	struct ilist *reflist = Vect_new_list();
	
	G_message(_("Snapping boundaries with %g ..."), snap);

	/* snap boundaries in B to boundaries in A,
	 * not modifying boundaries in A */

	if (BList->n_values > 1)
	    qsort(BList->value, BList->n_values, sizeof(int), cmp_int);

	snapped_lines = 0;
	nlines = BList->n_values;
	for (i = 0; i < nlines; i++) {
	    line = BList->value[i];
	    Vect_read_line(Tmp, Points, Cats, line);
	    /* select lines by box */
	    Vect_get_line_box(Tmp, line, &box);
	    box.E += snap;
	    box.W -= snap;
	    box.N += snap;
	    box.S -= snap;
	    box.T = 0.0;
	    box.B = 0.0;
	    Vect_select_lines_by_box(Tmp, &box, GV_BOUNDARY, boxlist);
	    
	    if (boxlist->n_values > 0) {
		Vect_reset_list(reflist);
		for (j = 0; j < boxlist->n_values; j++) {
		    int aline = boxlist->id[j];

		    if (!bsearch(&aline, BList->value, BList->n_values,
			sizeof(int), cmp_int)) {
			G_ilist_add(reflist, aline);
		    }
		}
		
		/* snap bline to alines */
		if (Vect_snap_line(Tmp, reflist, Points, snap, 0, NULL, NULL)) {
		    /* rewrite bline*/
		    Vect_delete_line(Tmp, line);
		    ret = Vect_write_line(Tmp, GV_BOUNDARY, Points, Cats);
		    G_ilist_add(BList, ret);
		    snapped_lines++;
		    G_debug(3, "line %d snapped", line);
		}
	    }
	}
	Vect_destroy_boxlist(boxlist);
	Vect_destroy_list(reflist);

	G_verbose_message(n_("%d boundary snapped",
                             "%d boundaries snapped",
                             snapped_lines), snapped_lines);
    }

    /* same procedure like for v.in.ogr:
     * Vect_clean_small_angles_at_nodes() can change the geometry so that new intersections
     * are created. We must call Vect_break_lines(), Vect_remove_duplicates()
     * and Vect_clean_small_angles_at_nodes() until no more small dangles are found */
    do {
	G_message(_("Breaking lines..."));
	Vect_break_lines_list(Tmp, NULL, BList, GV_BOUNDARY, NULL);

	/* Probably not necessary for LINE x AREA */
	G_message(_("Removing duplicates..."));
	Vect_remove_duplicates(Tmp, GV_BOUNDARY, NULL);

	G_message(_("Cleaning boundaries at nodes..."));
	nmodif =
	    Vect_clean_small_angles_at_nodes(Tmp, GV_BOUNDARY, NULL);
    } while (nmodif > 0);

    /* ?: May be result of Vect_break_lines() + Vect_remove_duplicates() any dangle or bridge?
     * In that case, calls to Vect_remove_dangles() and Vect_remove_bridges() would be also necessary */

    G_set_verbose(0);
    /* should be fast, be silent */
    Vect_build_partial(Tmp, GV_BUILD_AREAS);
    G_set_verbose(verbose);
    nlines = Vect_get_num_lines(Tmp);
    ret = 0;
    for (line = 1; line <= nlines; line++) {
	if (!Vect_line_alive(Tmp, line))
	    continue;
	if (Vect_get_line_type(Tmp, line) == GV_BOUNDARY) {
	    int left, rite;
	    
	    Vect_get_line_areas(Tmp, line, &left, &rite);
	    
	    if (left == 0 || rite == 0) {
		/* invalid boundary */
		ret = 1;
		break;
	    }
	}
    }
    if (ret) {
	Vect_remove_dangles(Tmp, GV_BOUNDARY, -1, NULL);
	Vect_remove_bridges(Tmp, NULL, NULL, NULL);
    }

    G_set_verbose(0);
    Vect_build_partial(Tmp, GV_BUILD_NONE);
    Vect_build_partial(Tmp, GV_BUILD_BASE);
    G_set_verbose(verbose);
    G_message(_("Merging lines..."));
    Vect_merge_lines(Tmp, GV_BOUNDARY, NULL, NULL);

    /* Attach islands */
    G_message(_("Attaching islands..."));
    /* can take some time, show messages */
    Vect_build_partial(Tmp, GV_BUILD_ATTACH_ISLES);

    /* Calculate new centroids for all areas */
    nareas = Vect_get_num_areas(Tmp);

    Centr = (CENTR *) G_malloc((nareas + 1) * sizeof(CENTR));	/* index from 1 ! */
    for (area = 1; area <= nareas; area++) {
	ret =
	    Vect_get_point_in_area(Tmp, area, &(Centr[area].x),
				   &(Centr[area].y));
	if (ret < 0) {
	    G_warning(_("Cannot calculate area centroid"));
	    Centr[area].valid = 0;
	}
	else {
	    Centr[area].valid = 1;
	}
    }

    /* Query input maps */
    for (input = 0; input < 2; input++) {
	G_message(_("Querying vector map <%s>..."),
		  Vect_get_full_name(&(In[input])));

	for (area = 1; area <= nareas; area++) {
	    Centr[area].cat[input] = Vect_new_cats_struct();

	    G_percent(area, nareas, 1);

	    in_area =
		Vect_find_area(&(In[input]), Centr[area].x, Centr[area].y);
	    if (in_area > 0) {
		in_centr = Vect_get_area_centroid(&(In[input]), in_area);
		if (in_centr > 0) {
		    int i;

		    Vect_read_line(&(In[input]), NULL, Cats, in_centr);
		    /* Add all cats with original field number */
		    for (i = 0; i < Cats->n_cats; i++) {
			if (Cats->field[i] == field[input]) {
			    ATTR *at;

			    Vect_cat_set(Centr[area].cat[input], ofield[input + 1],
					 Cats->cat[i]);

			    /* Mark as used */
			    at = find_attr(&(attr[input]), Cats->cat[i]);
			    if (!at)
				G_fatal_error(_("Attribute not found"));

			    at->used = 1;
			}
		    }
		}
	    }
	}
    }

    G_message(_("Writing centroids..."));

    db_init_string(&stmt);
    out_cat = 1;
    for (area = 1; area <= nareas; area++) {
	int i;

	G_percent(area, nareas, 1);

	/* check the condition */
	switch (operator) {
	case OP_AND:
	    if (!
		(Centr[area].cat[0]->n_cats > 0 &&
		 Centr[area].cat[1]->n_cats > 0))
		continue;
	    break;
	case OP_OR:
	    if (!
		(Centr[area].cat[0]->n_cats > 0 ||
		 Centr[area].cat[1]->n_cats > 0))
		continue;
	    break;
	case OP_NOT:
	    if (!
		(Centr[area].cat[0]->n_cats > 0 &&
		 !(Centr[area].cat[1]->n_cats > 0)))
		continue;
	    break;
	case OP_XOR:
	    if ((Centr[area].cat[0]->n_cats > 0 &&
		 Centr[area].cat[1]->n_cats > 0) ||
		(!(Centr[area].cat[0]->n_cats > 0) &&
		 !(Centr[area].cat[1]->n_cats > 0)))
		continue;
	    break;
	}

	Vect_reset_line(Points);
	Vect_reset_cats(Cats);

	Vect_append_point(Points, Centr[area].x, Centr[area].y, 0.0);

	if (ofield[0] > 0) {
	    /* Add new cats for all combinations of input cats (-1 in cycle for null) */
	    for (i = -1; i < Centr[area].cat[0]->n_cats; i++) {
		int j;

		if (i == -1 && Centr[area].cat[0]->n_cats > 0)
		    continue;	/* no need to make null */

		for (j = -1; j < Centr[area].cat[1]->n_cats; j++) {
		    if (j == -1 && Centr[area].cat[1]->n_cats > 0)
			continue;	/* no need to make null */

		    if (ofield[0] > 0)
			Vect_cat_set(Cats, ofield[0], out_cat);

		    /* attributes */
		    if (driver) {
			ATTR *at;

			sprintf(buf, "insert into %s values ( %d", Fi->table,
				out_cat);
			db_set_string(&stmt, buf);

			/* cata */
			if (i >= 0) {
			    if (attr[0].columns) {
				at = find_attr(&(attr[0]),
					       Centr[area].cat[0]->cat[i]);
				if (!at)
				    G_fatal_error(_("Attribute not found"));

				if (at->values)
				    db_append_string(&stmt, at->values);
				else
				    db_append_string(&stmt, attr[0].null_values);
			    }
			    else {
				sprintf(buf, ", %d", Centr[area].cat[0]->cat[i]);
				db_append_string(&stmt, buf);
			    }
			}
			else {
			    if (attr[0].columns) {
				db_append_string(&stmt, attr[0].null_values);
			    }
			    else {
				sprintf(buf, ", null");
				db_append_string(&stmt, buf);
			    }
			}

			/* catb */
			if (j >= 0) {
			    if (attr[1].columns) {
				at = find_attr(&(attr[1]),
					       Centr[area].cat[1]->cat[j]);
				if (!at)
				    G_fatal_error(_("Attribute not found"));

				if (at->values)
				    db_append_string(&stmt, at->values);
				else
				    db_append_string(&stmt, attr[1].null_values);
			    }
			    else {
				sprintf(buf, ", %d", Centr[area].cat[1]->cat[j]);
				db_append_string(&stmt, buf);
			    }
			}
			else {
			    if (attr[1].columns) {
				db_append_string(&stmt, attr[1].null_values);
			    }
			    else {
				sprintf(buf, ", null");
				db_append_string(&stmt, buf);
			    }
			}

			db_append_string(&stmt, " )");

			G_debug(3, "%s", db_get_string(&stmt));

			if (db_execute_immediate(driver, &stmt) != DB_OK)
			    G_warning(_("Unable to insert new record: '%s'"),
				      db_get_string(&stmt));
		    }
		    out_cat++;
		}
	    }
	}

	/* Add all cats from input vectors */
	if (ofield[1] > 0 && field[0] > 0) {
	    for (i = 0; i < Centr[area].cat[0]->n_cats; i++) {
		if (Centr[area].cat[0]->field[i] == field[0])
		    Vect_cat_set(Cats, ofield[1], Centr[area].cat[0]->cat[i]);
	    }
	}

	if (ofield[2] > 0 && field[1] > 0 && ofield[1] != ofield[2]) {
	    for (i = 0; i < Centr[area].cat[1]->n_cats; i++) {
		if (Centr[area].cat[1]->field[i] == field[1])
		    Vect_cat_set(Cats, ofield[2], Centr[area].cat[1]->cat[i]);
	    }
	}

	Vect_write_line(Tmp, GV_CENTROID, Points, Cats);
	Vect_write_line(Out, GV_CENTROID, Points, Cats);
    }

    G_set_verbose(0);
    /* should be fast, be silent */
    Vect_build_partial(Tmp, GV_BUILD_CENTROIDS);
    G_set_verbose(verbose);
    /* Copy valid boundaries to final output */
    nlines = Vect_get_num_lines(Tmp);

    for (line = 1; line <= nlines; line++) {
	int i, ltype, side[2], centr[2];

	G_percent(line, nlines, 1);	/* must be before any continue */

	if (!Vect_line_alive(Tmp, line))
	    continue;

	ltype = Vect_read_line(Tmp, Points, Cats, line);
	if (!(ltype & GV_BOUNDARY))
	    continue;

	Vect_get_line_areas(Tmp, line, &side[0], &side[1]);

	for (i = 0; i < 2; i++) {
	    if (side[i] == 0) {	/* This should not happen ! */
		centr[i] = 0;
		continue;
	    }

	    if (side[i] > 0) {
		area = side[i];
	    }
	    else {		/* island */
		area = Vect_get_isle_area(Tmp, abs(side[i]));
	    }

	    if (area > 0)
		centr[i] = Vect_get_area_centroid(Tmp, area);
	    else
		centr[i] = 0;
	}

	if (centr[0] || centr[1])
	    Vect_write_line(Out, GV_BOUNDARY, Points, Cats);
    }

    return 0;
}
Ejemplo n.º 5
0
/*!
   \brief Build topology 

   \param Map vector map
   \param build build level

   \return 1 on success
   \return 0 on error
 */
int Vect_build_nat(struct Map_info *Map, int build)
{
    struct Plus_head *plus;
    int i, s, type, line;
    off_t offset;
    int side, area;
    struct line_cats *Cats;
    struct P_line *Line;
    struct P_area *Area;
    struct bound_box box;
    
    G_debug(3, "Vect_build_nat() build = %d", build);

    plus = &(Map->plus);

    if (build == plus->built)
	return 1;		/* Do nothing */

    /* Check if upgrade or downgrade */
    if (build < plus->built) {
        /* -> downgrade */
	Vect__build_downgrade(Map, build);
        return 1;
    }

    /* -> upgrade */
    if (!Points)
        Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    
    if (plus->built < GV_BUILD_BASE) {
        int npoints, c;
        
	/* 
	 *  We shall go through all primitives in coor file and add
	 *  new node for each end point to nodes structure if the node
	 *  with the same coordinates doesn't exist yet.
	 */

	/* register lines, create nodes */
	Vect_rewind(Map);
	G_message(_("Registering primitives..."));
	i = 0;
	npoints = 0;
	while (TRUE) {
	    /* register line */
	    type = Vect_read_next_line(Map, Points, Cats);

	    /* Note: check for dead lines is not needed, because they
               are skipped by V1_read_next_line() */
	    if (type == -1) {
		G_warning(_("Unable to read vector map"));
		return 0;
	    }
	    else if (type == -2) {
		break;
	    }

	    G_progress(++i, 1e4);
	    
	    npoints += Points->n_points;

	    offset = Map->head.last_offset;

	    G_debug(3, "Register line: offset = %lu", (unsigned long)offset);
	    dig_line_box(Points, &box);
	    line = dig_add_line(plus, type, Points, &box, offset);
	    if (line == 1)
		Vect_box_copy(&(plus->box), &box);
	    else
		Vect_box_extend(&(plus->box), &box);

	    /* Add all categories to category index */
	    if (build == GV_BUILD_ALL) {
		for (c = 0; c < Cats->n_cats; c++) {
		    dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c],
				     line, type);
		}
		if (Cats->n_cats == 0)	/* add field 0, cat 0 */
		    dig_cidx_add_cat(plus, 0, 0, line, type);
	    }
	}
	G_progress(1, 1);

	G_message(_n("One primitive registered", "%d primitives registered", plus->n_lines), plus->n_lines);
	G_message(_n("One vertex registered", "%d vertices registered", npoints), npoints);

	plus->built = GV_BUILD_BASE;
    }

    if (build < GV_BUILD_AREAS)
	return 1;

    if (plus->built < GV_BUILD_AREAS) {
	/* Build areas */
	/* Go through all bundaries and try to build area for both sides */
	G_important_message(_("Building areas..."));
	for (line = 1; line <= plus->n_lines; line++) {
	    G_percent(line, plus->n_lines, 1);

	    /* build */
	    if (plus->Line[line] == NULL) {
		continue;
	    }			/* dead line */
	    Line = plus->Line[line];
	    if (Line->type != GV_BOUNDARY) {
		continue;
	    }

	    for (s = 0; s < 2; s++) {
		if (s == 0)
		    side = GV_LEFT;
		else
		    side = GV_RIGHT;

		G_debug(3, "Build area for line = %d, side = %d", line, side);
		Vect_build_line_area(Map, line, side);
	    }
	}
	G_message(_n("One area built", "%d areas built", plus->n_areas), plus->n_areas);
	G_message(_n("One isle built", "%d isles built", plus->n_isles), plus->n_isles);
	plus->built = GV_BUILD_AREAS;
    }

    if (build < GV_BUILD_ATTACH_ISLES)
	return 1;

    /* Attach isles to areas */
    if (plus->built < GV_BUILD_ATTACH_ISLES) {
	G_important_message(_("Attaching islands..."));
	for (i = 1; i <= plus->n_isles; i++) {
	    G_percent(i, plus->n_isles, 1);
	    Vect_attach_isle(Map, i);
	}
	plus->built = GV_BUILD_ATTACH_ISLES;
    }

    if (build < GV_BUILD_CENTROIDS)
	return 1;

    /* Attach centroids to areas */
    if (plus->built < GV_BUILD_CENTROIDS) {
	int nlines;
	struct P_topo_c *topo;

	G_important_message(_("Attaching centroids..."));

	nlines = Vect_get_num_lines(Map);
	for (line = 1; line <= nlines; line++) {
	    G_percent(line, nlines, 1);

	    Line = plus->Line[line];
	    if (!Line)
		continue;	/* Dead */

	    if (Line->type != GV_CENTROID)
		continue;

	    Vect_read_line(Map, Points, NULL, line);
	    area = Vect_find_area(Map, Points->x[0], Points->y[0]);

	    if (area > 0) {
		G_debug(3, "Centroid (line=%d) in area %d", line, area);

		Area = plus->Area[area];
		topo = (struct P_topo_c *)Line->topo;

		if (Area->centroid == 0) {	/* first */
		    Area->centroid = line;
		    topo->area = area;
		}
		else {		/* duplicate */
		    topo->area = -area;
		}
	    }
	}
	plus->built = GV_BUILD_CENTROIDS;
    }

    /* Add areas to category index */
    for (i = 1; i <= plus->n_areas; i++) {
	int c;

	if (plus->Area[i] == NULL)
	    continue;

	if (plus->Area[i]->centroid > 0) {
	    Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid);

	    for (c = 0; c < Cats->n_cats; c++) {
		dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i,
				 GV_AREA);
	    }
	}

	if (plus->Area[i]->centroid == 0 || Cats->n_cats == 0)	/* no centroid or no cats */
	    dig_cidx_add_cat(plus, 0, 0, i, GV_AREA);
    }

    Vect_destroy_cats_struct(Cats);
    
    return 1;
}
Ejemplo n.º 6
0
/*!
   \brief Overlay 2 vector maps with AND.

   AND supports:point line area
   point  +     -    +
   line   -     -    -
   area   +     -    -

   \param AMap vector map A
   \param atype feature type for A
   \param AList unused ?
   \param AAList unused ?
   \param BMap vector map B
   \param btype feature type for B
   \param BList unused ?
   \param BAList unused ?
   \param operator operator code

   \return 1 on success
   \return 0 on error
 */
int
Vect_overlay_and(struct Map_info *AMap, int atype, struct ilist *AList,
		 struct ilist *AAList, struct Map_info *BMap, int btype,
		 struct ilist *BList, struct ilist *BAList,
		 struct Map_info *OMap)
{
    int i, j, k, node, line, altype, bltype, oltype, area, centr;
    struct line_pnts *Points;
    struct line_cats *ACats, *BCats, *OCats;
    struct ilist *AOList, *BOList;

    /* TODO: support Lists */

    Points = Vect_new_line_struct();
    ACats = Vect_new_cats_struct();
    BCats = Vect_new_cats_struct();
    OCats = Vect_new_cats_struct();
    AOList = Vect_new_list();
    BOList = Vect_new_list();

    /* TODO: support all types; at present only point x point, area x point and point x area supported  */
    if ((atype & GV_LINES) || (btype & GV_LINES))
	G_warning(_("Overlay: line/boundary types not supported by AND operator"));

    if ((atype & GV_AREA) && (btype & GV_AREA))
	G_warning(_("Overlay: area x area types not supported by AND operator"));

    /* TODO: more points in one node in one map */

    /* point x point: select all points with identical coordinates in both maps */
    if ((atype & GV_POINTS) && (btype & GV_POINTS)) {	/* both points and centroids */
	G_debug(3, "overlay: AND: point x point");
	for (i = 1; i <= Vect_get_num_lines(AMap); i++) {
	    altype = Vect_read_line(AMap, Points, ACats, i);
	    if (!(altype & GV_POINTS))
		continue;

	    node =
		Vect_find_node(BMap, Points->x[0], Points->y[0], Points->z[0],
			       0, 1);
	    G_debug(3, "overlay: node = %d", node);
	    if (node == 0)
		continue;

	    Vect_reset_cats(OCats);

	    for (j = 0; j < Vect_get_node_n_lines(BMap, node); j++) {
		line = Vect_get_node_line(BMap, node, j);
		bltype = Vect_read_line(BMap, NULL, BCats, line);
		if (!(bltype & GV_POINTS))
		    continue;

		/* Identical points found -> write out */
		/* TODO: do something if fields in ACats and BCats are identical */
		for (k = 0; k < ACats->n_cats; k++)
		    Vect_cat_set(OCats, ACats->field[k], ACats->cat[k]);

		for (k = 0; k < BCats->n_cats; k++)
		    Vect_cat_set(OCats, BCats->field[k], BCats->cat[k]);

		/* TODO: what to do if one type is GV_POINT and second GV_CENTROID */
		oltype = altype;
		Vect_write_line(OMap, oltype, Points, OCats);
		Vect_list_append(AOList, i);	/* add to list of written lines */
		Vect_list_append(BOList, line);
		break;
	    }
	}
    }

    /* TODO: check only labeled areas */
    /* point x area: select points from A in areas in B */
    if ((atype & GV_POINTS) && (btype & GV_AREA)) {	/* both points and centroids */
	G_debug(3, "overlay: AND: point x area");

	for (i = 1; i <= Vect_get_num_lines(AMap); i++) {
	    altype = Vect_read_line(AMap, Points, ACats, i);
	    if (!(altype & GV_POINTS))
		continue;

	    area = Vect_find_area(BMap, Points->x[0], Points->y[0]);
	    if (area == 0)
		continue;

	    Vect_reset_cats(OCats);

	    /* TODO: do something if fields in ACats and BCats are identical */
	    for (k = 0; k < ACats->n_cats; k++)
		Vect_cat_set(OCats, ACats->field[k], ACats->cat[k]);

	    centr = Vect_get_area_centroid(BMap, area);
	    if (centr > 0) {
		bltype = Vect_read_line(BMap, NULL, BCats, centr);
		for (k = 0; k < BCats->n_cats; k++)
		    Vect_cat_set(OCats, BCats->field[k], BCats->cat[k]);
	    }

	    /* Check if not yet written */
	    if (!(Vect_val_in_list(AOList, i))) {
		Vect_write_line(OMap, altype, Points, OCats);
		Vect_list_append(AOList, i);
	    }

	}
    }
    /* area x point: select points from B in areas in A */
    if ((btype & GV_POINTS) && (atype & GV_AREA)) {	/* both points and centroids */
	G_debug(3, "overlay: AND: area x point");

	for (i = 1; i <= Vect_get_num_lines(BMap); i++) {
	    bltype = Vect_read_line(BMap, Points, BCats, i);
	    if (!(bltype & GV_POINTS))
		continue;

	    area = Vect_find_area(AMap, Points->x[0], Points->y[0]);
	    if (area == 0)
		continue;

	    Vect_reset_cats(OCats);

	    /* TODO: do something if fields in ACats and BCats are identical */
	    for (k = 0; k < BCats->n_cats; k++)
		Vect_cat_set(OCats, BCats->field[k], BCats->cat[k]);

	    centr = Vect_get_area_centroid(AMap, area);
	    if (centr > 0) {
		altype = Vect_read_line(AMap, NULL, ACats, centr);
		for (k = 0; k < ACats->n_cats; k++)
		    Vect_cat_set(OCats, ACats->field[k], ACats->cat[k]);
	    }

	    /* Check if not yet written */
	    if (!(Vect_val_in_list(BOList, i))) {
		Vect_write_line(OMap, bltype, Points, OCats);
		Vect_list_append(BOList, i);
	    }

	}
    }

    return 0;
}