int test_basics_2d(void) { int sum = 0, num, i; struct RTree* tree = RTreeCreateTree(-1, 0, 2); struct ilist *list = G_new_ilist(); for(i = 0; i < 10; i++) { struct RTree_Rect* rect1 = RTreeAllocRect(tree); RTreeSetRect2D(rect1, tree,(i - 2), (i + 2), (i - 2), (i + 2)); RTreeInsertRect(rect1, i + 1, tree); struct RTree_Rect* rect2 = RTreeAllocRect(tree); RTreeSetRect2D(rect2, tree, 2.0, 7.0, 2.0, 7.0); num = RTreeSearch2(tree, rect2, list); printf("Found %i neighbors\n", num); if(num != i + 1) sum++; RTreeFreeRect(rect1); RTreeFreeRect(rect2); } RTreeDestroyTree(tree); G_free_ilist(list); return sum; }
/* break polygons using a file-based search index */ void Vect_break_polygons_file(struct Map_info *Map, int type, struct Map_info *Err) { struct line_pnts *BPoints, *Points; struct line_cats *Cats, *ErrCats; int i, j, k, ret, ltype, broken, last, nlines; int nbreaks; struct RTree *RTree; int npoints, nallpoints, nmarks; XPNT2 XPnt; double dx, dy, a1 = 0, a2 = 0; int closed, last_point; char cross; int fd, xpntfd; char *filename; static struct RTree_Rect rect; static int rect_init = 0; if (!rect_init) { rect.boundary = G_malloc(6 * sizeof(RectReal)); rect_init = 6; } G_debug(1, "File-based version of Vect_break_polygons()"); filename = G_tempfile(); fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); RTree = RTreeCreateTree(fd, 0, 2); remove(filename); filename = G_tempfile(); xpntfd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); remove(filename); BPoints = Vect_new_line_struct(); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); ErrCats = Vect_new_cats_struct(); nlines = Vect_get_num_lines(Map); G_debug(3, "nlines = %d", nlines); /* Go through all lines in vector, and add each point to structure of points, * if such point already exists check angles of segments and if differ mark for break */ nmarks = 0; npoints = 1; /* index starts from 1 ! */ nallpoints = 0; XPnt.used = 0; G_message(_("Breaking polygons (pass 1: select break points)...")); for (i = 1; i <= nlines; i++) { G_percent(i, nlines, 1); G_debug(3, "i = %d", i); if (!Vect_line_alive(Map, i)) continue; ltype = Vect_read_line(Map, Points, Cats, i); if (!(ltype & type)) continue; /* This would be confused by duplicate coordinates (angle cannot be calculated) -> * prune line first */ Vect_line_prune(Points); /* If first and last point are identical it is close polygon, we don't need to register last point * and we can calculate angle for first. * If first and last point are not identical we have to mark for break both */ last_point = Points->n_points - 1; if (Points->x[0] == Points->x[last_point] && Points->y[0] == Points->y[last_point]) closed = 1; else closed = 0; for (j = 0; j < Points->n_points; j++) { G_debug(3, "j = %d", j); nallpoints++; if (j == last_point && closed) continue; /* do not register last of close polygon */ /* Box */ rect.boundary[0] = Points->x[j]; rect.boundary[3] = Points->x[j]; rect.boundary[1] = Points->y[j]; rect.boundary[4] = Points->y[j]; rect.boundary[2] = 0; rect.boundary[5] = 0; /* Already in DB? */ fpoint = -1; RTreeSearch(RTree, &rect, (void *)srch, NULL); G_debug(3, "fpoint = %d", fpoint); if (Points->n_points <= 2 || (!closed && (j == 0 || j == last_point))) { cross = 1; /* mark for cross in any case */ } else { /* calculate angles */ cross = 0; if (j == 0 && closed) { /* closed polygon */ dx = Points->x[last_point] - Points->x[0]; dy = Points->y[last_point] - Points->y[0]; a1 = atan2(dy, dx); dx = Points->x[1] - Points->x[0]; dy = Points->y[1] - Points->y[0]; a2 = atan2(dy, dx); } else { dx = Points->x[j - 1] - Points->x[j]; dy = Points->y[j - 1] - Points->y[j]; a1 = atan2(dy, dx); dx = Points->x[j + 1] - Points->x[j]; dy = Points->y[j + 1] - Points->y[j]; a2 = atan2(dy, dx); } } if (fpoint > 0) { /* Found */ /* read point */ lseek(xpntfd, (off_t) (fpoint - 1) * sizeof(XPNT2), SEEK_SET); read(xpntfd, &XPnt, sizeof(XPNT2)); if (XPnt.cross == 1) continue; /* already marked */ /* Check angles */ if (cross) { XPnt.cross = 1; nmarks++; /* write point */ lseek(xpntfd, (off_t) (fpoint - 1) * sizeof(XPNT2), SEEK_SET); write(xpntfd, &XPnt, sizeof(XPNT2)); } else { G_debug(3, "a1 = %f xa1 = %f a2 = %f xa2 = %f", a1, XPnt.a1, a2, XPnt.a2); if ((a1 == XPnt.a1 && a2 == XPnt.a2) || (a1 == XPnt.a2 && a2 == XPnt.a1)) { /* identical */ } else { XPnt.cross = 1; nmarks++; /* write point */ lseek(xpntfd, (off_t) (fpoint - 1) * sizeof(XPNT2), SEEK_SET); write(xpntfd, &XPnt, sizeof(XPNT2)); } } } else { /* Add to tree and to structure */ RTreeInsertRect(&rect, npoints, RTree); if (j == 0 || j == (Points->n_points - 1) || Points->n_points < 3) { XPnt.a1 = 0; XPnt.a2 = 0; XPnt.cross = 1; nmarks++; } else { XPnt.a1 = a1; XPnt.a2 = a2; XPnt.cross = 0; } /* write point */ lseek(xpntfd, (off_t) (npoints - 1) * sizeof(XPNT2), SEEK_SET); write(xpntfd, &XPnt, sizeof(XPNT2)); npoints++; } } } nbreaks = 0; /* Second loop through lines (existing when loop is started, no need to process lines written again) * and break at points marked for break */ G_message(_("Breaking polygons (pass 2: break at selected points)...")); for (i = 1; i <= nlines; i++) { int n_orig_points; G_percent(i, nlines, 1); G_debug(3, "i = %d", i); if (!Vect_line_alive(Map, i)) continue; ltype = Vect_read_line(Map, Points, Cats, i); if (!(ltype & type)) continue; if (!(ltype & GV_LINES)) continue; /* Nonsense to break points */ /* Duplicates would result in zero length lines -> prune line first */ n_orig_points = Points->n_points; Vect_line_prune(Points); broken = 0; last = 0; G_debug(3, "n_points = %d", Points->n_points); for (j = 1; j < Points->n_points; j++) { G_debug(3, "j = %d", j); nallpoints++; /* Box */ rect.boundary[0] = Points->x[j]; rect.boundary[3] = Points->x[j]; rect.boundary[1] = Points->y[j]; rect.boundary[4] = Points->y[j]; rect.boundary[2] = 0; rect.boundary[5] = 0; if (Points->n_points <= 1 || (j == (Points->n_points - 1) && !broken)) break; /* One point only or * last point and line is not broken, do nothing */ RTreeSearch(RTree, &rect, (void *)srch, 0); G_debug(3, "fpoint = %d", fpoint); /* read point */ lseek(xpntfd, (off_t) (fpoint - 1) * sizeof(XPNT2), SEEK_SET); read(xpntfd, &XPnt, sizeof(XPNT2)); /* break or write last segment of broken line */ if ((j == (Points->n_points - 1) && broken) || XPnt.cross) { Vect_reset_line(BPoints); for (k = last; k <= j; k++) { Vect_append_point(BPoints, Points->x[k], Points->y[k], Points->z[k]); } /* Result may collapse to one point */ Vect_line_prune(BPoints); if (BPoints->n_points > 1) { ret = Vect_write_line(Map, ltype, BPoints, Cats); G_debug(3, "Line %d written j = %d n_points(orig,pruned) = %d n_points(new) = %d", ret, j, Points->n_points, BPoints->n_points); } if (!broken) Vect_delete_line(Map, i); /* not yet deleted */ /* Write points on breaks */ if (Err) { if (XPnt.cross && !XPnt.used) { Vect_reset_line(BPoints); Vect_append_point(BPoints, Points->x[j], Points->y[j], 0); Vect_write_line(Err, GV_POINT, BPoints, ErrCats); } if (!XPnt.used) { XPnt.used = 1; /* write point */ lseek(xpntfd, (off_t) (fpoint - 1) * sizeof(XPNT2), SEEK_SET); write(xpntfd, &XPnt, sizeof(XPNT2)); } } last = j; broken = 1; nbreaks++; } } if (!broken && n_orig_points > Points->n_points) { /* was pruned before -> rewrite */ if (Points->n_points > 1) { Vect_rewrite_line(Map, i, ltype, Points, Cats); G_debug(3, "Line %d pruned, npoints = %d", i, Points->n_points); } else { Vect_delete_line(Map, i); G_debug(3, "Line %d was deleted", i); } } else { G_debug(3, "Line %d was not changed", i); } } close(RTree->fd); RTreeDestroyTree(RTree); close(xpntfd); Vect_destroy_line_struct(Points); Vect_destroy_line_struct(BPoints); Vect_destroy_cats_struct(Cats); Vect_destroy_cats_struct(ErrCats); G_verbose_message(_("Breaks: %d"), nbreaks); }