/** * R T _ P G _ P L O T * * Calculate the bounding RPP for a poly */ int rt_pg_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) { struct rt_pg_internal *pgp; size_t i; size_t p; pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); VSETALL((*min), INFINITY); VSETALL((*max), -INFINITY); for (p = 0; p < pgp->npoly; p++) { vect_t work[3]; VMOVE(work[0], &pgp->poly[p].verts[0*3]); VMINMAX((*min), (*max), work[0]); VMOVE(work[1], &pgp->poly[p].verts[1*3]); VMINMAX((*min), (*max), work[1]); for (i=2; i < pgp->poly[p].npts; i++) { VMOVE(work[2], &pgp->poly[p].verts[i*3]); VMINMAX((*min), (*max), work[2]); /* Chop off a triangle, and continue */ VMOVE(work[1], work[2]); } } return 0; /* OK */ }
} RT_VISIT_ALL_SOLTABS_END /* * Another pass, no restarting. Assign "piecestate" indices * for those solids which contain pieces. */ RT_VISIT_ALL_SOLTABS_START( stp, rtip ) { if ( stp->st_npieces > 1 ) { /* all pieces must be within model bounding box for pieces * to work correctly. */ VMINMAX( rtip->mdl_min, rtip->mdl_max, stp->st_min ); VMINMAX( rtip->mdl_min, rtip->mdl_max, stp->st_max ); stp->st_piecestate_num = rtip->rti_nsolids_with_pieces++; } if (RT_G_DEBUG&DEBUG_SOLIDS) rt_pr_soltab( stp ); } RT_VISIT_ALL_SOLTABS_END
/** * Create a bounding RPP for an hyp */ int rt_hyp_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) { struct rt_hyp_internal *xip; vect_t hyp_Au, hyp_B, hyp_An, hyp_Bn, hyp_H; vect_t pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8; RT_CK_DB_INTERNAL(ip); xip = (struct rt_hyp_internal *)ip->idb_ptr; RT_HYP_CK_MAGIC(xip); VMOVE(hyp_H, xip->hyp_Hi); VUNITIZE(hyp_H); VMOVE(hyp_Au, xip->hyp_A); VUNITIZE(hyp_Au); VCROSS(hyp_B, hyp_Au, hyp_H); VSETALL((*min), INFINITY); VSETALL((*max), -INFINITY); VSCALE(hyp_B, hyp_B, xip->hyp_b); VREVERSE(hyp_An, xip->hyp_A); VREVERSE(hyp_Bn, hyp_B); VADD3(pt1, xip->hyp_Vi, xip->hyp_A, hyp_B); VADD3(pt2, xip->hyp_Vi, xip->hyp_A, hyp_Bn); VADD3(pt3, xip->hyp_Vi, hyp_An, hyp_B); VADD3(pt4, xip->hyp_Vi, hyp_An, hyp_Bn); VADD4(pt5, xip->hyp_Vi, xip->hyp_A, hyp_B, xip->hyp_Hi); VADD4(pt6, xip->hyp_Vi, xip->hyp_A, hyp_Bn, xip->hyp_Hi); VADD4(pt7, xip->hyp_Vi, hyp_An, hyp_B, xip->hyp_Hi); VADD4(pt8, xip->hyp_Vi, hyp_An, hyp_Bn, xip->hyp_Hi); /* Find the RPP of the rotated axis-aligned hyp bbox - that is, * the bounding box the given hyp would have if its height * vector were in the positive Z direction. This does not give * us an optimal bbox except in the case where the hyp is * actually axis aligned to start with, but it's usually * at least a bit better than the bounding sphere RPP. */ VMINMAX((*min), (*max), pt1); VMINMAX((*min), (*max), pt2); VMINMAX((*min), (*max), pt3); VMINMAX((*min), (*max), pt4); VMINMAX((*min), (*max), pt5); VMINMAX((*min), (*max), pt6); VMINMAX((*min), (*max), pt7); VMINMAX((*min), (*max), pt8); return 0; }
/** * Calculates the bounding Right Parallel Piped (RPP) of the NURB * surface, and returns the minimum and maximum points of the surface. */ int rt_nurb_s_bound(struct face_g_snurb *srf, fastf_t *bmin, fastf_t *bmax) { register fastf_t *p_ptr; /* Mesh pointer */ register int coords; /* Elements per vector */ int i; int rat; VSETALL(bmin, INFINITY); VSETALL(bmax, -INFINITY); if (srf == (struct face_g_snurb *)0) { bu_log("nurb_s_bound: NULL surface\n"); return -1; /* BAD */ } p_ptr = srf->ctl_points; coords = RT_NURB_EXTRACT_COORDS(srf->pt_type); rat = RT_NURB_IS_PT_RATIONAL(srf->pt_type); for (i = (srf->s_size[RT_NURB_SPLIT_ROW] * srf->s_size[RT_NURB_SPLIT_COL]); i > 0; i--) { if (!rat) { VMINMAX(bmin, bmax, p_ptr); } else if (rat) { point_t tmp_pt; if (ZERO(p_ptr[H])) { HPRINT("mesh point", p_ptr); bu_log("nurb_s_bound: H too small\n"); } else { HDIVIDE(tmp_pt, p_ptr); VMINMAX(bmin, bmax, tmp_pt); } } p_ptr += coords; } return 0; /* OK */ }
int PolylineBBox( const ON_Polyline& pline, ON_BoundingBox* bbox ) { ON_3dPoint min = pline[0], max = pline[0]; for (int i = 1; i < pline.Count(); i++) { VMINMAX(min, max, pline[i]); } bbox->m_min = min; bbox->m_max = max; return 0; }
/** * Calculate a bounding RPP for an ARBN */ int rt_arbn_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) { size_t i, j, k; struct rt_arbn_internal *aip; RT_CK_DB_INTERNAL(ip); aip = (struct rt_arbn_internal *)ip->idb_ptr; RT_ARBN_CK_MAGIC(aip); VSETALL((*min), INFINITY); VSETALL((*max), -INFINITY); /* Discover all vertices, use to calculate RPP */ for (i = 0; i < aip->neqn-2; i++) { for (j = i+1; j < aip->neqn-1; j++) { double dot; /* If normals are parallel, no intersection */ dot = VDOT(aip->eqn[i], aip->eqn[j]); if (((dot) <= -SMALL_FASTF) ? (NEAR_EQUAL((dot), -1.0, RT_DOT_TOL)) : (NEAR_EQUAL((dot), 1.0, RT_DOT_TOL))) continue; /* Have an edge line, isect with higher numbered planes */ for (k = j + 1; k < aip->neqn; k++) { size_t m; size_t next_k; point_t pt; next_k = 0; if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue; /* See if point is outside arb */ for (m = 0; m < aip->neqn; m++) { if (i == m || j == m || k == m) continue; if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > RT_LEN_TOL) { next_k = 1; break; } } if (next_k != 0) continue; VMINMAX((*min), (*max), pt); } } } return 0; }
/** * Returns - * 0 OK * !0 failure */ int rt_arbn_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip) { struct rt_arbn_internal *aip; vect_t work; fastf_t f; size_t i; size_t j; size_t k; int *used = (int *)0; /* plane eqn use count */ const struct bn_tol *tol = &rtip->rti_tol; RT_CK_DB_INTERNAL(ip); aip = (struct rt_arbn_internal *)ip->idb_ptr; RT_ARBN_CK_MAGIC(aip); used = (int *)bu_malloc(aip->neqn*sizeof(int), "arbn used[]"); /* * ARBN must be convex. Test for concavity. * Byproduct is an enumeration of all the vertices, * which are used to make the bounding RPP. No need * to call the bbox routine, as the work must be duplicated * here to count faces. */ /* Zero face use counts * and make sure normal vectors are unit vectors */ for (i = 0; i < aip->neqn; i++) { double normalLen = MAGNITUDE(aip->eqn[i]); double scale; if (ZERO(normalLen)) { bu_log("arbn has zero length normal vector\n"); return 1; } scale = 1.0 / normalLen; HSCALE(aip->eqn[i], aip->eqn[i], scale); used[i] = 0; } for (i = 0; i < aip->neqn-2; i++) { for (j=i+1; j<aip->neqn-1; j++) { double dot; /* If normals are parallel, no intersection */ dot = VDOT(aip->eqn[i], aip->eqn[j]); if (BN_VECT_ARE_PARALLEL(dot, tol)) continue; /* Have an edge line, isect with higher numbered planes */ for (k=j+1; k<aip->neqn; k++) { size_t m; size_t next_k; point_t pt; next_k = 0; if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue; /* See if point is outside arb */ for (m = 0; m < aip->neqn; m++) { if (i == m || j == m || k == m) continue; if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) { next_k = 1; break; } } if (next_k != 0) continue; VMINMAX(stp->st_min, stp->st_max, pt); /* Increment "face used" counts */ used[i]++; used[j]++; used[k]++; } } } /* If any planes were not used, then arbn is not convex */ for (i = 0; i < aip->neqn; i++) { if (used[i] != 0) continue; /* face was used */ bu_log("arbn(%s) face %zu unused, solid is not convex\n", stp->st_name, i); bu_free((char *)used, "arbn used[]"); return -1; /* BAD */ } bu_free((char *)used, "arbn used[]"); stp->st_specific = (void *)aip; ip->idb_ptr = ((void *)0); /* indicate we stole it */ VADD2SCALE(stp->st_center, stp->st_min, stp->st_max, 0.5); VSUB2SCALE(work, stp->st_max, stp->st_min, 0.5); f = work[X]; if (work[Y] > f) f = work[Y]; if (work[Z] > f) f = work[Z]; stp->st_aradius = f; stp->st_bradius = MAGNITUDE(work); return 0; /* OK */ }