int test_bu_bitv_and(char *inp1 , char *inp2 , char *exp) { struct bu_bitv *res_bitv , *res_bitv1 , *result; struct bu_vls *a , *b; int pass; a = bu_vls_vlsinit(); b = bu_vls_vlsinit(); res_bitv1 = bu_hex_to_bitv(inp1); res_bitv = bu_hex_to_bitv(inp2); result = bu_hex_to_bitv(exp); bu_bitv_and(res_bitv1,res_bitv); bu_bitv_vls(a,res_bitv1); bu_bitv_vls(b,result); if (!bu_strcmp(a->vls_str , b->vls_str)) { printf("\nbu_bitv_and test PASSED Input1:%s Input2:%s Output:%s", inp1, inp2, exp); pass = 1; } else { printf("\nbu_bitv_and test FAILED Input1:%s Input2:%s Expected:%s", inp1, inp2, exp); pass = 0; } bu_bitv_free(res_bitv); bu_bitv_free(res_bitv1); bu_bitv_free(result); return pass; }
static void clean_pmp(struct plate_mode *pmp) { int i; for (i = 0; i < pmp->num_bots; i++) { bu_free(pmp->bots[i]->faces, "pmp->bots[i]->faces"); bu_free(pmp->bots[i]->vertices, "pmp->bots[i]->vertices"); if ((pmp->bots[i]->bot_flags & RT_BOT_PLATE) || (pmp->bots[i]->bot_flags & RT_BOT_PLATE_NOCOS)) { bu_free(pmp->bots[i]->thickness, "pmp->bots[i]->thickness"); } if (pmp->bots[i]->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) { bu_free(pmp->bots[i]->normals, "pmp->bots[i]->normals"); } if ((pmp->bots[i]->bot_flags & RT_BOT_PLATE) || (pmp->bots[i]->bot_flags & RT_BOT_PLATE_NOCOS)) { bu_bomb("about to free pmp->bots[i]->face_mode\n"); bu_bitv_free(pmp->bots[i]->face_mode); } bu_free(pmp->bots[i], "bots"); pmp->bots[i] = (struct rt_bot_internal *)NULL; } pmp->num_bots = 0; pmp->num_nonbots = 0; }
void writePlateBot ( rt_wdb* wdbp, Form& form, bool translate ) { char name[NAMELEN + 1]; fastf_t vertices[MAX_NPTS * 3]; if (translate) { for (size_t i = 0; i < form.data.bot.num_vertices; ++i) { vertices[i * 3] = (form.data.bot.vertices[i * 3] + form.tr_vec[0]) * IntavalUnitInMm; vertices[i * 3 + 1] = (form.data.bot.vertices[i * 3 + 1] + form.tr_vec[1]) * IntavalUnitInMm; vertices[i * 3 + 2] = (form.data.bot.vertices[i * 3 + 2] + form.tr_vec[2]) * IntavalUnitInMm; } } else { for (size_t i = 0; i<form.data.bot.num_vertices; ++i) { vertices[i * 3] = form.data.bot.vertices[i * 3] * IntavalUnitInMm; vertices[i * 3 + 1] = form.data.bot.vertices[i * 3 + 1] * IntavalUnitInMm; vertices[i * 3 + 2] = form.data.bot.vertices[i * 3 + 2] * IntavalUnitInMm; } } fastf_t thickness[MAX_TRIANGLES]; for (size_t i = 0; i < form.data.bot.num_faces; ++i) thickness[i] = form.thickness * IntavalUnitInMm; bu_bitv* faceMode = bu_bitv_new(form.data.bot.num_faces); sprintf(name, "s%lu.pbot", (long unsigned)++bot_counter); mk_bot(wdbp, name, RT_BOT_PLATE, RT_BOT_UNORIENTED, 0, form.data.bot.num_vertices, form.data.bot.num_faces, vertices, form.data.bot.faces, thickness, faceMode); addToRegion(form.compnr, name); if (form.s_compnr >= 1000) excludeFromRegion(form.s_compnr, name); bu_bitv_free(faceMode); }
/** * Given a ray, shoot it at all the relevant parts of the model, * (building the HeadSeg chain), and then call rt_boolregions() to * build and evaluate the partition chain. If the ray actually hit * anything, call the application's a_hit() routine with a pointer to * the partition chain, otherwise, call the application's a_miss() * routine. * * It is important to note that rays extend infinitely only in the * positive direction. The ray is composed of all points P, where * * P = r_pt + K * r_dir * * for K ranging from 0 to +infinity. There is no looking backwards. * * It is also important to note that the direction vector r_dir must * have unit length; this is mandatory, and is not ordinarily checked, * in the name of efficiency. * * Input: Pointer to an application structure, with these mandatory fields: * a_ray.r_pt Starting point of ray to be fired * a_ray.r_dir UNIT VECTOR with direction to fire in (dir cosines) * a_hit Routine to call when something is hit * a_miss Routine to call when ray misses everything * * Calls user's a_miss() or a_hit() routine as appropriate. Passes * a_hit() routine list of partitions, with only hit_dist fields * valid. Normal computation deferred to user code, to avoid needless * computation here. * * Returns: whatever the application function returns (an int). * * NOTE: The application functions may call rt_shootray() recursively. * Thus, none of the local variables may be static. * * An open issue for execution in a PARALLEL environment is locking of * the statistics variables. */ int rt_vshootray(struct application *ap) { struct seg *HeadSeg; int ret; vect_t inv_dir; /* inverses of ap->a_ray.r_dir */ struct bu_bitv *solidbits; /* bits for all solids shot so far */ struct bu_ptbl *regionbits; /* bits for all involved regions */ char *status; struct partition InitialPart; /* Head of Initial Partitions */ struct partition FinalPart; /* Head of Final Partitions */ int nrays = 1; /* for now */ int vlen; int id; int i; struct soltab **ary_stp; /* array of pointers */ struct xray **ary_rp; /* array of pointers */ struct seg *ary_seg; /* array of structures */ struct rt_i *rtip; int done; #define BACKING_DIST (-2.0) /* mm to look behind start point */ rtip = ap->a_rt_i; RT_AP_CHECK(ap); if (!ap->a_resource) { ap->a_resource = &rt_uniresource; } RT_CK_RESOURCE(ap->a_resource); if (RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION)) { bu_log("\n**********mshootray cpu=%d %d, %d lvl=%d (%s)\n", ap->a_resource->re_cpu, ap->a_x, ap->a_y, ap->a_level, ap->a_purpose != (char *)0 ? ap->a_purpose : "?"); VPRINT("Pnt", ap->a_ray.r_pt); VPRINT("Dir", ap->a_ray.r_dir); } rtip->rti_nrays++; if (rtip->needprep) rt_prep(rtip); /* Allocate dynamic memory */ vlen = nrays * rtip->rti_maxsol_by_type; ary_stp = (struct soltab **)bu_calloc(vlen, sizeof(struct soltab *), "*ary_stp[]"); ary_rp = (struct xray **)bu_calloc(vlen, sizeof(struct xray *), "*ary_rp[]"); ary_seg = (struct seg *)bu_calloc(vlen, sizeof(struct seg), "ary_seg[]"); /**** for each ray, do this ****/ InitialPart.pt_forw = InitialPart.pt_back = &InitialPart; FinalPart.pt_forw = FinalPart.pt_back = &FinalPart; HeadSeg = RT_SEG_NULL; solidbits = rt_get_solidbitv(rtip->nsolids, ap->a_resource); if (BU_LIST_IS_EMPTY(&ap->a_resource->re_region_ptbl)) { BU_ALLOC(regionbits, struct bu_ptbl); bu_ptbl_init(regionbits, 7, "rt_shootray() regionbits ptbl"); } else { regionbits = BU_LIST_FIRST(bu_ptbl, &ap->a_resource->re_region_ptbl); BU_LIST_DEQUEUE(®ionbits->l); BU_CK_PTBL(regionbits); } /* Compute the inverse of the direction cosines */ if (!ZERO(ap->a_ray.r_dir[X])) { inv_dir[X]=1.0/ap->a_ray.r_dir[X]; } else { inv_dir[X] = INFINITY; ap->a_ray.r_dir[X] = 0.0; } if (!ZERO(ap->a_ray.r_dir[Y])) { inv_dir[Y]=1.0/ap->a_ray.r_dir[Y]; } else { inv_dir[Y] = INFINITY; ap->a_ray.r_dir[Y] = 0.0; } if (!ZERO(ap->a_ray.r_dir[Z])) { inv_dir[Z]=1.0/ap->a_ray.r_dir[Z]; } else { inv_dir[Z] = INFINITY; ap->a_ray.r_dir[Z] = 0.0; } /* * XXX handle infinite solids here, later. */ /* * If ray does not enter the model RPP, skip on. * If ray ends exactly at the model RPP, trace it. */ if (!rt_in_rpp(&ap->a_ray, inv_dir, rtip->mdl_min, rtip->mdl_max) || ap->a_ray.r_max < 0.0) { rtip->nmiss_model++; if (ap->a_miss) ret = ap->a_miss(ap); else ret = 0; status = "MISS model"; goto out; } /* For each type of solid to be shot at, assemble the vectors */ for (id = 1; id <= ID_MAX_SOLID; id++) { register int nsol; if ((nsol = rtip->rti_nsol_by_type[id]) <= 0) continue; /* For each instance of this solid type */ for (i = nsol-1; i >= 0; i--) { ary_stp[i] = rtip->rti_sol_by_type[id][i]; ary_rp[i] = &(ap->a_ray); /* XXX, sb [ray] */ ary_seg[i].seg_stp = SOLTAB_NULL; BU_LIST_INIT(&ary_seg[i].l); } /* bounding box check */ /* bit vector per ray check */ /* mark elements to be skipped with ary_stp[] = SOLTAB_NULL */ ap->a_rt_i->nshots += nsol; /* later: skipped ones */ if (OBJ[id].ft_vshot) { OBJ[id].ft_vshot(ary_stp, ary_rp, ary_seg, nsol, ap); } else { vshot_stub(ary_stp, ary_rp, ary_seg, nsol, ap); } /* set bits for all solids shot at for each ray */ /* append resulting seg list to input for boolweave */ for (i = nsol-1; i >= 0; i--) { register struct seg *seg2; if (ary_seg[i].seg_stp == SOLTAB_NULL) { /* MISS */ ap->a_rt_i->nmiss++; continue; } ap->a_rt_i->nhits++; /* For now, do it the slow way. sb [ray] */ /* MUST dup it -- all segs have to live till after a_hit() */ RT_GET_SEG(seg2, ap->a_resource); *seg2 = ary_seg[i]; /* struct copy */ /* rt_boolweave(seg2, &InitialPart, ap); */ bu_bomb("FIXME: need to call boolweave here"); /* Add seg chain to list of used segs awaiting reclaim */ #if 0 /* FIXME: need to use waiting_segs/finished_segs here in * conjunction with rt_boolweave() { register struct seg *seg3 = seg2; while (seg3->seg_next != RT_SEG_NULL) seg3 = seg3->seg_next; seg3->seg_next = HeadSeg; HeadSeg = seg2; } */ #endif } } /* * Ray has finally left known space. */ if (InitialPart.pt_forw == &InitialPart) { if (ap->a_miss) ret = ap->a_miss(ap); else ret = 0; status = "MISSed all primitives"; goto freeup; } /* * All intersections of the ray with the model have been computed. * Evaluate the boolean trees over each partition. */ done = rt_boolfinal(&InitialPart, &FinalPart, BACKING_DIST, INFINITY, regionbits, ap, solidbits); if (done > 0) goto hitit; if (FinalPart.pt_forw == &FinalPart) { if (ap->a_miss) ret = ap->a_miss(ap); else ret = 0; status = "MISS bool"; goto freeup; } /* * Ray/model intersections exist. Pass the list to the user's * a_hit() routine. Note that only the hit_dist elements of * pt_inhit and pt_outhit have been computed yet. To compute both * hit_point and hit_normal, use the * * RT_HIT_NORMAL(NULL, hitp, stp, rayp, 0); * * macro. To compute just hit_point, use * * VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir); */ hitit: if (RT_G_DEBUG&DEBUG_SHOOT) rt_pr_partitions(rtip, &FinalPart, "a_hit()"); if (ap->a_hit) ret = ap->a_hit(ap, &FinalPart, HeadSeg/* &finished_segs */); else ret = 0; status = "HIT"; /* * Processing of this ray is complete. Free dynamic resources. */ freeup: { register struct partition *pp; /* Free up initial partition list */ for (pp = InitialPart.pt_forw; pp != &InitialPart;) { register struct partition *newpp; newpp = pp; pp = pp->pt_forw; FREE_PT(newpp, ap->a_resource); } /* Free up final partition list */ for (pp = FinalPart.pt_forw; pp != &FinalPart;) { register struct partition *newpp; newpp = pp; pp = pp->pt_forw; FREE_PT(newpp, ap->a_resource); } } /* Segs can't be freed until after a_hit() has returned */ #if 0 /* FIXME: depends on commented out code above */ if (HeadSeg) RT_FREE_SEG_LIST(HeadSeg, ap->a_resource); #endif out: bu_free((char *)ary_stp, "*ary_stp[]"); bu_free((char *)ary_rp, "*ary_rp[]"); bu_free((char *)ary_seg, "ary_seg[]"); if (solidbits != NULL) { bu_bitv_free(solidbits); } if (RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION)) { bu_log("----------mshootray cpu=%d %d, %d lvl=%d (%s) %s ret=%d\n", ap->a_resource->re_cpu, ap->a_x, ap->a_y, ap->a_level, ap->a_purpose != (char *)0 ? ap->a_purpose : "?", status, ret); } return ret; }
void writeRingModeBox ( rt_wdb* wdbp, Form& form, bool translate ) { char name[NAMELEN + 1]; // get the transformed outer points vect_t outer[MAX_NPTS]; if (translate) { for (size_t i = 0; i < form.npts; ++i) VADD2(outer[i], form.data.pt[i], form.tr_vec); } else { for (size_t i = 0; i < form.npts; ++i) { VMOVE(outer[i], form.data.pt[i]); } } for (size_t i1 = 0; i1 < form.npts; ++i1) { VSCALE(outer[i1], outer[i1], IntavalUnitInMm); } // compute inner points vect_t inner[MAX_NPTS]; for (size_t i2 = 0; i2 < form.npts; ++i2) { vect_t a, b, c; VMOVE(a, outer[i2]); if (i2 == 0) { VMOVE(b, outer[i2 + 1]); VMOVE(c, outer[form.npts-1]); } else if (i2 == form.npts-1) { VMOVE(b, outer[0]); VMOVE(c, outer[i2 - 1]); } else { VMOVE(b, outer[i2 + 1]); VMOVE(c, outer[i2 - 1]); } vect_t b_v, c_v; VSUB2(b_v, b, a); VSUB2(c_v, c, a); vect_t n_v; VCROSS(n_v, b_v, c_v); // with on b_v vect_t width_b_v; VCROSS(width_b_v, b_v, n_v); if (VDOT(width_b_v, c_v) < 0) VREVERSE(width_b_v, width_b_v); VUNITIZE(width_b_v); VSCALE(width_b_v, width_b_v, form.width * IntavalUnitInMm); // with on c_v vect_t width_c_v; VCROSS(width_c_v, c_v, n_v); if (VDOT(width_c_v, b_v) < 0) VREVERSE(width_c_v, width_c_v); VUNITIZE(width_c_v); VSCALE(width_c_v, width_c_v, form.width * IntavalUnitInMm); // intersection VUNITIZE(b_v); VUNITIZE(c_v); vect_t cb_v; VSUB2(cb_v, b_v, c_v); fastf_t l_cb_v = MAGNITUDE(cb_v); if (!NEAR_ZERO(l_cb_v, VUNITIZE_TOL)) { vect_t width_cb_v; VSUB2(width_cb_v, width_b_v, width_c_v); vect_t s_b_v; VSCALE(s_b_v, b_v, MAGNITUDE(width_cb_v) / l_cb_v); vect_t res; VADD2(res, a, width_c_v); VADD2(res, res, s_b_v); VMOVE(inner[i2], res); } else { VMOVE(inner[i2], outer[i2]); } } // bot parameters // vertices size_t num_vertices = 0; size_t outer_i[MAX_NPTS]; size_t inner_i[MAX_NPTS]; fastf_t vertices[MAX_NPTS * 3]; for (size_t i3 = 0; i3 < form.npts; ++i3) { size_t i = 0; // outer // search for duplicate vertex for (; i < num_vertices; ++i) { if (NEAR_EQUAL(outer[i3][0], vertices[3 * i], VUNITIZE_TOL) && NEAR_EQUAL(outer[i3][1], vertices[3 * i + 1], VUNITIZE_TOL) && NEAR_EQUAL(outer[i3][2], vertices[3 * i + 2], VUNITIZE_TOL)) { outer_i[i3] = i; break; } } if (i == num_vertices) { // add a new vertex vertices[num_vertices * 3] = outer[i3][0]; vertices[num_vertices * 3 + 1] = outer[i3][1]; vertices[num_vertices * 3 + 2] = outer[i3][2]; outer_i[i3] = num_vertices; ++num_vertices; } // inner // search for duplicate vertex for (i = 0; i < num_vertices; ++i) { if (NEAR_EQUAL(inner[i3][0], vertices[3 * i], VUNITIZE_TOL) && NEAR_EQUAL(inner[i3][1], vertices[3 * i + 1], VUNITIZE_TOL) && NEAR_EQUAL(inner[i3][2], vertices[3 * i + 2], VUNITIZE_TOL)) { inner_i[i3] = i; break; } } if (i == num_vertices) { // add a new vertex vertices[num_vertices * 3] = inner[i3][0]; vertices[num_vertices * 3 + 1] = inner[i3][1]; vertices[num_vertices * 3 + 2] = inner[i3][2]; inner_i[i3] = num_vertices; ++num_vertices; } } // faces size_t num_faces = 0; int faces[MAX_TRIANGLES * 3]; for (size_t i4 = 0; i4 < form.npts; ++i4) { size_t nextIndex = (i4 + 1) % form.npts; addTriangle(faces, num_faces, outer_i[i4], outer_i[nextIndex], inner_i[i4]); addTriangle(faces, num_faces, inner_i[i4], outer_i[nextIndex], inner_i[nextIndex]); } fastf_t thickness[MAX_TRIANGLES]; for (size_t i5 = 0; i5 < num_faces; ++i5) thickness[i5] = form.thickness * IntavalUnitInMm; bu_bitv* faceMode = bu_bitv_new(num_faces); sprintf(name, "s%lu.pbot", (long unsigned)++bot_counter); mk_bot(wdbp, name, RT_BOT_PLATE, RT_BOT_UNORIENTED, 0, num_vertices, num_faces, vertices, faces, thickness, faceMode); addToRegion(form.compnr, name); if (form.s_compnr >= 1000) excludeFromRegion(form.s_compnr, name); bu_bitv_free(faceMode); }