Example #1
0
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);
}
Example #4
0
/**
 * 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(&regionbits->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);
}