int gridkmap_xy2ij(gridkmap* gm, double x, double y, int* iout, int* jout) { double* minmax = kd_getminmax(gm->tree); double pos[2]; size_t nearest; size_t id; poly* p; int i, j, i1, i2, j1, j2; int success = 0; if (x < minmax[0] || y < minmax[1] || x > minmax[2] || y > minmax[3]) return success; pos[0] = x; pos[1] = y; nearest = kd_findnearestnode(gm->tree, pos); id = kd_getnodeorigid(gm->tree, nearest); p = poly_create(); j = id / (gm->nce1 + 1); i = id % (gm->nce1 + 1); i1 = (i > 0) ? i - 1 : i; i2 = (i < gm->nce1) ? i + 1 : i; j1 = (j > 0) ? j - 1 : j; j2 = (j < gm->nce2) ? j + 1 : j; /* * TODO?: looks a bit heavyweight */ for (j = j1; j <= j2 - 1; ++j) for (i = i1; i <= i2 - 1; ++i) { if (!isfinite(gm->gx[j][i]) || !isfinite(gm->gx[j][i + 1]) || !isfinite(gm->gx[j + 1][i + 1]) || !isfinite(gm->gx[j + 1][i])) continue; poly_addpoint(p, gm->gx[j][i], gm->gy[j][i]); poly_addpoint(p, gm->gx[j][i + 1], gm->gy[j][i + 1]); poly_addpoint(p, gm->gx[j + 1][i + 1], gm->gy[j + 1][i + 1]); poly_addpoint(p, gm->gx[j + 1][i], gm->gy[j + 1][i]); poly_addpoint(p, gm->gx[j][i], gm->gy[j][i]); if (poly_containspoint(p, x, y)) { success = 1; *iout = i; *jout = j; goto finish; } poly_clear(p); } finish: poly_destroy(p); return success; }
/** Forms polyline boundary around a grid in index space. * @param nce1 Number of cells in X direction * @param nce2 Number of cells in Y direction * @param x X coordinates of grid nodes * @return Boundary polyline */ poly* poly_formboundij(int nce1, int nce2, double** x) { poly* pl = poly_create(); int direction = 0; /* 0 - down, 1 - right, 2 - up, 3 -left */ int iinc[] = { 0, 1, 0, -1 }; int jinc[] = { 1, 0, -1, 0 }; int i, j, istart, jstart; for (j = 0; j <= nce2; ++j) for (i = 0; i <= nce1; ++i) if (!isnan(x[j][i])) goto ok; ok: if (j > nce2) return pl; istart = i; jstart = j; poly_addpoint(pl, i, j); do { int direction_stop = (direction + 2) % 4; int inext, jnext; direction = (direction + 3) % 4; inext = i + iinc[direction]; jnext = j + jinc[direction]; while ((inext < 0 || jnext < 0 || inext > nce1 || jnext > nce2 || isnan(x[jnext][inext])) && direction != direction_stop) { direction = (direction + 1) % 4; inext = i + iinc[direction]; jnext = j + jinc[direction]; } if (direction == direction_stop) break; i = inext; j = jnext; poly_addpoint(pl, i, j); } while (j != jstart || i != istart); poly_close(pl); return (pl); }
/* Cuts boundary polygon in two. * The cut goes either horizontally ([fixed][changes]) or vertically * ([changes][fixed]) in index space; the physical nodes are given by * input double arrays; first two intersections of the cutting polyline * with the polygon are used to form the new polygons. * @param pl Original polygon * @param gx Array of x cell corner coordinates * @param gy Array of y cell corner coordinates * @param horiz flag: 1 for horizontal cut; 0 otherwise * @param index Value of "fixed" index * @param start Start value of "variable" index * @param end End value of "variable" index * @param pl1 Output polygon 1 * @param pl1 Output polygon 2 */ static void cut_boundary(poly* pl, double** gx, double** gy, int horiz, int index, int start, int end, poly** pl1, poly** pl2) { int n = pl->n; int i = -1; int i1 = -1; /* array index of the first intersection */ int i2 = -1; /* array index of the second intersection */ int ii1 = -1; /* polygon index of the first intersection */ int ii2 = -1; /* polygon index of the second intersection */ int tmp = -1; /* * if the polygon has been explicitely closed, ignore the last point */ if (poly_isclosed(pl, 1.0e-15)) n--; if (horiz) { /* horizontal cut */ /* * find first intersection */ for (i = start; i < end; ++i) { ii1 = poly_findindex(pl, gx[index][i], gy[index][i]); if (ii1 < 0) /* * this node does not belong to the boundary */ continue; /* * this node belongs to the boundary polygon To accept it as a * valid intersection, we must ensure that the very next node is * either inside the polygon or belongs to the boundary but is * not the next boundary node. */ tmp = poly_findindex(pl, gx[index][i + 1], gy[index][i + 1]); if ((tmp < 0 && poly_containspoint(pl, gx[index][i + 1], gy[index][i + 1])) || (tmp >= 0 && abs(tmp - ii1) > 1 && abs(tmp - ii1) < n - 1)) break; } /* * how the for-cycle ended */ if (i < end) /* ok */ i1 = i; else /* no intersection found */ return; /* * find second intersection start from the node next to the first * intersection */ for (i = i1 + 1; i <= end; ++i) { ii2 = poly_findindex(pl, gx[index][i], gy[index][i]); if (ii2 >= 0) /* * this node must be inside the boundary polygon -- skip */ break; } if (ii2 < 0) /* * no intersection found */ return; else /* * ok */ i2 = i; /* * we found all necessary details, now form the new polygons */ *pl1 = poly_create(); *pl2 = poly_create(); /* * add the portion of perimeter */ for (i = ii1; i != ii2; i = (i + 1) % n) poly_addpoint(*pl1, pl->x[i], pl->y[i]); /* * add the cutting section */ for (i = i2; i > i1; --i) poly_addpoint(*pl1, gx[index][i], gy[index][i]); /* * add the portion of perimeter */ for (i = ii2; i != ii1; i = (i + 1) % n) poly_addpoint(*pl2, pl->x[i], pl->y[i]); /* * add the cutting section */ for (i = i1; i < i2; ++i) poly_addpoint(*pl2, gx[index][i], gy[index][i]); } else { /* vertical cut */ for (i = start; i < end; ++i) { ii1 = poly_findindex(pl, gx[i][index], gy[i][index]); if (ii1 < 0) continue; tmp = poly_findindex(pl, gx[i + 1][index], gy[i + 1][index]); if ((tmp < 0 && poly_containspoint(pl, gx[i + 1][index], gy[i + 1][index])) || (tmp >= 0 && abs(tmp - ii1) > 1 && abs(tmp - ii1) < n - 1)) break; } if (i < end) i1 = i; else return; for (i = i1 + 1; i <= end; ++i) { ii2 = poly_findindex(pl, gx[i][index], gy[i][index]); if (ii2 >= 0) break; } if (ii2 < 0) return; else i2 = i; *pl1 = poly_create(); *pl2 = poly_create(); for (i = ii1; i != ii2; i = (i + 1) % n) poly_addpoint(*pl1, pl->x[i], pl->y[i]); for (i = i2; i > i1; --i) poly_addpoint(*pl1, gx[i][index], gy[i][index]); for (i = ii2; i != ii1; i = (i + 1) % n) poly_addpoint(*pl2, pl->x[i], pl->y[i]); for (i = i1; i < i2; ++i) poly_addpoint(*pl2, gx[i][index], gy[i][index]); /* * There used to be closure of the polylines here: * poly_close(*pl1); * poly_close(*pl2); * While this does not harm, it causes the boundary of a quadrilateral * to contain 5 points rather than 4, which caused allocation for 8 * points... Anyway, considering the way search in poly_containspoint() * works, this is not necessary. */ } }
int main (void) { poly *P0, *P1, *P2, *P3, *M1, *M2, *P4, *P5, *P6, *P7; P0=poly_create(4,2,1,3,2,6,5,1,7); //4 terms: 1x^7 + 6x^5 + 3x^2 + 2x^1 P1=poly_create(3,3,2,1,4,6,5); //3 terms: 6x^5 + 1x^4 + 3x^2 P2=poly_create(1,16,2); //1 term: 16x^2 P3=poly_create(0); // no terms printf("P0: "); poly_print(P0); printf("P1: "); poly_print(P1); printf("P2: "); poly_print(P2); printf("P3: "); poly_print(P3); M1=poly_scalar_mult(P1,2); printf("M1 (P1*2): "); poly_print(M1); M2=poly_scalar_mult(P3,4); printf("M2 (P3*4): "); poly_print(M2); P4=poly_duplicate(M1); printf("P4 (dup M1): "); poly_print(P4); P5=poly_add(P1,P0); printf("P5 (P1+P0): "); poly_print(P5); P6=poly_add(P3,P3); printf("P6 (P3+P3): "); poly_print(P6); P7=poly_add(P0,P3); printf("P7 (P0+P3): "); poly_print(P7); poly_free(&P1); if (P1==NULL) printf("P1: was freed\n"); else printf("P1: is not null!!\n"); poly *test1=poly_create(4,2,1,3,2,6,5,1,7); //4 terms: 1x^7 + 6x^5 + 3x^2 + 2x^1 poly *test2=poly_duplicate(test1); test2=poly_scalar_mult(test2, 5); printf("test1: ");poly_print(test1); printf("test2: ");poly_print(test2); //printf("%p, %p\n", test1, test2); poly_free(&test1); poly *MM1 = poly_create(5,1,1,2,2,3,3,4,4,5,5); poly *MM2 = poly_create(5,-1,1,-2,2,-3,3,-4,4,-5,5); printf("MM1: ");poly_print(MM1); printf("MM2: ");poly_print(MM2); poly *MM1_Plus_MM2 = poly_add(MM1, MM2); printf("(MM1+MM2): ");poly_print(MM1_Plus_MM2); poly *MM1_Multiplied_By_5 = poly_scalar_mult(MM1, 5); poly *MM2_Multiplied_By_10 = poly_scalar_mult(MM2, 10); printf("MM1*5: ");poly_print(MM1_Multiplied_By_5); printf("MM2*10: ");poly_print(MM2_Multiplied_By_10); printf("MM1: ");poly_print(MM1); printf("MM2: ");poly_print(MM2); }