int clip_line(struct liang_barsky_clip_window *c, float *x1, float *y1, float *x2, float *y2) { float dx, dy, tE, tL; dx = *x2 - *x1; dy = *y2 - *y1; if (is_zero(dx) && is_zero(dy) && point_inside(c, *x1, *y1)) return 1; tE = 0; tL = 1; if (clipT(c->x1 - *x1, dx, &tE, &tL) && clipT( *x1 - c->x2, -dx, &tE, &tL) && clipT(c->y1 - *y1, dy, &tE, &tL) && clipT( *y1 - c->y2, -dy, &tE, &tL)) { if (tL < 1) { *x2 = ((float) *x1 + tL * dx); *y2 = ((float) *y1 + tL * dy); } if (tE > 0) { *x1 += tE * dx; *y1 += tE * dy; } return 1; } return 0; }
/* does this sphere contain the point? */ int SPHERE_Contains_Point (void *dummy, SPHERE *sph, double *point) { return point_inside (sph->cur_center, sph->cur_radius, point); }
/* return sphere containing a spatial point */ SPHERE* SPHERE_Containing_Point (SPHERE *sph, double *point) { if (point_inside (sph->cur_center, sph->cur_radius, point)) return sph; else return NULL; }
static int quadtree_insert_node(quadtree *q, quadtree_node *qn, void *data, size_t size, double x, double y) { if (!qn) { return QUADTREE_ERROR; } if (!quadtree_node_has_children(qn) && llist_is_empty(qn->points)) { quadtree_data *qd = quadtree_data_create(data, size, x, y); if (!qd) { return QUADTREE_ERROR; } llist_add_to_back(qn->points, qd, sizeof(quadtree_data)); free(qd); ++q->size; return QUADTREE_OK; } else { quadtree_data *d = llist_first(qn->points); if (d && quadtree_data_same_location(d, x, y)) { // Same point quadtree_data *qd = quadtree_data_create(data, size, x, y); if (!qd) { return QUADTREE_ERROR; } llist_add_to_back(qn->points, qd, sizeof(quadtree_data)); free(qd); return QUADTREE_OK; } else { quadtree_data *e = llist_first(qn->points); // Split node double minX = qn->bounds.x; double minY = qn->bounds.y; double midX = qn->bounds.x + qn->bounds.w / 2; double midY = qn->bounds.y + qn->bounds.h / 2; double maxX = qn->bounds.x + qn->bounds.w; double maxY = qn->bounds.y + qn->bounds.h; double xDim[4][2] = { { midX, maxX - midX }, { minX, midX - minX }, { minX, midX - minX }, { midX, maxX - midX } }; double yDim[4][2] = { { midY, maxY - midY }, { midY, maxY - midY }, { minY, midY - minY }, { minY, midY - minY } }; quadtree_data *d = llist_first(qn->points); int ret = QUADTREE_ERROR; for (int i = 0; i < 4; i++) { if (point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], x, y) || (d && point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], d->x, d->y))) { if (!qn->children[i]) { qn->children[i] = quadtree_node_create(); } quadtree_node_set_bounds(qn->children[i], xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1]); if (point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], x, y)) { quadtree_insert_node(q, qn->children[i], data, size, x, y); ret = QUADTREE_OK; } else if (point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], d->x, d->y)) { // Move contained points into child node qn->children[i]->points = qn->points; qn->points = NULL; ret = QUADTREE_OK; } } } return ret; } } // Shouldn't happen return QUADTREE_ERROR; }
/* clip3d: * A fixed point version of clip3d_f. Works suprisingly well. */ int clip3d(int type, fixed min_z, fixed max_z, int vc, AL_CONST V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[]) { int i, j, vo, vt, flags; fixed t; V3D *v3; AL_CONST V3D *v1, *v2, **vin; static int flag_table[] = { INT_NONE, /* flat */ INT_3COLP, /* gcol */ INT_3COL, /* grgb */ INT_UV, /* atex */ INT_UV, /* ptex */ INT_UV, /* atex mask */ INT_UV, /* ptex mask */ INT_UV + INT_1COL, /* atex lit */ INT_UV + INT_1COL, /* ptex lit */ INT_UV + INT_1COL, /* atex mask lit */ INT_UV + INT_1COL, /* ptex mask lit */ INT_UV, /* atex trans */ INT_UV, /* ptex trans */ INT_UV, /* atex mask trans */ INT_UV /* ptex mask trans */ }; type &= ~POLYTYPE_ZBUF; flags = flag_table[type]; if (max_z > min_z) { vt = 0; for (i=0; i<vc; i++) out[i] = (vtx[i]->z > max_z); for (i=0, j=vc-1; i<vc; j=i, i++) { v1 = vtx[j]; v2 = vtx[i]; v3 = vtmp[vt]; if ((out[j] & out[i]) != 0) continue; if ((out[j] | out[i]) == 0) { point_inside(vt); continue; } t = fixdiv(max_z - v1->z, v2->z - v1->z); point_interp(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vin = (AL_CONST V3D**)vtmp; } else { vt = vc; vin = vtx; } vo = 0; for (i=0; i<vt; i++) out[i] = (vin[i]->z < min_z); for (i=0, j=vt-1; i<vt; j=i, i++) { v1 = vin[j]; v2 = vin[i]; v3 = vout[vo]; if ((out[j] & out[i]) != 0) continue; if ((out[j] | out[i]) == 0) { point_inside(vo); continue; } t = fixdiv(min_z - v1->z, v2->z - v1->z); point_interp(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } vt = 0; for (i=0; i<vo; i++) out[i] = (vout[i]->x < -vout[i]->z); for (i=0, j=vo-1; i<vo; j=i, i++) { v1 = vout[j]; v2 = vout[i]; v3 = vtmp[vt]; if ((out[j] & out[i]) != 0) continue; if ((out[j] | out[i]) == 0) { point_inside(vt); continue; } t = fixdiv(-v1->z - v1->x, v2->x - v1->x + v2->z - v1->z); point_interp(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vo = 0; for (i=0; i<vt; i++) out[i] = (vtmp[i]->x > vtmp[i]->z); for (i=0, j=vt-1; i<vt; j=i, i++) { v1 = vtmp[j]; v2 = vtmp[i]; v3 = vout[vo]; if ((out[j] & out[i]) != 0) continue; if ((out[j] | out[i]) == 0) { point_inside(vo); continue; } t = fixdiv(v1->z - v1->x, v2->x - v1->x - v2->z + v1->z); point_interp(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } vt = 0; for (i=0; i<vo; i++) out[i] = (vout[i]->y < -vout[i]->z); for (i=0, j=vo-1; i<vo; j=i, i++) { v1 = vout[j]; v2 = vout[i]; v3 = vtmp[vt]; if ((out[j] & out[i]) != 0) continue; if ((out[j] | out[i]) == 0) { point_inside(vt); continue; } t = fixdiv(-v1->z - v1->y, v2->y - v1->y + v2->z - v1->z); point_interp(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vo = 0; for (i=0; i<vt; i++) out[i] = (vtmp[i]->y > vtmp[i]->z); for (i=0, j=vt-1; i<vt; j=i, i++) { v1 = vtmp[j]; v2 = vtmp[i]; v3 = vout[vo]; if ((out[j] & out[i]) != 0) continue; if ((out[j] | out[i]) == 0) { point_inside(vo); continue; } t = fixdiv(v1->z - v1->y, v2->y - v1->y - v2->z + v1->z); point_interp(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } if (type == POLYTYPE_FLAT) vout[0]->c = vtx[0]->c; return vo; }
/** for a pair (p, q) of points, add the edge pq if their are visible to each other */ void handle(struct Point *p, struct Point *q, struct Map_info *out) { /* if it's a point without segments, just report the edge */ if (segment1(q) == NULL && segment2(q) == NULL && before(p, q, p->vis)) { report(p, q, out); } else if (segment1(p) != NULL && q == other1(p)) { /* we need to check if there is another segment at q so it can be set to the vis */ if (segment1(q) == segment1(p) && segment2(q) != NULL && left_turn(p, q, other2(q))) { p->vis = segment2(q); } else if (segment2(q) == segment1(p) && segment1(q) != NULL && left_turn(p, q, other1(q))) { p->vis = segment1(q); } else p->vis = q->vis; report(p, q, out); } else if (segment2(p) != NULL && q == other2(p)) { /* we need to check if there is another segment at q so it can be set to the vis */ if (segment1(q) == segment2(p) && segment2(q) != NULL && left_turn(p, q, other2(q))) { p->vis = segment2(q); } else if (segment2(q) == segment2(p) && segment1(q) != NULL && left_turn(p, q, other1(q))) { p->vis = segment1(q); } else p->vis = q->vis; report(p, q, out); } else if (segment1(q) == p->vis && segment1(q) != NULL) { /* we need to check if there is another segment at q so it can be set to the vis */ if (segment2(q) != NULL && left_turn(p, q, other2(q))) p->vis = segment2(q); else p->vis = q->vis; /* check that p and q are not on the same boundary and that the edge pq is inside the boundary */ if (p->cat == -1 || p->cat != q->cat || !point_inside(p, (p->x + q->x) * 0.5, (p->y + q->y) * 0.5)) report(p, q, out); } else if (segment2(q) == p->vis && segment2(q) != NULL) { /* we need to check if there is another segment at q so it can be set to the vis */ if (segment1(q) != NULL && left_turn(p, q, other1(q))) p->vis = segment1(q); else p->vis = q->vis; /* check that p and q are not on the same boundary and that the edge pq is inside the boundary */ if (p->cat == -1 || p->cat != q->cat || !point_inside(p, (p->x + q->x) * 0.5, (p->y + q->y) * 0.5)) report(p, q, out); } else if (before(p, q, p->vis)) { /* if q only has one segment, then this is the new vis */ if (segment2(q) == NULL) p->vis = segment1(q); else if (segment1(q) == NULL) p->vis = segment2(q); /* otherwise take the one with biggest slope */ else if (left_turn(p, q, other1(q)) && !left_turn(p, q, other2(q))) p->vis = segment1(q); else if (!left_turn(p, q, other1(q)) && left_turn(p, q, other2(q))) p->vis = segment2(q); else if (left_turn(q, other2(q), other1(q))) p->vis = segment1(q); else p->vis = segment2(q); /* check that p and q are not on the same boundary and that the edge pq is inside the boundary */ if (p->cat == -1 || p->cat != q->cat || !point_inside(p, (p->x + q->x) * 0.5, (p->y + q->y) * 0.5)) report(p, q, out); } }