int main() { RTREENODE* root = RTreeCreate(); int i, nhits; fprintf (stdout, "nrects = %d ", nrects); /* Insert all the testing data rects */ for(i=0; i<nrects; i++){ RTreeInsertRect(&rects[i], /* the mbr being inserted */ i+10, /* i+1 is mbr ID. ID MUST NEVER BE ZERO */ &root, /* the address of rtree's root since root can change undernieth*/ 0 /* always zero which means to add from the root */ ); } nhits = RTreeSearch(root, &search_rect, MySearchCallback, 0); fprintf (stdout, "Search resulted in %d hits ", nhits); RTreeDestroy (root); return 0; }
/* RTreeSearch in an index tree or subtree for all data retangles that ** overlap the argument rectangle. ** Returns the number of qualifying data rects. */ LeafList_t *RTreeSearch(RTree_t * rtp, Node_t * n, Rect_t * r) { register int i; LeafList_t *llp = 0; assert(n); assert(n->level >= 0); assert(r); rtp->SeTouchCount++; if (n->level > 0) { /* this is an internal node in the tree */ for (i = 0; i < NODECARD; i++) if (n->branch[i].child && Overlap(r, &n->branch[i].rect)) { LeafList_t *tlp = RTreeSearch(rtp, n->branch[i].child, r); if (llp) { LeafList_t *xlp = llp; while (xlp->next) xlp = xlp->next; xlp->next = tlp; } else llp = tlp; } } else { /* this is a leaf node */ for (i = 0; i < NODECARD; i++) { if (n->branch[i].child && Overlap(r, &n->branch[i].rect)) { llp = RTreeLeafListAdd(llp, (Leaf_t *) & n->branch[i]); # ifdef RTDEBUG PrintRect(&n->branch[i].rect); # endif } } } return llp; }
/*ARGS ARE AVAILABLE*/ void *RtreeUdiSearch (control_t *control) { rect_t r; int i; struct ClauseList clauselist; struct CallbackM cm; callback_m_t c; YAP_Term Constraints; /*RTreePrint ((*control)[0].tree);*/ for (i = 0; i < NARGS && (*control)[i].arg != 0 ; i++) if (YAP_IsAttVar(YAP_A((*control)[i].arg))) { /*get the constraits rect*/ Constraints = YAP_AttsOfVar(YAP_A((*control)[i].arg)); /* Yap_DebugPlWrite(Constraints); */ r = RectOfTerm(YAP_ArgOfTerm(2,Constraints)); c = &cm; c->cl = Yap_ClauseListInit(&clauselist); c->pred = (*control)[i].pred; if (!c->cl) return NULL; /*? or fail*/ RTreeSearch((*control)[i].tree, r, callback, c); Yap_ClauseListClose(c->cl); if (Yap_ClauseListCount(c->cl) == 0) { Yap_ClauseListDestroy(c->cl); return Yap_FAILCODE(); } if (Yap_ClauseListCount(c->cl) == 1) { return Yap_ClauseListToClause(c->cl); } return Yap_ClauseListCode(c->cl); } return NULL; /*YAP FALLBACK*/ }
/* 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); }
/* * Search in an index tree or subtree for all data rectangles that * overlap the argument rectangle. * Return the number of qualifying data rects. */ int RTreeSearch(struct Node *N, struct Rect *R, SearchHitCallback shcb, void* cbarg, int mode) { register struct Node *n = N; register struct Rect *r = R; /* NOTE: Suspected bug was R sent in as Node* and cast to Rect* here.*/ /* Fix not yet tested. */ register int hitCount = 0; register int i; long index; int sdebug = 0; if(mode == ID) { index = (long)N; n = &nodes[index]; } if(sdebug) { if (n->level > 0) printf("\nChecking internal node %ld\n", index); else printf("\nChecking leaf node %ld\n", index); } assert(n); assert(n->level >= 0); assert(r); if (n->level > 0) /* this is an internal node in the tree */ { for (i=0; i<NODECARD; i++) { if (sdebug && n->branch[i].child) { printf("\nNODECARD %ld\n", (long)n->branch[i].child); fflush(stdout); } if (n->branch[i].child && RTreeOverlap(r,&n->branch[i].rect)) { if(RTreeContained(&n->branch[i].rect, r)) hitCount += RTreeSearch(n->branch[i].child, R, shcb, cbarg, mode); else hitCount += RTreeSearch(n->branch[i].child, R, shcb, cbarg, mode); } } } else /* this is a leaf node */ { for (i=0; i<LEAFCARD; i++) { if (sdebug && n->branch[i].child) { printf("\nLEAFCARD %ld\n", (long)n->branch[i].child); fflush(stdout); } if (n->branch[i].child && RTreeOverlap(r,&n->branch[i].rect)) { hitCount++; if(sdebug) printf("---> Found\n"); if(shcb) /* call the user-provided callback */ if( ! shcb((long)n->branch[i].child, cbarg)) return hitCount; /* callback wants to terminate search early */ } } } return hitCount; }
/** * Responds to a new day event by releasing any pending infections and * stochastically generating infections. * * @param self the model. * @param herds a list of herds. * @param event a new day event. * @param rng a random number generator. * @param queue for any new events the model creates. */ void handle_new_day_event (struct ergadm_model_t_ *self, HRD_herd_list_t * herds, EVT_new_day_event_t * event, RAN_gen_t * rng, EVT_event_queue_t * queue) { local_data_t *local_data; HRD_herd_t *herd1; unsigned int nherds; /* number of herds */ unsigned int herd1_index, herd2_index; gboolean herd1_can_be_source; double distance; GQueue *q; EVT_event_t *pending_event; struct Rect search_rect; /* for narrowing down radius searches using the R-tree (spatial index) */ double mult; /* to account for latitude */ callback_t callback_data; #if DEBUG GString *s; #endif #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER handle_new_day_event (%s)", MODEL_NAME); #endif local_data = (local_data_t *) (self->model_data); /* Release any pending (due to airborne transport delays) events. */ local_data->rotating_index = (local_data->rotating_index + 1) % local_data->pending_infections->len; q = (GQueue *) g_ptr_array_index (local_data->pending_infections, local_data->rotating_index); while (!g_queue_is_empty (q)) { /* Remove the event from this model's internal queue and place it in the * simulation's event queue. */ pending_event = (EVT_event_t *) g_queue_pop_head (q); EVT_event_enqueue (queue, pending_event); local_data->npending_infections--; } if ( #if defined(USE_RTREE) && USE_RTREE == 1 /* For debugging purposes, you can #define USE_RTREE to 0 to never use * the spatial index, or 1 to always use it. */ TRUE || #endif local_data->use_rtree_index) { /* Initialize a data structure used by the callback function. */ callback_data.self = self; callback_data.herds = herds; callback_data.event = event; callback_data.rng = rng; callback_data.queue = queue; } nherds = HRD_herd_list_length (herds); for (herd1_index = 0; herd1_index < nherds; herd1_index++) { herd1 = HRD_herd_list_get (herds, herd1_index); /* Can this herd be the source of an exposure? */ #if DEBUG s = g_string_new (NULL); g_string_sprintf (s, "unit \"%s\" is %s, state is %s: ", herd1->official_id, herd1->production_type_name, HRD_status_name[herd1->status]); #endif herd1_can_be_source = local_data->param_block[herd1->production_type] != NULL && (herd1->status == InfectiousSubclinical || herd1->status == InfectiousClinical); #if DEBUG g_string_sprintfa (s, "%s be source", herd1_can_be_source ? "can" : "cannot"); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s", s->str); g_string_free (s, TRUE); #endif if (!herd1_can_be_source) continue; if (local_data->use_rtree_index[herd1->production_type]) { distance = local_data->max_spread[herd1->production_type] / GIS_DEGREE_DISTANCE; mult = 1.0 / MIN (cos (DEG2RAD * (herd1->lat + distance)), cos(DEG2RAD * (herd1->lat - distance))); search_rect.boundary[0] = herd1->lon - (distance * mult) - EPSILON; search_rect.boundary[1] = herd1->lat - distance - EPSILON; search_rect.boundary[2] = herd1->lon + (distance * mult) + EPSILON; search_rect.boundary[3] = herd1->lat + distance + EPSILON; callback_data.herd1 = herd1; RTreeSearch (herds->spatial_index, &search_rect, callback, &callback_data); } else for (herd2_index = 0; herd2_index < nherds; herd2_index++) check_and_infect (self, herds, herd1, HRD_herd_list_get (herds, herd2_index), event, rng, queue); } #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT handle_new_day_event (%s)", MODEL_NAME); #endif return; }