Example #1
0
BrlCadInterface::BrlCadInterface(QString file_name, QString object_name)
{
  m_Rtip = rt_dirbuild(qPrintable(file_name), m_IdBuf, sizeof(m_IdBuf));
  if (m_Rtip == RTI_NULL) {
    EG_ERR_RETURN("Unable to open BRL-CAD database!");
  }
  if (rt_gettree(m_Rtip, qPrintable(object_name)) < 0) {
    EG_ERR_RETURN("unable to access selected object");
  }
  rt_prep_parallel(m_Rtip, 1);
  application ap = {0};
  m_Ap = ap;
  m_Ap.a_rt_i   = m_Rtip;

  setName("BRL-CAD interface");
  m_ShootRayImplemented = true;

  //m_Ap.a_onehit = 1;
}
Example #2
0
/**
 * START HERE
 *
 * This is where it all begins.
 */
int
main(int argc, char **argv)
{
    /* Every application needs one of these.  The "application"
     * structure carries information about how the ray-casting should
     * be performed.  Defined in the raytrace.h header.
     */
    struct application	ap;

    /* The "raytrace instance" structure contains definitions for
     * librt which are specific to the particular model being
     * processed.  One copy exists for each model.  Defined in
     * the raytrace.h header and is returned by rt_dirbuild().
     */
    static struct rt_i *rtip;

    /* optional parameter to rt_dirbuild() what can be used to capture
     * a title if the geometry database has one set.
     */
    char title[1024] = {0};

    /* Check for command-line arguments.  Make sure we have at least a
     * geometry file and one geometry object on the command line.
     */
    if (argc < 3) {
	bu_exit(1, "Usage: %s model.g objects...\n", argv[0]);
    }

    /* Load the specified geometry database (i.e., a ".g" file).
     * rt_dirbuild() returns an "instance" pointer which describes the
     * database to be raytraced.  It also gives you back the title
     * string if you provide a buffer.  This builds a directory of the
     * geometry (i.e., a table of contents) in the file.
     */
    rtip = rt_dirbuild(argv[1], title, sizeof(title));
    if (rtip == RTI_NULL) {
	bu_exit(2, "Building the database directory for [%s] FAILED\n", argv[1]);
    }

    /* Display the geometry database title obtained during
     * rt_dirbuild if a title is set.
     */
    if (title[0]) {
	bu_log("Title:\n%s\n", title);
    }

    /* Walk the geometry trees.  Here you identify any objects in the
     * database that you want included in the ray trace by iterating
     * of the object names that were specified on the command-line.
     */
    while (argc > 2)  {
	if (rt_gettree(rtip, argv[2]) < 0)
	    bu_log("Loading the geometry for [%s] FAILED\n", argv[2]);
	argc--;
	argv++;
    }

    /* This next call gets the database ready for ray tracing.  This
     * causes some values to be precomputed, sets up space
     * partitioning, computes boudning volumes, etc.
     */
    rt_prep_parallel(rtip, 1);

    /* initialize all values in application structure to zero */
    RT_APPLICATION_INIT(&ap);

    /* your application uses the raytrace instance containing the
     * geometry we loaded.  this describes what we're shooting at.
     */
    ap.a_rt_i = rtip;

    /* stop at the first point of intersection or shoot all the way
     * through (defaults to 0 to shoot all the way through).
     */
    ap.a_onehit = 0;

    /* Set the ray start point and direction rt_shootray() uses these
     * two to determine what ray to fire.  In this case we simply
     * shoot down the z axis toward the origin from 10 meters away.
     *
     * It's worth nothing that librt assumes units of millimeters.
     * All geometry is stored as millimeters regardless of the units
     * set during editing.  There are libbu routines for performing
     * unit conversions if desired.
     */
    VSET(ap.a_ray.r_pt, 0.0, 0.0, 10000.0);
    VSET(ap.a_ray.r_dir, 0.0, 0.0, -1.0);

    /* Simple debug printing */
    VPRINT("Pnt", ap.a_ray.r_pt);
    VPRINT("Dir", ap.a_ray.r_dir);

    /* This is what callback to perform on a hit. */
    ap.a_hit = hit;

    /* This is what callback to perform on a miss. */
    ap.a_miss = miss;

    /* Shoot the ray. */
    (void)rt_shootray(&ap);

    /* A real application would probably set up another ray and fire
     * again or do something a lot more complex in the callbacks.
     */

    return 0;
}
Example #3
0
/**
 * voxelize function takes raytrace instance and user parameters as inputs
 */
void
voxelize(struct rt_i *rtip, fastf_t sizeVoxel[3], int levelOfDetail, void (*create_boxes)(void *callBackData, int x, int y, int z, const char *regionName, fastf_t percentageFill), void *callBackData)
{
    struct rayInfo voxelHits;
    int            numVoxel[3];
    int            yMin;
    int            zMin;
	int            i, j, k, rayNum;
    fastf_t        *voxelArray;
    fastf_t        rayTraceDistance;
    fastf_t        effectiveDistance;

    /* get bounding box values etc. */
    rt_prep_parallel(rtip, 1);

    /* calculate number of voxels in each dimension */
    numVoxel[0] = (int)(((rtip->mdl_max)[0] - (rtip->mdl_min)[0])/sizeVoxel[0]) + 1;
    numVoxel[1] = (int)(((rtip->mdl_max)[1] - (rtip->mdl_min)[1])/sizeVoxel[1]) + 1;
    numVoxel[2] = (int)(((rtip->mdl_max)[2] - (rtip->mdl_min)[2])/sizeVoxel[2]) + 1;

    if (EQUAL(numVoxel[0] - 1, (((rtip->mdl_max)[0] - (rtip->mdl_min)[0])/sizeVoxel[0])))
	numVoxel[0] -=1;

    if (EQUAL(numVoxel[1] - 1, (((rtip->mdl_max)[1] - (rtip->mdl_min)[1])/sizeVoxel[1])))
	numVoxel[1] -=1;

    if (EQUAL(numVoxel[2] - 1, (((rtip->mdl_max)[2] - (rtip->mdl_min)[2])/sizeVoxel[2])))
	numVoxel[2] -=1;

    voxelHits.sizeVoxel = sizeVoxel[0];

    /* voxelArray stores the distance in path of ray inside a voxel which is filled
     * initialize with 0s */
    voxelArray = (fastf_t *)bu_calloc(numVoxel[0], sizeof(fastf_t), "voxelize:voxelArray");

    /* regionList holds the names of voxels inside the voxels
     * initialize with NULLs */
    voxelHits.regionList = (struct voxelRegion *)bu_calloc(numVoxel[0], sizeof(struct voxelRegion), "voxelize:regionList");

    /* minimum value of bounding box in Y and Z directions */
    yMin = (int)((rtip->mdl_min)[1]);
    zMin = (int)((rtip->mdl_min)[2]);

    BU_ASSERT_LONG(levelOfDetail, >, 0);
    /* 1.0 / (levelOfDetail + 1) and effectiveDistance have to be used multiple times in the following loops */
    rayTraceDistance  = 1. / levelOfDetail;
    effectiveDistance = levelOfDetail * levelOfDetail * sizeVoxel[0];

    /* start shooting */
    for (i = 0; i < numVoxel[2]; ++i) {
	for (j = 0; j < numVoxel[1]; ++j) {
	    struct application ap;

	    RT_APPLICATION_INIT(&ap);
	    ap.a_rt_i   = rtip;
	    ap.a_onehit = 0;
	    VSET(ap.a_ray.r_dir, 1., 0., 0.);

	    ap.a_hit  = hit_voxelize;
	    ap.a_miss = NULL;
	    ap.a_uptr = &voxelHits;

	    voxelHits.fillDistances = voxelArray;

	    for (rayNum = 0; rayNum < levelOfDetail; ++rayNum) {
		for (k = 0; k < levelOfDetail; ++k) {

		    /* ray is hit through evenly spaced points of the unit sized voxels */
		    VSET(ap.a_ray.r_pt, (rtip->mdl_min)[0] - 1.,
			                yMin + (j + (k + 0.5) * rayTraceDistance) * sizeVoxel[1],
			                zMin + (i + (rayNum + 0.5) * rayTraceDistance) * sizeVoxel[2]);
		    rt_shootray(&ap);
		}
	    }

	    /* output results via a call-back supplied by user*/
	    for (k = 0; k < numVoxel[0]; ++k) {
		if (voxelHits.regionList[k].regionName == NULL)
		    /* an air voxel */
		    create_boxes(callBackData, k, j, i, NULL, 0.);
		else {
		    struct voxelRegion *tmp = voxelHits.regionList + k;
		    struct voxelRegion *old = tmp->nextRegion;

		    create_boxes(callBackData, k, j, i, tmp->regionName, tmp->regionDistance / effectiveDistance);

		    if (tmp->regionName != 0)
			bu_free(tmp->regionName, "voxelize:voxelRegion:regionName");

		    while (old != NULL) {
			tmp = old;
			create_boxes(callBackData, k, j, i, tmp->regionName, tmp->regionDistance / effectiveDistance);
			old = tmp->nextRegion;

			/* free the space allocated for new regions */
			if (tmp->regionName != 0)
			    bu_free(tmp->regionName, "voxelize:voxelRegion:regionName");

			BU_FREE(tmp, struct voxelRegion);
		    }
		}

		voxelArray[k] = 0.;
		voxelHits.regionList[k].regionName     = NULL;
		voxelHits.regionList[k].nextRegion     = NULL;
		voxelHits.regionList[k].regionDistance = 0.;
	    }
	}
    }

    bu_free(voxelArray, "voxelize:voxelArray");
    bu_free(voxelHits.regionList, "voxelize:regionList");
}
/* 0 = no difference within tolerance, 1 = difference >= tolerance */
int
analyze_raydiff(/* TODO - decide what to return.  Probably some sort of left, common, right segment sets.  See what rtcheck does... */
	struct db_i *dbip, const char *obj1, const char *obj2, struct bn_tol *tol)
{
    int ret;
    int count = 0;
    struct rt_i *rtip;
    int ncpus = bu_avail_cpus();
    point_t min, mid, max;
    struct rt_pattern_data *xdata, *ydata, *zdata;
    fastf_t *rays;
    struct raydiff_container *state;

    if (!dbip || !obj1 || !obj2 || !tol) return 0;

    rtip = rt_new_rti(dbip);
    if (rt_gettree(rtip, obj1) < 0) return -1;
    if (rt_gettree(rtip, obj2) < 0) return -1;
    rt_prep_parallel(rtip, 1);


    /* Now we've got the bounding box - set up the grids */
    VMOVE(min, rtip->mdl_min);
    VMOVE(max, rtip->mdl_max);
    VSET(mid, (max[0] - min[0])/2, (max[1] - min[1])/2, (max[2] - min[2])/2);

    BU_GET(xdata, struct rt_pattern_data);
    VSET(xdata->center_pt, min[0] - 0.1 * min[0], mid[1], mid[2]);
    VSET(xdata->center_dir, 1, 0, 0);
    xdata->vn = 2;
    xdata->pn = 2;
    xdata->n_vec = (vect_t *)bu_calloc(xdata->vn + 1, sizeof(vect_t), "vects array");
    xdata->n_p = (fastf_t *)bu_calloc(xdata->pn + 1, sizeof(fastf_t), "params array");
    xdata->n_p[0] = 50; /* TODO - get tolerances from caller */
    xdata->n_p[1] = 50;
    VSET(xdata->n_vec[0], 0, max[1], 0);
    VSET(xdata->n_vec[1], 0, 0, max[2]);
    ret = rt_pattern(xdata, RT_PATTERN_RECT_ORTHOGRID);
    bu_free(xdata->n_vec, "x vec inputs");
    bu_free(xdata->n_p, "x p inputs");
    if (ret < 0) return -1;


    BU_GET(ydata, struct rt_pattern_data);
    VSET(ydata->center_pt, mid[0], min[1] - 0.1 * min[1], mid[2]);
    VSET(ydata->center_dir, 0, 1, 0);
    ydata->vn = 2;
    ydata->pn = 2;
    ydata->n_vec = (vect_t *)bu_calloc(ydata->vn + 1, sizeof(vect_t), "vects array");
    ydata->n_p = (fastf_t *)bu_calloc(ydata->pn + 1, sizeof(fastf_t), "params array");
    ydata->n_p[0] = 50; /* TODO - get tolerances from caller */
    ydata->n_p[1] = 50;
    VSET(ydata->n_vec[0], max[0], 0, 0);
    VSET(ydata->n_vec[1], 0, 0, max[2]);
    ret = rt_pattern(ydata, RT_PATTERN_RECT_ORTHOGRID);
    bu_free(ydata->n_vec, "y vec inputs");
    bu_free(ydata->n_p, "y p inputs");
    if (ret < 0) return -1;

    BU_GET(zdata, struct rt_pattern_data);
    VSET(zdata->center_pt, mid[0], mid[1], min[2] - 0.1 * min[2]);
    VSET(zdata->center_dir, 0, 0, 1);
    zdata->vn = 2;
    zdata->pn = 2;
    zdata->n_vec = (vect_t *)bu_calloc(zdata->vn + 1, sizeof(vect_t), "vects array");
    zdata->n_p = (fastf_t *)bu_calloc(zdata->pn + 1, sizeof(fastf_t), "params array");
    zdata->n_p[0] = 50; /* TODO - get tolerances from caller */
    zdata->n_p[1] = 50;
    VSET(zdata->n_vec[0], max[0], 0, 0);
    VSET(zdata->n_vec[1], 0, max[1], 0);
    ret = rt_pattern(zdata, RT_PATTERN_RECT_ORTHOGRID);
    bu_free(zdata->n_vec, "x vec inputs");
    bu_free(zdata->n_p, "x p inputs");
    if (ret < 0) return -1;

    /* Consolidate the grids into a single ray array */
    {
	size_t i, j;
	rays = (fastf_t *)bu_calloc((xdata->ray_cnt + ydata->ray_cnt + zdata->ray_cnt + 1) * 6, sizeof(fastf_t), "rays");
	count = 0;
	for (i = 0; i < xdata->ray_cnt; i++) {
	    for (j = 0; j < 6; j++) {
		rays[6*count+j] = xdata->rays[6*i + j];
	    }
	    count++;
	}
	for (i = 0; i < ydata->ray_cnt; i++) {
	    for (j = 0; j < 6; j++) {
		rays[6*count+j] = ydata->rays[6*i + j];
	    }
	    count++;
	}
	for (i = 0; i < zdata->ray_cnt; i++) {
	    for (j = 0; j < 6; j++) {
		rays[6*count+j] = zdata->rays[6*i+j];
	    }
	    count++;
	}

    }
    bu_free(xdata->rays, "x rays");
    bu_free(ydata->rays, "y rays");
    bu_free(zdata->rays, "z rays");
    BU_PUT(xdata, struct rt_pattern_data);
    BU_PUT(ydata, struct rt_pattern_data);
    BU_PUT(zdata, struct rt_pattern_data);

    bu_log("ray cnt: %d\n", count);

    {
	int i, j;
	ncpus = 2;
	state = (struct raydiff_container *)bu_calloc(ncpus+1, sizeof(struct raydiff_container), "resources");
	for (i = 0; i < ncpus+1; i++) {
	    state[i].rtip = rtip;
	    state[i].tol = 0.5;
	    state[i].ncpus = ncpus;
	    state[i].left_name = bu_strdup(obj1);
	    state[i].right_name = bu_strdup(obj2);
	    BU_GET(state[i].resp, struct resource);
	    rt_init_resource(state[i].resp, i, state->rtip);
	    BU_GET(state[i].left, struct bu_ptbl);
	    bu_ptbl_init(state[i].left, 64, "left solid hits");
	    BU_GET(state[i].both, struct bu_ptbl);
	    bu_ptbl_init(state[i].both, 64, "hits on both solids");
	    BU_GET(state[i].right, struct bu_ptbl);
	    bu_ptbl_init(state[i].right, 64, "right solid hits");
	    state[i].rays_cnt = count;
	    state[i].rays = rays;
	}
	bu_parallel(raydiff_gen_worker, ncpus, (void *)state);

	/* Collect and print all of the results */
	for (i = 0; i < ncpus+1; i++) {
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j);
		bu_log("Result: LEFT diff vol (%s): %g %g %g -> %g %g %g\n", obj1, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt));
	    }
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j);
		bu_log("Result: BOTH): %g %g %g -> %g %g %g\n", V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt));
	    }
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j);
		bu_log("Result: RIGHT diff vol (%s): %g %g %g -> %g %g %g\n", obj2, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt));
	    }
	}

	/* Free results */
	for (i = 0; i < ncpus+1; i++) {
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j);
		BU_PUT(dseg, struct diff_seg);
	    }
	    bu_ptbl_free(state[i].left);
	    BU_PUT(state[i].left, struct diff_seg);
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j);
		BU_PUT(dseg, struct diff_seg);
	    }
	    bu_ptbl_free(state[i].both);
	    BU_PUT(state[i].both, struct diff_seg);
	    for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) {
		struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j);
		BU_PUT(dseg, struct diff_seg);
	    }
	    bu_ptbl_free(state[i].right);
	    BU_PUT(state[i].right, struct diff_seg);

	    bu_free((void *)state[i].left_name, "left name");
	    bu_free((void *)state[i].right_name, "right name");
	    BU_PUT(state[i].resp, struct resource);
	}
	bu_free(state, "free state containers");
    }
    return 0;
}
HIDDEN int
_rt_generate_points(int **faces, int *num_faces, point_t **points, int *num_pnts, struct bu_ptbl *hit_pnts, struct db_i *dbip, const char *obj, fastf_t delta)
{
    int i, dir1, j;
    point_t min, max;
    int ncpus = bu_avail_cpus();
    struct rt_parallel_container *state;
    struct bu_vls vlsstr;
    bu_vls_init(&vlsstr);

    if (!hit_pnts || !dbip || !obj) return -1;

    BU_GET(state, struct rt_parallel_container);

    state->rtip = rt_new_rti(dbip);
    state->delta = delta;

    if (rt_gettree(state->rtip, obj) < 0) return -1;
    rt_prep_parallel(state->rtip, 1);

    state->resp = (struct resource *)bu_calloc(ncpus+1, sizeof(struct resource), "resources");
    for (i = 0; i < ncpus+1; i++) {
	rt_init_resource(&(state->resp[i]), i, state->rtip);
    }

    state->npts = (struct rt_point_container *)bu_calloc(ncpus+1, sizeof(struct rt_point_container), "point container arrays");
    int n[3];
    VMOVE(min, state->rtip->mdl_min);
    VMOVE(max, state->rtip->mdl_max);
    for (i = 0; i < 3; i++) {
	n[i] = (int)((max[i] - min[i])/state->delta) + 2;
	if(n[i] < 12) n[i] = 12;
    }
    int total = 0;
    for (i = 0; i < 3; i++) total += n[i]*n[(i+1)%3];
    if (total > 1e6) total = 1e6;
    for (i = 0; i < ncpus+1; i++) {
	state->npts[i].pts = (struct npoints *)bu_calloc(total, sizeof(struct npoints), "npoints arrays");
	state->npts[i].pnt_cnt = 0;
	state->npts[i].capacity = total;
    }

    for (dir1 = 0; dir1 < 3; dir1++) {
	state->ray_dir = dir1;
	state->ncpus = ncpus;
	state->delta = delta;
	bu_parallel(_rt_gen_worker, ncpus, (void *)state);
    }

    int out_cnt = 0;
    for (i = 0; i < ncpus+1; i++) {
	bu_log("%d, pnt_cnt: %d\n", i, state->npts[i].pnt_cnt);
	for (j = 0; j < state->npts[i].pnt_cnt; j++) {
	    struct npoints *npt = &(state->npts[i].pts[j]);
	    if (npt->in.is_set) out_cnt++;
	    if (npt->out.is_set) out_cnt++;
	}
    }

    struct rt_vert **rt_verts = (struct rt_vert **)bu_calloc(out_cnt, sizeof(struct rt_vert *), "output array");
    int curr_ind = 0;
    for (i = 0; i < ncpus+1; i++) {
	for (j = 0; j < state->npts[i].pnt_cnt; j++) {
	    struct npoints *npt = &(state->npts[i].pts[j]);
	    if (npt->in.is_set) {
		rt_verts[curr_ind] = &(npt->in);
		curr_ind++;
	    }
	    if (npt->out.is_set) {
		rt_verts[curr_ind] = &(npt->out);
		curr_ind++;
	    }
	}
    }

    struct spr_options opts = SPR_OPTIONS_DEFAULT_INIT;
    (void)spr_surface_build(faces, num_faces, (double **)points, num_pnts, (const struct cvertex **)rt_verts, out_cnt, &opts);

    return 0;
}