/*- * Written by H. Mitasova, I. Kosinovsky, D. Gerdes Fall 1993 * University of Illinois * US Army Construction Engineering Research Lab * Copyright 1993, H. Mitasova (University of Illinois), * I. Kosinovsky, (USA-CERL), and D.Gerdes (USA-CERL) * * Modified by H.Mitasova November 1996 to include variable smoothing * */ #include #include #include /* sm added to point structure */ struct triple * quad_point_new (double x, double y, double z, double sm) /* Initializes POINT structure with given arguments */ { struct triple *point; if (!(point = (struct triple *) malloc (sizeof (struct triple)))) { return NULL; } point->x = x; point->y = y; point->z = z; point->sm = sm; return point; } struct quaddata * quad_data_new (double x_or, double y_or, double xmax, double ymax, int rows, int cols, int n_points, int kmax) /* Initializes QUADDATA structure with given arguments*/ { struct quaddata *data; int i; if (!(data = (struct quaddata *) malloc (sizeof (struct quaddata)))) { return NULL; } data->x_orig = x_or; data->y_orig = y_or; data->xmax = xmax; data->ymax = ymax; data->n_rows = rows; data->n_cols = cols; data->n_points = n_points; data->points = (struct triple *) malloc (sizeof (struct triple) * (kmax + 1)) ; if (!data->points) return NULL; for (i = 0; i <= kmax; i++) { data->points[i].x = 0.; data->points[i].y = 0.; data->points[i].z = 0.; data->points[i].sm = 0.; } return data; } int quad_compare (struct triple *point, struct quaddata *data) /* returns the quadrant the point should be inserted in */ /* called by divide() */ { int cond1, cond2, cond3, cond4, rows, cols; double ew_res,ns_res; ew_res = (data->xmax-data->x_orig)/data->n_cols; ns_res = (data->ymax-data->y_orig)/data->n_rows; if (data == NULL) return -1; if (data->n_rows % 2 == 0) { rows = data->n_rows / 2; } else { rows = (int) (data->n_rows / 2) + 1; } if (data->n_cols % 2 == 0) { cols = data->n_cols / 2; } else { cols = (int) (data->n_cols / 2) + 1; } cond1 = (point->x >= data->x_orig); cond2 = (point->x >= data->x_orig+ew_res*cols); cond3 = (point->y >= data->y_orig); cond4 = (point->y >= data->y_orig+ns_res*rows); if (cond1 && cond3) { if (cond2 && cond4) return NE; if (cond2) return SE; if (cond4) return NW; return SW; } else return 0; } int quad_add_data (struct triple *point, struct quaddata *data, double dmin) /* Adds POINT to a given DATA . Called by tree function insert_quad() */ /* and by data function quad_divide_data() */ { int n, i, cond; double xx, yy, r; cond = 1; if (data==NULL) { fprintf(stderr,"add_data: data is NULL \n"); return -5; } for (i = 0; i < data->n_points; i++) { xx = data->points[i].x - point->x; yy = data->points[i].y - point->y; r = xx * xx + yy * yy; if (r <= dmin) { cond = 0; break; } } if (cond) { n = (data->n_points)++; data->points[n].x = point->x; data->points[n].y = point->y; data->points[n].z = point->z; data->points[n].sm = point->sm; } return cond; } int quad_intersect (struct quaddata *data_inter, struct quaddata *data) /* Checks if region defined by DATA intersects the region defined by data_inter. Called by tree function MT_region_data() */ { double xmin,xmax,ymin,ymax; xmin = data_inter->x_orig; xmax = data_inter->xmax; ymin = data_inter->y_orig; ymax = data_inter->ymax; if (((data->x_orig >= xmin) && (data->x_orig <= xmax) && (((data->y_orig >= ymin) && (data->y_orig <= ymax)) || ((ymin >= data->y_orig) && (ymin <= data->ymax)) ) ) || ((xmin >= data->x_orig) && (xmin <= data->xmax) && (((ymin >= data->y_orig) && (ymin <= data->ymax)) || ((data->y_orig >= ymin) && (data->y_orig <= ymax)) ) ) ) { return 1; } else return 0; } int quad_division_check (struct quaddata *data, int kmax) /* Checks if DATA needs to be divided. If data->points is empty, returns -1; if its not empty but there aren't enough points in DATA for division returns 0. Othervise (if its not empty and there are too many points) returns 1. Called by MT_insert() */ { if (data->points == NULL) return -1; if (data->n_points < kmax) return 0; else return 1; } struct quaddata ** quad_divide_data (struct quaddata *data, int kmax, double dmin) /* Divides DATA into 4 new datas reinserting data->points in them by calling data function quad_compare() to detrmine were to insert. Called by MT_divide(). Returns array of 4 new datas */ { struct quaddata **datas; int cols1, cols2, rows1, rows2, i; /*j1, j2, jmin = 0;*/ double dx, dy; /* x2, y2, dist, mindist; */ double xr,xm,xl,yr,ym,yl; /* left, right, middle coord */ double ew_res,ns_res; ew_res = (data->xmax-data->x_orig)/data->n_cols; ns_res = (data->ymax-data->y_orig)/data->n_rows; if ((data->n_cols <= 1) || (data->n_rows <= 1)) { fprintf(stderr,"Points are too concentrated -- please increase DMIN\n"); exit (0); } if (data->n_cols % 2 == 0) { cols1 = data->n_cols / 2; cols2 = cols1; } else { cols2 = (int) (data->n_cols / 2); cols1 = cols2 + 1; } if (data->n_rows % 2 == 0) { rows1 = data->n_rows / 2; rows2 = rows1; } else { rows2 = (int) (data->n_rows / 2); rows1 = rows2 + 1; } dx = cols1 * ew_res; dy = rows1 * ns_res; xl = data->x_orig; xm = xl+dx; xr = data->xmax; yl = data->y_orig; ym = yl+dy; yr = data->ymax; if (!(datas=(struct quaddata **) malloc(sizeof(struct quaddata *) * 5))) { return NULL; } datas[NE]=quad_data_new(xm,ym,xr,yr,rows2,cols2,0,kmax); datas[SW]=quad_data_new(xl,yl,xm,ym,rows1,cols1,0,kmax); datas[SE]=quad_data_new(xm,yl,xr,ym,rows1,cols2,0,kmax); datas[NW]=quad_data_new(xl,ym,xm,yr,rows2,cols1,0,kmax); for (i=0;in_points;i++) { switch (quad_compare (data->points+i, data)) { case SW: { quad_add_data (data->points+i, datas[SW], dmin); break; } case SE: { quad_add_data (data->points+i, datas[SE], dmin); break; } case NW: { quad_add_data (data->points+i, datas[NW], dmin); break; } case NE: { quad_add_data (data->points+i, datas[NE], dmin); break; } } } data->points = NULL; return datas; } int quad_get_points (struct quaddata *data_inter, struct quaddata *data, int MAX) /* Gets such points from DATA that lie within region determined by data_inter. Called by tree function region_data(). */ { int i,ind; int n=0; int l = 0; double xmin,xmax,ymin,ymax; struct triple *point; xmin = data_inter->x_orig; xmax = data_inter->xmax; ymin = data_inter->y_orig; ymax = data_inter->ymax; for (i = 0; i < data->n_points; i++) { point = data->points+i; if (l >= MAX) return MAX + 1; if ((point->x > xmin) && (point->x < xmax) && (point->y > ymin) && (point->y < ymax)) { ind = data_inter->n_points++; data_inter->points[ind].x = point->x; data_inter->points[ind].y = point->y; data_inter->points[ind].z = point->z; data_inter->points[ind].sm = point->sm; l=l+1; } } n = l; return (n); }