//*******************************************************************
 // NAME    constructor
 //
 // INPUTS
 //    ti - pointer to a target
 //    cpuID - thread ID
 //
 // DESCRIPTION
 //    Construct the object.
 //*******************************************************************
 DbTracer::DbTracer(Interface::INativeGeometry *ti, int cpuID)
   : Interface::IGeometryTracer(ti)
   , m_cpuID(cpuID)
 {
   // set up the application object that will be used
   RT_APPLICATION_INIT(&m_ap);
   m_ap.a_rt_i = (struct rt_i *) ti->getGeometry();
   m_ap.a_hit = hit_func;
   m_ap.a_resource = ((DbGeometry *) ti)->getResource(cpuID);
   m_ap.a_user = cpuID;
 }
Ejemplo n.º 2
0
/**
 * raytraces an object in parallel and stores or compares it to source
 */
void
rt_worker(int UNUSED(cpu), void *g)
{
    struct application ap;
    struct fitness_state *fstate = (struct fitness_state *)g;
    int u, v;

    RT_APPLICATION_INIT(&ap);
    ap.a_rt_i = fstate->rtip;
    if (fstate->capture) {
	ap.a_hit = capture_hit;
	ap.a_miss = capture_miss;
    } else {
	ap.a_hit = compare_hit;
	ap.a_miss = compare_miss;
    }

    ap.a_resource = &rt_uniresource;/*fstate->resource[cpu];*/

    ap.a_ray.r_dir[X] = ap.a_ray.r_dir[Y] = 0.0;
    ap.a_ray.r_dir[Z] = 1.0;
    ap.a_uptr = (void *) g;

    u = -1;

    while ((v = get_next_row(fstate))) {
	for (u = 1; u <= fstate->res[X]; u++) {
	    ap.a_ray.r_pt[X] = fstate->min[X] + u * fstate->gridSpacing[X];
	    ap.a_ray.r_pt[Y] = fstate->min[Y] + v * fstate->gridSpacing[Y];
	    ap.a_ray.r_pt[Z] = fstate->min[Z];
	    ap.a_user = (v-1)*(fstate->res[X]) + u-1;

	    rt_shootray(&ap);


	}
    }
}
HIDDEN void
raydiff_gen_worker(int cpu, void *ptr)
{
    struct application ap;
    struct raydiff_container *state = &(((struct raydiff_container *)ptr)[cpu]);
    fastf_t si, ei;
    int start_ind, end_ind, i;
    if (cpu == 0) {
	/* If we're serial, start at the beginning */
	start_ind = 0;
	end_ind = state->rays_cnt - 1;
    } else {
	si = (fastf_t)(cpu - 1)/(fastf_t)state->ncpus * (fastf_t) state->rays_cnt;
	ei = (fastf_t)cpu/(fastf_t)state->ncpus * (fastf_t) state->rays_cnt - 1;
	start_ind = (int)si;
	end_ind = (int)ei;
	if (state->rays_cnt - end_ind < 3) end_ind = state->rays_cnt - 1;
	bu_log("start_ind (%d): %d\n", cpu, start_ind);
	bu_log("end_ind (%d): %d\n", cpu, end_ind);
    }

    RT_APPLICATION_INIT(&ap);
    ap.a_rt_i = state->rtip;
    ap.a_hit = raydiff_hit;
    ap.a_miss = raydiff_miss;
    ap.a_overlap = raydiff_overlap;
    ap.a_onehit = 0;
    ap.a_logoverlap = rt_silent_logoverlap;
    ap.a_resource = state->resp;
    ap.a_uptr = (void *)state;

    for (i = start_ind; i <= end_ind; i++) {
	VSET(ap.a_ray.r_pt, state->rays[6*i+0], state->rays[6*i+1], state->rays[6*i+2]);
	VSET(ap.a_ray.r_dir, state->rays[6*i+3], state->rays[6*i+4], state->rays[6*i+5]);
	rt_shootray(&ap);
    }
}
Ejemplo n.º 4
0
/**
 * Called at the start of a run.
 *
 * Returns 1 if framebuffer should be opened, else 0.
 */
int
view_init(struct application *ap, char *file, char *UNUSED(obj), int minus_o, int minus_F)
{
    /*
     * Allocate a scanline for each processor.
     */
    ap->a_hit = rayhit;
    ap->a_miss = raymiss;
    ap->a_onehit = 1;

    /*
     * Does the user want occlusion checking?
     *
     * If so, load and prep.
     */
    if (bu_vls_strlen(&occlusion_objects) != 0) {
	struct db_i *dbip;
	int nObjs;
	const char **objs;
	int i;

	bu_log("rtedge: loading occlusion geometry from %s.\n", file);

	if (Tcl_SplitList(NULL, bu_vls_addr(&occlusion_objects), &nObjs,
			  &objs) == TCL_ERROR) {
	    bu_log("rtedge: occlusion list = %s\n",
		   bu_vls_addr(&occlusion_objects));
	    bu_exit(EXIT_FAILURE, "rtedge: could not parse occlusion objects list.\n");
	}

	for (i=0; i<nObjs; ++i) {
	    bu_log("rtedge: occlusion object %d = %s\n", i, objs[i]);
	}


	if ((dbip = db_open(file, DB_OPEN_READONLY)) == DBI_NULL)
	    bu_exit(EXIT_FAILURE, "rtedge: could not open geometry database file %s.\n", file);
	RT_CK_DBI(dbip);

#if 0
	/* FIXME: calling this when db_open()'s mapped file doesn't
	 * fail will cause duplicate directory entries.  need to make
	 * sure db_dirbuild rebuilds from scratch or only updates
	 * existing entries when they exist.
	 */
	if (db_dirbuild(dbip) < 0)
	    bu_exit(EXIT_FAILURE, "rtedge: could not read database.\n");
#endif

	occlusion_rtip = rt_new_rti(dbip); /* clones dbip */

	for (i=0; i < MAX_PSW; i++) {
	    rt_init_resource(&occlusion_resources[i], i, occlusion_rtip);
	    bn_rand_init(occlusion_resources[i].re_randptr, i);
	}

	db_close(dbip);			 /* releases original dbip */

	for (i=0; i<nObjs; ++i)
	    if (rt_gettree(occlusion_rtip, objs[i]) < 0)
		bu_log("rtedge: gettree failed for %s\n", objs[i]);
	    else
		bu_log("rtedge: got tree for object %d = %s\n", i, objs[i]);

	bu_log("rtedge: occlusion rt_gettrees done.\n");

	rt_prep(occlusion_rtip);

	bu_log("rtedge: occlusion prep done.\n");

	/*
	 * Create a set of application structures for the occlusion
	 * geometry. Need one per cpu, the upper half does the per-
	 * thread allocation in worker, but that's off limits.
	 */
	occlusion_apps = (struct application **)bu_calloc(npsw, sizeof(struct application *),
							  "occlusion application structure array");
	for (i=0; i<npsw; ++i) {
	    BU_ALLOC(occlusion_apps[i], struct application);
	    RT_APPLICATION_INIT(occlusion_apps[i]);

	    occlusion_apps[i]->a_rt_i = occlusion_rtip;
	    occlusion_apps[i]->a_resource = (struct resource *)BU_PTBL_GET(&occlusion_rtip->rti_resources, i);
	    occlusion_apps[i]->a_onehit = 1;
	    occlusion_apps[i]->a_hit = occlusion_hit;
	    occlusion_apps[i]->a_miss = occlusion_miss;
	    if (rpt_overlap)
		occlusion_apps[i]->a_logoverlap = (void (*)(struct application *, const struct partition *, const struct bu_ptbl *, const struct partition *))NULL;
	    else
		occlusion_apps[i]->a_logoverlap = rt_silent_logoverlap;

	}
	bu_log("rtedge: will perform occlusion testing.\n");

	/*
	 * If an inclusion mode has not been specified, use the default.
	 */
	if (occlusion_mode == OCCLUSION_MODE_NONE) {
	    occlusion_mode = OCCLUSION_MODE_DEFAULT;
	    bu_log("rtedge: occlusion mode = %d\n", occlusion_mode);
	}

	if ((occlusion_mode != OCCLUSION_MODE_NONE) &&
	    (overlay == OVERLAY_MODE_UNSET)) {
	    bu_log("rtedge: automagically activating overlay mode.\n");
	    overlay = OVERLAY_MODE_DOIT;
	}

    }

    if (occlusion_mode != OCCLUSION_MODE_NONE &&
	bu_vls_strlen(&occlusion_objects) == 0) {
	bu_exit(EXIT_FAILURE, "rtedge: occlusion mode set, but no objects were specified.\n");
    }

    /* if non-default/inverted background was requested, swap the
     * foreground and background colors.
     */
    if (!default_background) {
	color tmp;
	tmp[RED] = fgcolor[RED];
	tmp[GRN] = fgcolor[GRN];
	tmp[BLU] = fgcolor[BLU];
	fgcolor[RED] = bgcolor[RED];
	fgcolor[GRN] = bgcolor[GRN];
	fgcolor[BLU] = bgcolor[BLU];
	bgcolor[RED] = tmp[RED];
	bgcolor[GRN] = tmp[GRN];
	bgcolor[BLU] = tmp[BLU];
    }

    if (minus_o && (overlay || blend)) {
	/*
	 * Output is to a file stream.  Do not allow parallel
	 * processing since we can't seek to the rows.
	 */
	RTG.rtg_parallel = 0;
	bu_log("view_init: deactivating parallelism due to -o option.\n");
	/*
	 * The overlay and blend cannot be used in -o mode.  Note that
	 * the overlay directive takes precedence, they can't be used
	 * together.
	 */
	overlay = 0;
	blend = 0;
	bu_log("view_init: deactivating overlay and blending due to -o option.\n");
    }

    if (overlay)
	bu_log("view_init: will perform simple overlay.\n");
    else if (blend)
	bu_log("view_init: will perform blending.\n");

    return minus_F || (!minus_o && !minus_F); /* we need a framebuffer */
}
Ejemplo n.º 5
0
int
handle_main_ray(struct application *ap, register struct partition *PartHeadp,
		struct seg *segp)
{
    register struct partition *pp;
    register struct hit *hitp; /* which hit */

    struct application a2;
    struct cell me;
    struct cell below;
    struct cell left;

    struct cell above;
    struct cell right;

    double intensity = 1.0;

    int edge = 0;
    int cpu;
    int oc = 1;

    RGBpixel col;

    RT_APPLICATION_INIT(&a2);
    memset(&me, 0, sizeof(struct cell));
    memset(&below, 0, sizeof(struct cell));
    memset(&left, 0, sizeof(struct cell));

    cpu = ap->a_resource->re_cpu;

    if (PartHeadp == NULL || segp == NULL) {
	/* The main shotline missed.  pack the application struct
	 */
	me.c_ishit    = 0;
	me.c_dist   = MISS_DIST;
	me.c_id	    = MISS_ID;
	me.c_region = 0;
	VSETALL(me.c_hit, MISS_DIST);
	VSETALL(me.c_normal, 0);
	VMOVE(me.c_rdir, ap->a_ray.r_dir);
    } else {
	pp = PartHeadp->pt_forw;
	hitp = pp->pt_inhit;
	/*
	 * Stuff the information for this cell.
	 */
	me.c_ishit    = 1;
	me.c_id = pp->pt_regionp->reg_regionid;
	me.c_dist = hitp->hit_dist;
	me.c_region = pp->pt_regionp;
	VMOVE(me.c_rdir, ap->a_ray.r_dir);
	VJOIN1(me.c_hit, ap->a_ray.r_pt, hitp->hit_dist, ap->a_ray.r_dir);
	RT_HIT_NORMAL(me.c_normal, hitp,
		      pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip);
    }

    /*
     * Now, fire a ray for both the cell below and if necessary, the
     * cell to the left.
     */
    a2.a_hit = rayhit2;
    a2.a_miss = raymiss2;
    a2.a_onehit = 1;
    a2.a_rt_i = ap->a_rt_i;
    a2.a_resource = ap->a_resource;
    a2.a_logoverlap = ap->a_logoverlap;

    VSUB2(a2.a_ray.r_pt, ap->a_ray.r_pt, dy_model); /* below */
    VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir);
    a2.a_uptr = (void *)&below;
    rt_shootray(&a2);

    if (ap->a_x == 0) {
	/*
	 * For the first pixel in a scanline, we have to shoot to the
	 * left.  For each pixel afterword, we save the current cell
	 * info to be used as the left side cell info for the
	 * following pixel
	 */
	VSUB2(a2.a_ray.r_pt, ap->a_ray.r_pt, dx_model); /* left */
	VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir);
	a2.a_uptr = (void *)&left;
	rt_shootray(&a2);
    } else {
	left.c_ishit = saved[cpu]->c_ishit;
	left.c_id = saved[cpu]->c_id;
	left.c_dist = saved[cpu]->c_dist;
	left.c_region = saved[cpu]->c_region;
	VMOVE(left.c_rdir, saved[cpu]->c_rdir);
	VMOVE(left.c_hit, saved[cpu]->c_hit);
	VMOVE(left.c_normal, saved[cpu]->c_normal);
    }

    if (both_sides) {
	VADD2(a2.a_ray.r_pt, ap->a_ray.r_pt, dy_model); /* above */
	VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir);
	a2.a_uptr = (void *)&above;
	rt_shootray(&a2);

	VADD2(a2.a_ray.r_pt, ap->a_ray.r_pt, dx_model); /* right */
	VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir);
	a2.a_uptr = (void *)&right;
	rt_shootray(&a2);
    }


    /*
     * Is this pixel an edge?
     */
    if (both_sides) {
	edge = is_edge(&intensity, ap, &me, &left, &below, &right, &above);
    } else {
	edge = is_edge(&intensity, ap, &me, &left, &below, NULL, NULL);
    }

    /*
     * Does this pixel occlude the second geometry?  Note that we must
     * check on edges as well since right side and top edges are
     * actually misses.
     */
    if (occlusion_mode != OCCLUSION_MODE_NONE)
	if (me.c_ishit || edge)
	    oc = occludes(ap, &me);

    /*
     * Perverse Pixel Painting Paradigm(tm) If a pixel should be
     * written to the fb, writeable is set.
     */
    if (occlusion_mode == OCCLUSION_MODE_EDGES)
	writeable[cpu][ap->a_x] = (edge && oc);
    else if (occlusion_mode == OCCLUSION_MODE_HITS)
	writeable[cpu][ap->a_x] = ((me.c_ishit || edge) && oc);
    else if (occlusion_mode == OCCLUSION_MODE_DITHER) {
	if (edge && oc)
	    writeable[cpu][ap->a_x] = 1;
	else if (me.c_ishit && oc) {
	    /*
	     * Dither mode.
	     *
	     * For occluding non-edges, only write every other pixel.
	     */
	    if (oc == 1 && ((ap->a_x + ap->a_y) % 2) == 0)
		writeable[cpu][ap->a_x] = 1;
	    else if (oc == 2)
		writeable[cpu][ap->a_x] = 1;
	    else
		writeable[cpu][ap->a_x] = 0;
	} else {
	    writeable[cpu][ap->a_x] = 0;
	}
    } else {
	if (edge)
	    writeable[cpu][ap->a_x] = 1;
	else
	    writeable[cpu][ap->a_x] = 0;
    }

    if (edge) {
	if (both_sides) {
	    choose_color(col, intensity, &me, &left, &below, &right, &above);
	} else {
	    choose_color(col, intensity, &me, &left, &below, NULL, NULL);
	}

	scanline[cpu][ap->a_x*3+RED] = col[RED];
	scanline[cpu][ap->a_x*3+GRN] = col[GRN];
	scanline[cpu][ap->a_x*3+BLU] = col[BLU];
    } else {
	scanline[cpu][ap->a_x*3+RED] = bgcolor[RED];
	scanline[cpu][ap->a_x*3+GRN] = bgcolor[GRN];
	scanline[cpu][ap->a_x*3+BLU] = bgcolor[BLU];
    }

    /*
     * Save the cell info for the next pixel.
     */
    saved[cpu]->c_ishit = me.c_ishit;
    saved[cpu]->c_id = me.c_id;
    saved[cpu]->c_dist = me.c_dist;
    saved[cpu]->c_region = me.c_region;
    VMOVE(saved[cpu]->c_rdir, me.c_rdir);
    VMOVE(saved[cpu]->c_hit, me.c_hit);
    VMOVE(saved[cpu]->c_normal, me.c_normal);

    return edge;
}
Ejemplo n.º 6
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");
}
int main(int argc, char **argv)
{
    /* START # 1 */
    struct application ap;	/* Application struct, passed between functions.  */

    int idx;		/* Index for rt_dirbuild & rt_gettree.  */
    static struct rt_i *rtip;/* Used for building directory, etc.  */
    char idbuf[132];	/* First id record in .g file.  */

    int i, j, k;		/* Loop variables.  */
    double vec[3];		/* Temporary vector.  */
    double r[8];		/* Temporary variable.  */
    int c;			/* Variable to read a character.  */
    char tmpstrng[150];	/* Temporary string variable.  */
    FILE *fpr=NULL;	/* Used to read a file.  */
    FILE *fpw;		/* Used to write a file.  */
    char filetmp[MAXFIL];	/* Temperature file name.  */
    char filernn[MAXFIL];	/* Region # & name file.  */
    char fileout[MAXFIL];	/* Output file name.  */
    char line[151];	/* Used to read one line of a file.  */
    int mon, day, yr;	/* Month, day, and year read from PRISM file.  */
    float hr, min;		/* Hour & minute read from PRISM file.  */
    int itype;		/* Type of temperature file, 0=>PRISM, 1=>other.  */
    int numreg;		/* Number of regions (includes background).  */
			/* User enters when using a PRISM file or read */
			/* from generic file.  */
    int numreg_read;	/* Number of regions read from region # & name */
			/* file (includes background).  */
    int numreg_g;		/* Number of regions read from .g file plus one */
    /* for the background.  */
    double eltim;		/* Elapsed time.  */
    double eltim_read;	/* Elapsed time read from temperature file.  */
    int frst_line;		/* Number of regions to be read in first line */
    /* of PRISM file.  */
    int last_line;		/* Number of regions to be read in last line */
    /* of PRISM file.  */
    int full_line;		/* Number of full lines of PRISM file to read.  */

    double center[3];	/* Center of bounding sphere or rpp.  */
    double radius;		/* Radius of bounding sphere.  */
    double rppmax[3];	/* Maximum of bounding rpp.  */
    double rppmin[3];	/* Minimum of bounding rpp.  */
    double multi;		/* Multiplication factor for radius.  */

    int region_hit;	/* Region number hit by ray.  */
    int wide, high;		/* Width & height of picture.  */
    double deltaw, deltah;	/* Spacing between rays.  */

    double denom;		/* Denominator for use in equations.  */
    double az, el;		/* Viewing azimuth & elevation.  */
    double alpha, beta;	/* Angles for rotation (rad).  */
    double calpha, salpha;	/* Cosine & sine of alpha.  */
    double cbeta, sbeta;	/* Cosine & sine of beta.  */
    int ret;

    /* Check to see if arguments implemented correctly.  */
    if (argc < 3 || argv[1]==NULL || argv[2]==NULL) {
	fprintf(stderr, "\nUsage:  showtherm file.g objects\n\n");
    } else {
	/* START # 4 */
	/* Get beginning info such as name of temperature file,  */
	/* name of region # & name file, type of temperature file */
	/* using.  */

	/* Ask type of temperature file to be used.  */
	fprintf(stderr, "Type of output file to be read 0=>PRISM, ");
	fprintf(stderr, "1=>generic.\n\t");
	ret = scanf("%d", &itype);
	if (ret == 0)
	    perror("scanf");
	if (itype != 1) itype = 0;

	if (itype == 0) {
	    /* Read info about (name & # regions) PRISM file.  */
	    fprintf(stderr, "Enter name of the PRISM output ");
	    fprintf(stderr, "file to be read (%d char max).\n\t", MAXFIL);
	    ret = scanf("%25s", filetmp); /* MAXFIL */
	    if (ret == 0)
		perror("scanf");

	    /* Ask for number of regions.  */
	    fprintf(stderr, "Enter the number of regions in the PRISM ");
	    fprintf(stderr, "file, must be more\n");
	    fprintf(stderr, "than eight (not including the background).\n\t");
	    ret = scanf("%d", &numreg);
	    if (ret == 0)
		perror("scanf");
	} else {
	    /* Read info about (name) generic file.  */
	    fprintf(stderr, "Enter name of the generic output file to be ");
	    fprintf(stderr, "read (%d char max).\n\t", MAXFIL);
	    ret = scanf("%25s", filetmp); /* MAXFIL */
	    if (ret == 0)
		perror("scanf");
	}

	/* Find name of region # & name file.  */
	fprintf(stderr, "Enter name of region # & name file to be read ");
	fprintf(stderr, "(%d char max).\n\t", MAXFIL);
	ret = scanf("%25s", filernn); /* MAXFIL */
	if (ret == 0)
	    perror("scanf");

	/* Find name of output file.  */
	fprintf(stderr, "Enter name of output file (%d char max).\n\t", MAXFIL);
	ret = scanf("%25s", fileout); /*MAXFIL */
	if (ret == 0)
	    perror("scanf");

	/* Find elapsed time to create graphical representation of.  */
	fprintf(stderr, "Enter the elapsed time to create graphical ");
	fprintf(stderr, "representation of.\n\t");
	ret = scanf("%lf", &eltim);
	if (ret == 0)
	    perror("scanf");

	/* Open generic file and read number of regions if necessary.  */
	if (itype == 1) {
	    fpr = fopen(filetmp, "rb");
	    (void)bu_fgets(line, 150, fpr);
	    sscanf(line, "%d", &numreg);
	}

	/* Add one to number of regions to include background.  */
	numreg ++;
	printf("Number of regions (including ");
	(void)fflush(stdout);
	printf("the background):  %d\n", numreg);
	(void)fflush(stdout);

	/* Malloc arrays.  */
	info = (struct table *)bu_malloc(numreg * sizeof (struct table), "info");

	/* Zero all arrays.  */
	for (i=0; i<numreg; i++) {
	    info[i].temp = 0.0;
	    for (j=0; j<150; j++) {
		info[i].regname[j] = ' ';
	    }
	}

	/* Now read the temperature file.  */
	if (itype == 0) {
	    /* PRISM file.  */
	    /* START # 2 */
	    fpr = fopen(filetmp, "rb");

	    /* Read date and print out.  */
	    (void)bu_fgets(line, 150, fpr);
	    sscanf(line, "%d %d %d %f %f", &mon, &day, &yr, &hr, &min);
	    printf("%d/%d/%d ", mon, day, yr);
	    printf(" %f:%f\n", hr, min);
	    (void)fflush(stdout);

	    /* Find number of lines to read.  */
	    frst_line = 7;
	    full_line = (numreg - frst_line) / (frst_line + 1);
	    last_line = numreg - frst_line -(full_line * (frst_line + 1));

	    /* Read first line & check if correct elapsed time.  */
	    (void)bu_fgets(line, 150, fpr);
	    sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf", &eltim_read,
		   &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6]);

	    /*
	     * while (eltim_read != eltim)
	     */
	    while ((eltim_read < (eltim - VUNITIZE_TOL)) || ((eltim + VUNITIZE_TOL) < eltim_read)) {
		/* Page through to end of data.  */
		for (i=0; i<(full_line + 1); i++) {
		    (void)bu_fgets(line, 150, fpr);
		}
		/* Read next elapsed time.  */
		(void)bu_fgets(line, 150, fpr);
		sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf", &eltim_read,
		       &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6]);
	    }

	    /* When correct elapsed time is found, read data.  */
	    /* Read first line of data.  */
	    for (i=0; i<frst_line; i++) {
		info[i].temp = r[i];
	    }
	    k = frst_line;	/* Next region number of temperature to be read.  */
	    /* Read full lines of data.  */
	    for (i=0; i<full_line; i++) {
		(void)bu_fgets(line, 150, fpr);
		sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf",
		       &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6], &r[7]);
		for (j=0; j<(frst_line + 1); j++) {
		    info[k].temp = r[j];
		    k++;
		}
	    }
	    /* Read last line of data.  */
	    (void)bu_fgets(line, 150, fpr);
	    if (last_line == 1) sscanf(line, "%lf", &r[0]);
	    if (last_line == 2) sscanf(line, "%lf %lf", &r[0], &r[1]);
	    if (last_line == 3) sscanf(line, "%lf %lf %lf", &r[0], &r[1], &r[2]);
	    if (last_line == 4) sscanf(line, "%lf %lf %lf %lf", &r[0], &r[1], &r[2],
				       &r[3]);
	    if (last_line == 5) sscanf(line, "%lf %lf %lf %lf %lf",
				       &r[0], &r[1], &r[2], &r[3], &r[4]);
	    if (last_line == 6) sscanf(line, "%lf %lf %lf %lf %lf %lf",
				       &r[0], &r[1], &r[2], &r[3], &r[4], &r[5]);
	    if (last_line == 7) sscanf(line, "%lf %lf %lf %lf %lf %lf %lf",
				       &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6]);
	    if (last_line == 8) sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf",
				       &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6], &r[7]);
	    if (last_line != 0) {
		for (j=0; j<last_line; j++) {
		    info[k].temp = r[j];
		    k++;
		}
	    }
	    printf("Prism out file read.\n");
	    (void)fflush(stdout);
	    /* END # 2 */
	} else {
	    /* Read generic file.  */
	    /* START # 3 */
	    /* File is already open.  */
	    /* Read elapsed time.  */
	    (void)bu_fgets(line, 150, fpr);
	    sscanf(line, "%lf", &eltim_read);

	    while (!EQUAL(eltim_read, eltim)) {
		/* Page through to end of data.  */
		for (i=0; i<numreg; i++) {
		    (void)bu_fgets(line, 150, fpr);
		}
		(void)bu_fgets(line, 150, fpr);
		sscanf(line, "%lf", &eltim_read);
	    }

	    /* When correct elapsed time is found, read data.  */
	    for (i=0; i<numreg; i++) {
		(void)bu_fgets(line, 150, fpr);
		sscanf(line, "%lf", &r[0]);
		info[i].temp = r[0];
	    }
	}							/* END # 3 */

	/* Close file.  */
	(void)fclose(fpr);

	/* Read the region # & name file.  */
	fpr = fopen(filernn, "rb");
	printf("Region # & name file opened.\n");
	(void)fflush(stdout);
	numreg_read = 1;
	c = getc(fpr);
	while ((c != EOF) && (numreg_read < numreg)) {
	    (void)ungetc(c, fpr);
	    (void)bu_fgets(line, 150, fpr);
	    sscanf(line, "%*d%149s", tmpstrng);
	    for (i=0; i<150; i++) {
		info[numreg_read].regname[i] = tmpstrng[i];
	    }
	    numreg_read++;
	    c = getc(fpr);
	}
	/* Close file.  */
	(void)fclose(fpr);

	/* Check if the number of regions read from the output file is */
	/* the same as the number of regions read from the region # &  */
	/* name file.  */
	if (numreg_read == numreg) {
	    printf("The number of regions read from the output file ");
	    printf("and the region # & name\n");
	    printf("file was the same, %d (does not ", (numreg-1));
	    printf("include background in number).\n");
	    (void)fflush(stdout);
	}
	if (numreg_read != numreg) {
	    printf("The number of regions read from the output file ");
	    printf("and the region # & name\n");
	    printf("file was not the same, %d vs %d.\n", (numreg-1),
		   (numreg_read-1));
	    printf("This is an ERROR.\n\n");
	    (void)fflush(stdout);
	}

	/* Build the directory.  */
	printf("Building directory.\n");
	(void)fflush(stdout);
	idx = 1;		/* Set index for rt_dirbuild.  */
	rtip = rt_dirbuild(argv[idx], idbuf, sizeof(idbuf));
	printf("File:  %s\n", argv[idx]);
	(void)fflush(stdout);
	printf("Database Title:  %s\n", idbuf);
	(void)fflush(stdout);

	/* Set useair to 1, to show hits of air.  Must show hits of air */
	/* since other irprep programs do.  */
	rtip->useair = 1;

	/* Load desired objects.  */
	idx = 2;		/* Set index for rt_gettree.  */
	while (argv[idx] != NULL) {
	    rt_gettree(rtip, argv[idx]);
	    printf("\t%s loaded.\n", argv[idx]);
	    (void)fflush(stdout);
	    idx++;
	}

	/* Find the total number of regions in the .g file & add one */
	/* for background.  */
	numreg_g = (int)rtip->nregions + 1;

	if ((numreg == numreg_read) && (numreg_read == numreg_g)) {
	    printf("The number of regions read from the output\n");
	    printf("file, the region # & name file, and the .g\n");
	    printf("file are all equal.  The number of regions\n");
	    printf("read, including the background is %d\n", numreg_g);
	    (void)fflush(stdout);
	} else {
	    printf("The number of regions read from the output\n");
	    printf("file, the region # & name file, and the .g\n");
	    printf("file are not all equal.\n");
	    printf("\toutput file:  %d\n", numreg);
	    printf("\tregion # & name file:  %d\n", numreg_read);
	    printf("\t.g file:  %d\n", numreg_g);
	    (void)fflush(stdout);
	}

	/* Start preparation.  */
	printf("Preparation started.\n");
	(void)fflush(stdout);
	rt_prep(rtip);

	/* Maximums & minimums of bounding rpp.  */
	rppmin[X] = rtip->mdl_min[X];
	rppmin[Y] = rtip->mdl_min[Y];
	rppmin[Z] = rtip->mdl_min[Z];
	rppmax[X] = rtip->mdl_max[X];
	rppmax[Y] = rtip->mdl_max[Y];
	rppmax[Z] = rtip->mdl_max[Z];

	/* Find the center of the bounding sphere or rpp.  */
	center[X] = rppmin[X] + (rppmax[X] - rppmin[X]) / 2.0;
	center[Y] = rppmin[Y] + (rppmax[Y] - rppmin[Y]) / 2.0;
	center[Z] = rppmin[Z] + (rppmax[Z] - rppmin[Z]) / 2.0;

	/* Find the length of the radius of the bounding sphere.  */
	radius = (rppmax[X] - rppmin[X]) * (rppmax[X] - rppmin[X]) +
	    (rppmax[Y] - rppmin[Y]) * (rppmax[Y] - rppmin[Y]) +
	    (rppmax[Z] - rppmin[Z]) * (rppmax[Z] - rppmin[Z]);
	radius = sqrt(radius) / 2.0 + 1.0;	/* Make radius a bit longer.  */

	printf("\nMinimum & maximum X:  %f - %f\n", rppmin[X], rppmax[X]);
	printf("Minimum & maximum Y:  %f - %f\n", rppmin[Y], rppmax[Y]);
	printf("Minimum & maximum Z:  %f - %f\n", rppmin[Z], rppmax[Z]);
	printf("Center of bounding sphere:  %f, %f, %f\n",
	       center[X], center[Y], center[Z]);
	printf("Radius of bounding sphere:  %f\n", radius);
	printf("Enter multiplication factor for radius.\n\t");
	(void)fflush(stdout);
	ret = scanf("%lf", &multi);
	if (ret == 0)
	    perror("scanf");
	/* Multiply radius by multiplication factor.  */
	radius = radius * multi;

	/* Set up parameters for rt_shootray.  */
	RT_APPLICATION_INIT(&ap);
	ap.a_hit = hit;		/* User supplied hit function.  */
	ap.a_miss = miss;		/* User supplied miss function.  */
	ap.a_overlap = overlap;	/* User supplied overlap function.  */
	ap.a_rt_i = rtip;		/* Pointer from rt_dirbuild.  */
	ap.a_onehit = 1;		/* Hit flag, stop after first hit.  */
	ap.a_level = 0;		/* Recursion level for diagnostics.  */
	ap.a_resource = 0;		/* Address of resource struct.  */

	/* Open output file.  */
	fpw = fopen(fileout, "wb");

	/* User enters grid size.  */
	fprintf(stderr, "Enter grid size.\n\t");
	ret = scanf("%d", &wide);
	if (ret == 0)
	    perror("scanf");
	high = wide;

	/* User enters azimuth & elevation for viewing.  */
	fprintf(stderr, "Enter azimuth & elevation.\n\t");
	ret = scanf("%lf %lf", &az, &el);
	if (ret == 0)
	    perror("scanf");
	alpha = az * DEG2RAD;
	beta = (-el) * DEG2RAD;
	calpha = cos(alpha);
	salpha = sin(alpha);
	cbeta = cos(beta);
	sbeta = sin(beta);

	/* Find spacing between rays.  */
	deltaw = 2. * radius / (float)wide;
	deltah = 2. * radius / (float)high;

	/* Print grid size, azimuth, and elevation.  */
	printf("gridsize:  %d x %d\n", wide, high);
	printf("azimuth:  %f degrees\n", az);
	printf("elevation:  %f degrees\n", el);
	(void)fflush(stdout);

	/* Write size of grid to output file.  */
	fprintf(fpw, "%d\t%d\n", wide, high);
	(void)fflush(stdout);

	/* Set firing direction.  Rotate (-1, 0, 0) to proper position.  */
	vec[X] = (-1.0) * cbeta * calpha;
	vec[Y] = (-1.0) * cbeta * salpha;
	vec[Z] = (-1.0) * (-1.0) * sbeta;
	/* Normalize.  */
	denom = vec[X] * vec[X] + vec[Y] * vec[Y] + vec[Z] * vec[Z];
	denom = sqrt(denom);
	vec[X] /= denom;
	vec[Y] /= denom;
	vec[Z] /= denom;
	ap.a_ray.r_dir[X] = vec[X];
	ap.a_ray.r_dir[Y] = vec[Y];
	ap.a_ray.r_dir[Z] = vec[Z];

	/* Set starting point.  */
	vec[X] = center[X] + radius;

	for (i=0; i<high; i++) {
	    vec[Z] = center[Z] + radius - (float)i * deltah;

	    for (j=0; j<wide; j++) {
		vec[Y] = center[Y] - radius + (float)j * deltaw;
		/* Rotate starting point.  */
		ap.a_ray.r_pt[X] = vec[X] * cbeta * calpha +
		    vec[Z] * sbeta * calpha - vec[Y] * salpha;
		ap.a_ray.r_pt[Y] = vec[X] * cbeta * salpha +
		    vec[Z] * sbeta * salpha + vec[Y] * calpha;
		ap.a_ray.r_pt[Z] = (-vec[X]) * sbeta + vec[Z] * cbeta;

		/* Call rt_shootray.  */
		region_hit = rt_shootray(&ap);

		/* Write temperature of region to output file.  */
		fprintf(fpw, "%f\n", info[region_hit].temp);
		(void)fflush(fpw);
	    }
	}

    }							/* END # 4 */
    return 0;
}							/* END # 1 */
Ejemplo n.º 8
0
int
main(int argc, char *argv[])
{
    struct rt_i *rtip = NULL;

    char db_title[TITLE_LEN+1];/* title from MGED file */
    const char *tmp_str;
    extern char local_u_name[65];
    extern double base2local;
    extern double local2base;
    FILE *fPtr;
    int Ch;		/* Option name */
    int mat_flag = 0;	/* Read matrix from stdin? */
    int use_of_air = 0;
    int print_ident_flag = 1;
    char ocastring[1024] = {0};
    struct bu_list script_list;	/* For -e and -f options */
    struct script_rec *srp;
    extern outval ValTab[];

    /* from if.c, callback functions for overlap, hit, and miss shots */
    int if_overlap(struct application *, struct partition *, struct region *, struct region *, struct partition *);
    int if_hit(struct application *, struct partition *, struct seg *);
    int if_miss(struct application *);

    BU_LIST_INIT(&script_list);

    bu_setprogname(argv[0]);

    ocname[OVLP_RESOLVE] = "resolve";
    ocname[OVLP_REBUILD_FASTGEN] = "rebuild_fastgen";
    ocname[OVLP_REBUILD_ALL] = "rebuild_all";
    ocname[OVLP_RETAIN] = "retain";
    *ocastring = '\0';

    bu_optind = 1;		/* restart */

    /* Handle command-line options */
    while ((Ch = bu_getopt(argc, argv, OPT_STRING)) != -1) {
    	if (bu_optopt == '?') Ch='h';
	switch (Ch) {
	    case 'A':
		attrib_add(bu_optarg, &need_prep);
		break;
	    case 'B':
		rt_bot_minpieces = atoi(bu_optarg);
		break;
	    case 'T':
		setenv("LIBRT_BOT_MINTIE", bu_optarg, 1);
		break;
	    case 'b':
		do_backout = 1;
		break;
	    case 'E':
		if (nirt_debug & DEBUG_SCRIPTS)
		    show_scripts(&script_list, "before erasure");
		while (BU_LIST_WHILE(srp, script_rec, &script_list)) {
		    BU_LIST_DEQUEUE(&(srp->l));
		    free_script(srp);
		}
		if (nirt_debug & DEBUG_SCRIPTS)
		    show_scripts(&script_list, "after erasure");
		break;
	    case 'e':
		enqueue_script(&script_list, READING_STRING, bu_optarg);
		if (nirt_debug & DEBUG_SCRIPTS)
		    show_scripts(&script_list, "after enqueueing a literal");
		break;
	    case 'f':
		enqueue_script(&script_list, READING_FILE, bu_optarg);
		if (nirt_debug & DEBUG_SCRIPTS)
		    show_scripts(&script_list, "after enqueueing a file name");
		break;
	    case 'L':
		listformats();
		bu_exit(EXIT_SUCCESS, NULL);
	    case 'M':
		mat_flag = 1;
		break;
	    case 'O':
		sscanf(bu_optarg, "%1024s", ocastring);
		break;
	    case 's':
		silent_flag = SILENT_YES;	/* Positively yes */
		break;
	    case 'v':
		silent_flag = SILENT_NO;	/* Positively no */
		break;
	    case 'x':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug);
		break;
	    case 'X':
		sscanf(bu_optarg, "%x", (unsigned int *)&nirt_debug);
		break;
	    case 'u':
		if (sscanf(bu_optarg, "%d", &use_of_air) != 1) {
		    (void) fprintf(stderr,
				   "Illegal use-air specification: '%s'\n", bu_optarg);
		    return 1;
		}
		break;
	    case 'H':
		if (sscanf(bu_optarg, "%d", &print_ident_flag) != 1) {
		    (void) fprintf(stderr,
				   "Illegal header output option specified: '%s'\n", bu_optarg);
		    return 1;
		}
		break;
	    default:
		printusage();
		bu_exit (Ch != 'h', NULL);
	}
    } /* end while getopt */

    if (argc - bu_optind < 2) {
	printusage();
	return 1;
    }

    if (isatty(0)) {
	if (silent_flag != SILENT_YES)
	    silent_flag = SILENT_NO;
    } else {
	/* stdin is not a TTY */
	if (silent_flag != SILENT_NO)
	    silent_flag = SILENT_YES;
    }
    if (silent_flag != SILENT_YES && print_ident_flag)
	(void) fputs(brlcad_ident("Natalie's Interactive Ray Tracer"), stdout);

    if (use_of_air && (use_of_air != 1)) {
	fprintf(stderr,
		"Warning: useair=%d specified, will set to 1\n", use_of_air);
	use_of_air = 1;
    }

    switch (*ocastring) {
	case '\0':
	    overlap_claims = OVLP_RESOLVE;
	    break;
	case '0':
	case '1':
	case '2':
	case '3':
	    if (ocastring[1] == '\0') {
		sscanf(ocastring, "%d", &overlap_claims);
	    } else {
		fprintf(stderr,
			"Illegal overlap_claims specification: '%s'\n", ocastring);
		return 1;
	    }
	    break;
	case 'r':
	    if (BU_STR_EQUAL(ocastring, "resolve"))
		overlap_claims = OVLP_RESOLVE;
	    else if (BU_STR_EQUAL(ocastring, "rebuild_fastgen"))
		overlap_claims = OVLP_REBUILD_FASTGEN;
	    else if (BU_STR_EQUAL(ocastring, "rebuild_all"))
		overlap_claims = OVLP_REBUILD_ALL;
	    else if (BU_STR_EQUAL(ocastring, "retain"))
		overlap_claims = OVLP_RETAIN;
	    else {
		fprintf(stderr,
			"Illegal overlap_claims specification: '%s'\n", ocastring);
		return 1;
	    }
	    break;
	default:
	    fprintf(stderr,
		    "Illegal overlap_claims specification: '%s'\n", ocastring);
	    return 1;
    }

    db_name = argv[bu_optind];

    /* build directory for target object */
    if (silent_flag != SILENT_YES) {
	printf("Database file:  '%s'\n", db_name);
	printf("Building the directory...");
    }
    if ((rtip = rt_dirbuild(db_name, db_title, TITLE_LEN)) == RTI_NULL) {
	fflush(stdout);
	fprintf(stderr, "Could not load file %s\n", db_name);
	return 1;
    }

    rti_tab[use_of_air] = rtip;
    rti_tab[1 - use_of_air] = RTI_NULL;
    rtip->useair = use_of_air;
    rtip->rti_save_overlaps = (overlap_claims > 0);

    ++bu_optind;
    do_rt_gettrees(rtip, argv + bu_optind, argc - bu_optind, &need_prep);

    /* Initialize the table of resource structures */
    rt_init_resource(&res_tab, 0, rtip);

    /* initialization of the application structure */
    RT_APPLICATION_INIT(&ap);
    ap.a_hit = if_hit;        /* branch to if_hit routine */
    ap.a_miss = if_miss;      /* branch to if_miss routine */
    ap.a_overlap = if_overlap;/* branch to if_overlap routine */
    ap.a_logoverlap = rt_silent_logoverlap;
    ap.a_onehit = 0;          /* continue through shotline after hit */
    ap.a_resource = &res_tab;
    ap.a_purpose = "NIRT ray";
    ap.a_rt_i = rtip;         /* rt_i pointer */
    ap.a_zero1 = 0;           /* sanity check, sayth raytrace.h */
    ap.a_zero2 = 0;           /* sanity check, sayth raytrace.h */
    ap.a_uptr = (void *)a_tab.attrib;

    /* initialize variables */
    azimuth() = 0.0;
    elevation() = 0.0;
    direct(X) = -1.0;
    direct(Y) = 0.0;
    direct(Z) = 0.0;
    grid(HORZ) = 0.0;
    grid(VERT) = 0.0;
    grid(DIST) = 0.0;
    grid2targ();
    set_diameter(rtip);

    /* initialize the output specification */
    default_ospec();

    /* initialize NIRT's local units */
    base2local = rtip->rti_dbip->dbi_base2local;
    local2base = rtip->rti_dbip->dbi_local2base;
    tmp_str = bu_units_string(local2base);
    if (tmp_str) {
	bu_strlcpy(local_u_name, tmp_str, sizeof(local_u_name));
    } else {
	bu_strlcpy(local_u_name, "Unknown units", sizeof(local_u_name));
    }

    if (silent_flag != SILENT_YES) {
	printf("Database title: '%s'\n", db_title);
	printf("Database units: '%s'\n", local_u_name);
	printf("model_min = (%g, %g, %g)    model_max = (%g, %g, %g)\n",
	       rtip->mdl_min[X] * base2local,
	       rtip->mdl_min[Y] * base2local,
	       rtip->mdl_min[Z] * base2local,
	       rtip->mdl_max[X] * base2local,
	       rtip->mdl_max[Y] * base2local,
	       rtip->mdl_max[Z] * base2local);
    }

    /* Run the run-time configuration file, if it exists */
    if ((fPtr = fopenrc()) != NULL) {
	interact(READING_FILE, fPtr, rtip);
	fclose(fPtr);
    }

    /* Run all scripts specified on the command line */
    run_scripts(&script_list, rtip);

    /* Perform the user interface */
    if (mat_flag) {
	read_mat(rtip);
	return 0;
    } else {
	interact(READING_FILE, stdin, rtip);
    }

    return 0;
}
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 */
HIDDEN int osl_render(struct application *ap, const struct partition *pp,
		      struct shadework *swp, void *dp)
/* defined in ../h/shadework.h */
/* ptr to the shader-specific struct */
{
    register struct osl_specific *osl_sp =
	(struct osl_specific *)dp;

    void * thread_info;

    int nsamples; /* Number of samples */

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_OSL_SP(osl_sp);

    if (rdebug&RDEBUG_SHADE)
	bu_struct_print("osl_render Parameters:", osl_print_tab,
			(char *)osl_sp);

    bu_semaphore_acquire(BU_SEM_SYSCALL);

    /* Check if it is the first time this thread is calling this function */
    bool visited = false;
    for (size_t i = 0; i < visited_addrs.size(); i++) {
	if (ap->a_resource == visited_addrs[i]) {
	    visited = true;
	    thread_info = thread_infos[i];
	    break;
	}
    }
    if (!visited) {
	visited_addrs.push_back(ap->a_resource);
	/* Get thread specific information from OSLRender system */
	thread_info = oslr->CreateThreadInfo();
	thread_infos.push_back(thread_info);
    }

    if (ap->a_level == 0) {
	default_a_hit = ap->a_hit; /* save the default hit callback (colorview @ rt) */
	default_a_miss = ap->a_miss;
    }
    bu_semaphore_release(BU_SEM_SYSCALL);

    Color3 acc_color(0.0f);

    /* -----------------------------------
     * Fill in all necessary information for the OSL renderer
     * -----------------------------------
     */
    RenderInfo info;
    /* Set hit point */
    VMOVE(info.P, swp->sw_hit.hit_point);

    /* Set normal at the point */
    VMOVE(info.N, swp->sw_hit.hit_normal);

    /* Set incidence ray direction */
    VMOVE(info.I, ap->a_ray.r_dir);

    /* U-V mapping stuff */
    info.u = swp->sw_uv.uv_u;
    info.v = swp->sw_uv.uv_v;
    VSETALL(info.dPdu, 0.0f);
    VSETALL(info.dPdv, 0.0f);

    /* x and y pixel coordinates */
    info.screen_x = ap->a_x;
    info.screen_y = ap->a_y;

    info.depth = ap->a_level;
    info.surfacearea = 1.0f;

    info.shader_ref = osl_sp->shader_ref;

    /* We assume that the only information that will be written is thread_info,
       so that oslr->QueryColor is thread safe */
    info.thread_info = thread_info;


// Ray-tracing (local illumination)

    /* We only perform reflection if application decides to */
    info.doreflection = 0;
    info.out_ray_type = 0;

    Color3 weight = oslr->QueryColor(&info);

    /* Fire another ray */
    if ((info.out_ray_type & RAY_REFLECT) || (info.out_ray_type & RAY_TRANSMIT)) {

	struct application new_ap;
	RT_APPLICATION_INIT(&new_ap);

	new_ap = *ap;                     /* struct copy */
	new_ap.a_onehit = 1;
	new_ap.a_hit = default_a_hit;
	new_ap.a_level = info.depth + 1;
	new_ap.a_flag = 0;

	VMOVE(new_ap.a_ray.r_dir, info.out_ray.dir);
	VMOVE(new_ap.a_ray.r_pt, info.out_ray.origin);

	/* This next ray represents refraction */
	if (info.out_ray_type & RAY_TRANSMIT) {

	    /* Displace the hit point a little bit in the direction
	       of the next ray */
	    Vec3 tmp;
	    VSCALE(tmp, info.out_ray.dir, 1e-4);
	    VADD2(new_ap.a_ray.r_pt, new_ap.a_ray.r_pt, tmp);

	    new_ap.a_onehit = 1;
	    new_ap.a_refrac_index = 1.5;
	    new_ap.a_flag = 2; /* mark as refraction */
	    new_ap.a_hit = osl_refraction_hit;
	}

	(void)rt_shootray(&new_ap);

	Color3 rec;
	VMOVE(rec, new_ap.a_color);

	Color3 res = rec*weight;

	VMOVE(swp->sw_color, res);
    }
    else {
	/* Final color */
	VMOVE(swp->sw_color, weight);
    }

    return 1;
}
Ejemplo n.º 10
0
int main(int argc, char **argv)
{
    /*  START # 99  */
    struct application ap;  /*  Structure passed between functions.  */
    struct rt_i *rtip;	/*  Used to build directory.  */
    int index;		/*  Index for rt_dirbuild & rt_gettree.  */
    char idbuf[32];	/*  Contains data base info.  */
    struct region *pr;   /*  Used in finding region names.  */

    int numreg;		/*  Number of regions.  */
    double centall[3];	/*  Center of entire model.  */
    double minall[3];	/*  Minimum of entire model.  */
    double maxall[3];	/*  Maximum of entire model.  */
    double areaall;	/*  Surface area of bounding sphere.  */
    double radall;	/*  Radius of bounding sphere.  */
    long seed;		/*  Seed for random number generator.  */
    double rayfir;	/*  Number of rays to be fired.  */
    double rho, phi, theta;/*  Spherical coordinates for starting point.  */
    double elev, az, rds;	/*  Elevation, azimuth, & radius for finding vector  */
    /*  in yz-plane.  */
    double strtpt[3];	/*  Starting point.  */
    double strtdir[3];	/*  Starting direction.  */
    double denom;	/*  Denominator.  */

    int ians;		/*  Answer to question.  */
    int i, j, k, m;		/*  Loop counters.  */
    double r;		/*  Loop counter.  */
    double q;		/*  Temporary variable.  */
    double s[3], t[3];	/*  Temporary variables.  */

    FILE *fpw;		/*  Allows a file to be written.  */
    char outfile[26];	/*  Output file name.  */
    char errfile[26];	/*  Error file name.  */
    FILE *fpw2;		/*  Allows a file to be written.  */
    char lwxfile[26];	/*  Longwave radiation exchange file for PRISM  */
    /*  (not quite PRISM ready).  */

    struct bn_unif *msr = NULL;

    /*  Check to see if arguments are implimented correctly.  */
    if ( (argv[1] == NULL) || (argv[2] == NULL) )
    {
        (void)fprintf(stderr, "\nusage:  %s file.g objects\n\n", *argv);
    }

    else
    {
        /*  START # 100  */

        /*  Find name of output file.  */
        (void)printf("Enter name of output file (25 char max).\n\t");
        (void)fflush(stdout);
        (void)scanf("%25s", outfile);

        /*  Find name of longwave radiation exchange (lwx) file  */
        /*  for use with PRISM (not quite PRISM ready).  */
        (void)printf("Enter name of longwave radiation exchange");
        (void)printf(" file (25 char max).\n\t");
        (void)fflush(stdout);
        (void)scanf("%25s", lwxfile);

        /*  Find name of error file.  */
        (void)printf("Enter name of error file (25 char max).\n\t");
        (void)fflush(stdout);
        (void)scanf("%25s", errfile);

        /*  Open files.  */
        fpw = fopen(outfile, "w");
        fpw1 = fopen(errfile, "w");
        fpw2 = fopen(lwxfile, "w");

        /*  Write info to output & error file.  */
        (void)fprintf(fpw, "\n.g file used:  %s\n", argv[1]);
        (void)fprintf(fpw, "regions used:\n");
        (void)fprintf(fpw1, "\n.g file used:  %s\n", argv[1]);
        (void)fprintf(fpw1, "regions used:\n");
        i = 2;
        while (argv[i] != NULL)
        {
            (void)fprintf(fpw, "\t%s\n", argv[i]);
            (void)fprintf(fpw1, "\t%s\n", argv[i]);
            i++;
        }
        (void)fprintf(fpw, "output file created:  %s\n", outfile);
        (void)fprintf(fpw, "error file created:  %s\n", errfile);
        (void)fprintf(fpw, "lwx file created:  %s\n", errfile);
        (void)fflush(fpw);
        (void)fprintf(fpw1, "output file created:  %s\n", outfile);
        (void)fprintf(fpw1, "error file created:  %s\n", errfile);
        (void)fprintf(fpw1, "lwx file created:  %s\n", errfile);
        (void)fflush(fpw1);

        /*  Build directory.  */
        index = 1;      /*  Set index for rt_dirbuild.  */
        rtip = rt_dirbuild(argv[index], idbuf, sizeof(idbuf));
        (void)printf("Database Title:  %s\n", idbuf);
        (void)fflush(stdout);

        /*  Set useair to 0 to show no hits of air.  */
        rtip->useair = 0;

        /*  Load desired objects.  */
        index = 2;      /*  Set index.  */
        while (argv[index] != NULL)
        {
            rt_gettree(rtip, argv[index]);
            index += 1;
        }

        /*  Find number of regions.  */
        numreg = (int)rtip->nregions;

        (void)fprintf(stderr, "Number of regions:  %d\n", numreg);
        (void)fflush(stderr);

        /*  Malloc everything now that the number of regions is known.  */
        info = (struct table *)bu_malloc(numreg * sizeof(*info), "info");
        for (i=0; i<numreg; i++)
        {
            info[i].intrays = (double *)bu_malloc(numreg * sizeof(double), "info[i].intrays");
            info[i].sf = (double *)bu_malloc(numreg * sizeof(double), "info[i].sf");
        }

        /*  Zero all arrays.  */
        for (i=0; i<numreg; i++)
        {
            /*  START # 110  */
            info[i].name = "\0";
            info[i].lvrays = 0.;
            for (j=0; j<numreg; j++)
            {
                info[i].intrays[j] = 0.;
                info[i].sf[j] = 0.;
            }
            info[i].regarea = 0.;
        }						/*  END # 110  */

        /*  Get database ready by starting prep.  */
        rt_prep(rtip);

        /*  Find the center of the bounding rpp of entire model.  */
        centall[X] = rtip->mdl_min[X] +
                     (rtip->mdl_max[X] - rtip->mdl_min[X]) / 2.;
        centall[Y] = rtip->mdl_min[Y] +
                     (rtip->mdl_max[Y] - rtip->mdl_min[Y]) / 2.;
        centall[Z] = rtip->mdl_min[Z] +
                     (rtip->mdl_max[Z] - rtip->mdl_min[Z]) / 2.;

        /*  Find minimum and maximum of entire model.  */
        minall[X] = rtip->mdl_min[X];
        minall[Y] = rtip->mdl_min[Y];
        minall[Z] = rtip->mdl_min[Z];
        maxall[X] = rtip->mdl_max[X];
        maxall[Y] = rtip->mdl_max[Y];
        maxall[Z] = rtip->mdl_max[Z];

        /*  Find radius of bounding sphere.  */
        radall = (maxall[X] - minall[X]) * (maxall[X] - minall[X])
                 + (maxall[Y] - minall[Y]) * (maxall[Y] - minall[Y])
                 + (maxall[Z] - minall[Z]) * (maxall[Z] - minall[Z]);
        /*  Add .5 to make sure completely outside the rpp.  */
        radall = sqrt(radall) / 2. + .5;

        /*  Find surface area of bounding sphere.  */
        areaall = 4 * M_PI * radall * radall;

        /*  Print info on min, max, center, radius, & surface area  */
        /*  of entire model.  */
        (void)printf("Min & max for entire model.\n");
        (void)printf("\tX:  %f - %f\n", minall[X], maxall[X]);
        (void)printf("\tY:  %f - %f\n", minall[Y], maxall[Y]);
        (void)printf("\tZ:  %f - %f\n", minall[Z], maxall[Z]);
        (void)printf("Center:  %f, %f, %f\n\n", centall[X], centall[Y],
                     centall[Z]);
        (void)printf("Radius:  %f\n", radall);
        (void)printf("Surface Area:  %f\n\n", areaall);
        (void)fflush(stdout);

        /*  Find number of rays to fire.  */
        (void)printf("Enter the number of rays to be fired.\n\t");
        (void)fflush(stdout);
        (void)scanf("%lf", &rayfir);

        /*  Write info to files.  */
        (void)fprintf(fpw, "Min & max for entire region:\n");
        (void)fprintf(fpw, "\tX:  %f - %f\n", minall[X], maxall[X]);
        (void)fprintf(fpw, "\tY:  %f - %f\n", minall[Y], maxall[Y]);
        (void)fprintf(fpw, "\tZ:  %f - %f\n", minall[Z], maxall[Z]);
        (void)fprintf(fpw, "Center:  %f, %f, %f\n", centall[X],
                      centall[Y], centall[Z]);
        (void)fprintf(fpw, "Radius:  %f\n", radall);
        (void)fprintf(fpw, "Surface area:  %f\n", areaall);
        (void)fprintf(fpw, "Number of rays fired:  %f\n\n", rayfir);
        (void)fflush(fpw);

        (void)fprintf(fpw1, "Min & max for entire region:\n");
        (void)fprintf(fpw1, "\tX:  %f - %f\n", minall[X], maxall[X]);
        (void)fprintf(fpw1, "\tY:  %f - %f\n", minall[Y], maxall[Y]);
        (void)fprintf(fpw1, "\tZ:  %f - %f\n", minall[Z], maxall[Z]);
        (void)fprintf(fpw1, "Center:  %f, %f, %f\n", centall[X],
                      centall[Y], centall[Z]);
        (void)fprintf(fpw1, "Radius:  %f\n", radall);
        (void)fprintf(fpw1, "Surface area:  %f\n", areaall);
        (void)fprintf(fpw1, "Number of rays fired:  %f\n\n", rayfir);
        (void)fflush(fpw1);

        /*  Put region names into structure.  */
        pr = BU_LIST_FIRST(region, &rtip->HeadRegion);
        for (i=0; i<numreg; i++)
        {
            info[(int)(pr->reg_bit)].name = pr->reg_name;
            pr = BU_LIST_FORW(region, &(pr->l) );
        }

        (void)printf("Region names in structure.\n");
        (void)fflush(stdout);

        /*  Write region names to error file.  */
        for (i=0; i<numreg; i++)
        {
            (void)fprintf(fpw1, "region %d:  %s\n", (i + 1), info[i].name);
            (void)fflush(fpw1);
        }
        (void)fprintf(fpw1, "\n");
        (void)fflush(fpw1);

        /*  Set seed for random number generator.  */
        seed = 1;
        (void)printf("Do you wish to enter your own seed (0) or ");
        (void)printf("use the default of 1 (1)?\n\t");
        (void)fflush(stdout);
        (void)scanf("%d", &ians);
        if (ians == 0)
        {
            (void)printf("Enter unsigned integer seed.\n\t");
            (void)fflush(stdout);
            (void)scanf("%ld", &seed);
        }
        msr = bn_unif_init(seed, 0);

        (void)printf("Seed initialized\n");
        (void)fflush(stdout);

        /*  Set up parameters for rt_shootray.  */
        RT_APPLICATION_INIT(&ap);
        ap.a_hit = hit;			/*  User supplied hit func.  */
        ap.a_miss = miss;		/*  User supplied miss func.  */
        ap.a_overlap = overlap;		/*  User supplied overlap func.  */
        ap.a_rt_i = rtip;		/*  Pointer from rt_dirbuild.  */
        ap.a_onehit = 0;		/*  Look at all hits.  */
        ap.a_level = 0;			/*  Recursion level for diagnostics.  */
        ap.a_resource = 0;		/*  Address for resource struct.  */
        /*
         *	(void)printf("Parameters for rt_shootray set.\n");
         *	(void)fflush(stdout);
         */

        /*  Loop through for each ray fired.  */
        for (r=0; r<rayfir; r++)
        {
            /*  START # 150  */
            /*
             *		(void)printf("In loop - %f\n", r);
             *		(void)fflush(stdout);
             */

            /*  Find point on the bounding sphere.  The negative  */
            /*  of the unit vector of this point will be the  */
            /*  firing direction.  */
            q = BN_UNIF_DOUBLE(msr) + 0.5;
            theta = q * 2. * M_PI;

            q = BN_UNIF_DOUBLE(msr) + 0.5;
            phi = (q * 2.) - 1.;
            phi = acos(phi);

            rho = radall;

            strtdir[X] = rho * sin(phi) * cos(theta);
            strtdir[Y] = rho * sin(phi) * sin(theta);
            strtdir[Z] = rho * cos(phi);

            /*  Elevation & azimuth for finding a vector in a plane.  */
            elev = M_PI / 2. - phi;
            az = theta;

            /*  Find vector in yz-plane.  */
            q = BN_UNIF_DOUBLE(msr) + 0.5;
            theta = q * 2. * M_PI;

            q = BN_UNIF_DOUBLE(msr) + 0.5;
            rds = rho * sqrt(q);
            s[X] = 0.;
            s[Y] = rds * cos(theta);
            s[Z] = rds * sin(theta);

            /*  Rotate vector.  */
            t[X] = s[X] * cos(elev) * cos(az) - s[Z] * sin(elev) * cos(az)
                   - s[Y] * sin(az);
            t[Y] = s[X] * cos(elev) * sin(az) - s[Z] * sin(elev) * sin(az)
                   + s[Y] * cos(az);
            t[Z] = s[X] * sin(elev) + s[Z] * cos(elev);

            /*  Translate the point.  This is the starting point.  */
            strtpt[X] = t[X] + strtdir[X];
            strtpt[Y] = t[Y] + strtdir[Y];
            strtpt[Z] = t[Z] + strtdir[Z];

            /*  Now transfer the starting point so that it is in the  */
            /*  absolute coordinates not the origin's.  */
            strtpt[X] += centall[X];
            strtpt[Y] += centall[Y];
            strtpt[Z] += centall[Z];

            /*  Normalize starting direction & make negative.  */
            denom = strtdir[X] *strtdir[X] +
                    strtdir[Y] *strtdir[Y] +
                    strtdir[Z] *strtdir[Z];
            denom = sqrt(denom);
            strtdir[X] /= (-denom);
            strtdir[Y] /= (-denom);
            strtdir[Z] /= (-denom);

            /*  Set up firing point & direction.  */
            ap.a_ray.r_pt[X] = strtpt[X];
            ap.a_ray.r_pt[Y] = strtpt[Y];
            ap.a_ray.r_pt[Z] = strtpt[Z];
            ap.a_ray.r_dir[X] = strtdir[X];
            ap.a_ray.r_dir[Y] = strtdir[Y];
            ap.a_ray.r_dir[Z] = strtdir[Z];

            /*
             *		(void)printf("Calling rt_shootray.\n");
             *		(void)fflush(stdout);
             */

            /*  Call rt_shootray.  */
            (void)rt_shootray(&ap);

            /*
             *		(void)printf("Rt_shootray finished.\n");
             *		(void)fflush(stdout);
             */

        }						/*  END # 150  */

        /*
         *	   (void)printf("Finished loop.\n");
         *	   (void)fflush(stdout);
         */

        for (i=0; i<numreg; i++)
        {
            /*  START # 160  */
            /*  Write region names to output file.  */
            (void)fprintf(fpw, "Region %d:  %s\n", (i+1), info[i].name);
            (void)fflush(fpw);

            /*  Find shape factors & print.  */
            if (info[i].lvrays == 0)
            {
                /*  START # 1060  */
                (void)fprintf(fpw1, "**  ERROR - # or rays hitting region ");
                (void)fprintf(fpw1, "%d is 0.  **\n", i);
                (void)fflush(fpw1);
            }						/*  END # 1060  */

            else
            {
                /*  START # 1070  */
                /*  Must divide by 2. since looking forwards & backwards.  */
                info[i].regarea = info[i].lvrays / rayfir * areaall / 2.;
                for (j=0; j<numreg; j++)
                {
                    /*  START # 1080  */
                    info[i].sf[j] = info[i].intrays[j] / info[i].lvrays;
                    (void)fprintf(fpw, "\t%d   %d   %f\n",
                                  (i + 1), (j + 1), info[i].sf[j]);
                    (void)fflush(fpw);

                    (void)fprintf(fpw1, "reg %d - reg %d - rays leave ",
                                  (i + 1), (j + 1));
                    (void)fprintf(fpw1, "& int %f - rays leave %f ",
                                  info[i].intrays[j], info[i].lvrays);
                    (void)fprintf(fpw1, "- sf %f - area %f\n",
                                  info[i].sf[j], info[i].regarea);
                    (void)fflush(fpw1);
                }					/*  END # 1080  */
            }						/*  END # 1070  */
        }						/*  END # 160  */

        /*  Write lwx file.  */
        (void)fprintf(fpw2, "Longwave Radiation Exchange Factors ");
        (void)fprintf(fpw2, "for %s\n", argv[1]);
        (void)fprintf(fpw2, "Number of Regions = %4d\n", numreg);
        (void)fprintf(fpw2, "TEMIS\n\n");

        for (i=0; i<numreg; i++)
        {
            /*  START # 1090  */
            (void)fprintf(fpw2, "Region\tArea\tEmissivity\n");
            /*  Area is put into square meters.  */
            (void)fprintf(fpw2, "%d\t%f\n", (i + 1),
                          (info[i].regarea / 1000. / 1000.));

            /*  Count the number of shape factors.  */
            k = 0;
            for (j=0; j<numreg; j++)
            {
                if (info[i].sf[j] != 0.) k++;
            }
            (void)fprintf(fpw2, "Bij\t%d\n", k);

            /*  Print shape factors.  */
            m = 0;
            for (j=0; j<numreg; j++)
            {
                /*  START # 1100  */
                if (info[i].sf[j] != 0.)
                {
                    /*  START # 1110  */
                    (void)fprintf(fpw2, "%4d   %.4f   ", (j + 1),
                                  info[i].sf[j]);
                    m++;
                    if (m == 5)
                    {
                        /*  START # 1120  */
                        m = 0;
                        (void)fprintf(fpw2, "\n");
                    }				/*  END # 1120  */
                }					/*  END # 1110  */
            }					/*  END # 1100  */
            if (m != 0) (void)fprintf(fpw2, "\n");
            (void)fprintf(fpw2, " Gnd         Sky\n\n");
            (void)fflush(fpw2);
        }						/*  END # 1090  */


        /* free memory */
        for (i=0; i<numreg; i++)
        {
            bu_free(info[i].intrays, "info[i].intrays");
            bu_free(info[i].sf, "info[i].sf");
        }
        bu_free(info, "info");

        /*  Close files.  */
        (void)fclose(fpw);
        (void)fclose(fpw1);
        (void)fclose(fpw2);
    }							/*  END # 100  */
    return 0;
}							/*  END # 99  */
Ejemplo n.º 11
0
/*
 * R R _ H I T
 *
 * This routine is called when an internal reflection ray hits something
 * (which is ordinarily the case).
 *
 * Generally, there will be one or two partitions on the hit list.
 * The values for pt_outhit for the second partition should not be used,
 * as a_onehit was set to 3, getting a maximum of 3 valid hit points.
 *
 * Explicit Returns -
 * 0 dreadful internal error
 * 1 treat as escaping ray & reshoot
 * 2 Proper exit point determined, with Implicit Returns:
 *	a_uvec		exit Point
 *	a_vvec		exit Normal (inward pointing)
 *	a_refrac_index	RI of *next* material
 */
HIDDEN int
rr_hit(struct application *ap, struct partition *PartHeadp, struct seg *UNUSED(segp))
{
    register struct partition *pp;
    register struct hit *hitp;
    register struct soltab *stp;
    struct partition *psave = (struct partition *)NULL;
    struct shadework sw;
    struct application appl;
    int ret;

    RT_AP_CHECK(ap);

    RT_APPLICATION_INIT(&appl);

    for (pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw)
	if (pp->pt_outhit->hit_dist > 0.0) break;
    if (pp == PartHeadp) {
	if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) {
	    bu_log("rr_hit:  %d, %d no hit out front?\n",
		   ap->a_x, ap->a_y);
	    ret = 0;	/* error */
	    goto out;
	}
	ret = 1;		/* treat as escaping ray */
	goto out;
    }

    /*
     * Ensure that the partition we are given is part of the same
     * region that we started in.  When the internal reflection
     * is happening very near an edge or corner, this is not always
     * the case, and either (a) a small sliver of some other region
     * is found to be in the way, or (b) the ray completely misses the
     * region that it started in, although not by much.
     */
    psave = pp;
    if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_hit(%s)\n", psave->pt_regionp->reg_name);
    for (; pp != PartHeadp; pp = pp->pt_forw)
	if (pp->pt_regionp == (struct region *)(ap->a_uptr)) break;
    if (pp == PartHeadp) {
	if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) {
	    bu_log("rr_hit:  %d, %d Ray internal to %s landed unexpectedly in %s\n",
		   ap->a_x, ap->a_y,
		   ((struct region *)(ap->a_uptr))->reg_name,
		   psave->pt_regionp->reg_name);
	    ret = 0;	/* error */
	    goto out;
	}
	ret = 1;		/* treat as escaping ray */
	goto out;
    }

    /*
     * At one time, this was a check for pp->pt_inhit->hit_dist
     * being NEAR zero.  That was a mistake, because we may have
     * been at the edge of a subtracted out center piece when
     * internal reflection happened, except that floating point
     * error (being right on the surface of the interior solid)
     * prevented us from "seeing" that solid on the next ray,
     * causing our ray endpoints to be quite far from the starting
     * point, yet with the ray still validly inside the glass region.
     *
     * There is a major problem if the entry point
     * is further ahead than the firing point, i.e., >0.
     *
     * Because this error has not yet been encountered, it is
     * considered dreadful.  Some recovery may be possible.
     *
     * For now, this seems to happen when a reflected ray starts outside
     * the glass and doesn't even intersect the glass, so treat it as
     * an escaping ray.
     */

    if (pp->pt_inhit->hit_dist > 10) {
	stp = pp->pt_inseg->seg_stp;
	if (R_DEBUG&RDEBUG_REFRACT)
	    bu_log("rr_hit: %d, %d %s inhit %g > 10.0! (treating as escaping ray)\n",
		   ap->a_x, ap->a_y,
		   pp->pt_regionp->reg_name,
		   pp->pt_inhit->hit_dist);
	ret = 1;	/* treat as escaping ray */
	goto out;
    }

    /*
     * If there is a very small crack in the glass, perhaps formed
     * by a small error when taking the Union of two solids,
     * attempt to find the real exit point.
     * NOTE that this is usually taken care of inside librt
     * in the bool_weave code, but it is inexpensive to check for it
     * here.  If this case is detected, push on, and log it.
     * This code is not expected to be needed.
     */
    while (pp->pt_forw != PartHeadp) {
	register fastf_t d;
	d = pp->pt_forw->pt_inhit->hit_dist - pp->pt_outhit->hit_dist;
	if (!NEAR_ZERO(d, AIR_GAP_TOL))
	    break;
	if (pp->pt_forw->pt_regionp != pp->pt_regionp)
	    break;
	if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) bu_log(
	    "rr_hit: %d, %d fusing small crack in glass %s\n",
	    ap->a_x, ap->a_y,
	    pp->pt_regionp->reg_name);
	pp = pp->pt_forw;
    }

    hitp = pp->pt_outhit;
    stp = pp->pt_outseg->seg_stp;
    if (hitp->hit_dist >= INFINITY) {
	bu_log("rr_hit: %d, %d infinite glass (%g, %g) %s\n",
	       ap->a_x, ap->a_y,
	       pp->pt_inhit->hit_dist, hitp->hit_dist,
	       pp->pt_regionp->reg_name);
	ret = 0;		/* dreadful error */
	goto out;
    }
    VJOIN1(hitp->hit_point, ap->a_ray.r_pt,
	   hitp->hit_dist, ap->a_ray.r_dir);
    RT_HIT_NORMAL(ap->a_vvec, hitp, stp, &(ap->a_ray), pp->pt_outflip);

    /* For refraction, want exit normal to point inward. */
    VREVERSE(ap->a_vvec, ap->a_vvec);
    VMOVE(ap->a_uvec, hitp->hit_point);
    ap->a_cumlen += (hitp->hit_dist - pp->pt_inhit->hit_dist);

    ap->a_refrac_index = RI_AIR;			/* Default medium: air */

    /*
     * Look ahead, and see if there is more glass to come.
     * If so, obtain its refractive index, to enable correct
     * calculation of the departing refraction angle.
     */
    if (pp->pt_forw != PartHeadp) {
	register fastf_t d;
	d = pp->pt_forw->pt_inhit->hit_dist - hitp->hit_dist;
	if (NEAR_ZERO(d, AIR_GAP_TOL)) {
	    /*
	     * Make a private copy of the application struct,
	     * because viewshade() may change various fields.
	     */
	    appl = *ap;			/* struct copy */

	    memset((char *)&sw, 0, sizeof(sw));
	    sw.sw_transmit = sw.sw_reflect = 0.0;

	    /* Set default in case shader doesn't fill this in. */
	    sw.sw_refrac_index = RI_AIR;

	    /* Set special flag so that we get only shader
	     * parameters (refractive index, in this case).
	     * We don't even care about transmitted energy.
	     */
	    sw.sw_xmitonly = 2;
	    sw.sw_inputs = 0;		/* no fields filled yet */
#ifdef RT_MULTISPECTRAL
	    sw.msw_color = bn_tabdata_get_constval(1.0, spectrum);
	    sw.msw_basecolor = bn_tabdata_get_constval(1.0, spectrum);
#else
	    VSETALL(sw.sw_color, 1);
	    VSETALL(sw.sw_basecolor, 1);
#endif

	    if (R_DEBUG&(RDEBUG_SHADE|RDEBUG_REFRACT))
		bu_log("rr_hit calling viewshade to discover refractive index\n");

	    (void)viewshade(&appl, pp->pt_forw, &sw);

#ifdef RT_MULTISPECTRAL
	    bu_free(sw.msw_color, "sw.msw_color");
	    bu_free(sw.msw_basecolor, "sw.msw_basecolor");
#endif

	    if (R_DEBUG&(RDEBUG_SHADE|RDEBUG_REFRACT))
		bu_log("rr_hit refractive index = %g\n", sw.sw_refrac_index);

	    if (sw.sw_transmit > 0) {
		ap->a_refrac_index = sw.sw_refrac_index;
		if (R_DEBUG&RDEBUG_SHADE) {
		    bu_log("rr_hit a_refrac_index=%g (trans=%g)\n",
			   ap->a_refrac_index,
			   sw.sw_transmit);
		}
		ret= 3;	/* OK -- more glass follows */
		goto out;
	    }
	}
    }
    ret = 2;				/* OK -- no more glass */
out:
    if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_hit(%s) return=%d\n",
				       psave ? psave->pt_regionp->reg_name : "",
				       ret);
    return ret;
}
Ejemplo n.º 12
0
/*
 * R R _ R E N D E R
 */
int
rr_render(register struct application *ap,
	  const struct partition *pp,
	  struct shadework *swp)
{
    struct application sub_ap;
    vect_t work;
    vect_t incident_dir;
    fastf_t shader_fract;
    fastf_t reflect;
    fastf_t transmit;

#ifdef RT_MULTISPECTRAL
    struct bn_tabdata *ms_filter_color = BN_TABDATA_NULL;
    struct bn_tabdata *ms_shader_color = BN_TABDATA_NULL;
    struct bn_tabdata *ms_reflect_color = BN_TABDATA_NULL;
    struct bn_tabdata *ms_transmit_color = BN_TABDATA_NULL;
#else
    vect_t filter_color;
    vect_t shader_color;
    vect_t reflect_color;
    vect_t transmit_color;
#endif

    fastf_t attenuation;
    vect_t to_eye;
    int code;

    RT_AP_CHECK(ap);

    RT_APPLICATION_INIT(&sub_ap);

#ifdef RT_MULTISPECTRAL
    sub_ap.a_spectrum = BN_TABDATA_NULL;
    ms_reflect_color = bn_tabdata_get_constval(0.0, spectrum);
#endif

    /*
     * sw_xmitonly is set primarily for light visibility rays.
     * Need to compute (partial) transmission through to the light,
     * or procedural shaders won't be able to cast shadows
     * and light won't be able to get through glass
     * (including "stained glass" and "filter glass").
     *
     * On the other hand, light visibility rays shouldn't be refracted,
     * it is pointless to shoot at where the light isn't.
     */
    if (swp->sw_xmitonly) {
	/* Caller wants transmission term only, don't fire reflected rays */
	transmit = swp->sw_transmit + swp->sw_reflect;	/* Don't loose energy */
	reflect = 0;
    } else {
	reflect = swp->sw_reflect;
	transmit = swp->sw_transmit;
    }
    if (R_DEBUG&RDEBUG_REFRACT) {
	bu_log("rr_render(%s) START: lvl=%d reflect=%g, transmit=%g, xmitonly=%d\n",
	       pp->pt_regionp->reg_name,
	       ap->a_level,
	       reflect, transmit,
	       swp->sw_xmitonly);
    }
    if (reflect <= 0 && transmit <= 0)
	goto out;

    if (ap->a_level > max_bounces) {
	/* Nothing more to do for this ray */
	static long count = 0;		/* Not PARALLEL, should be OK */

	if ((R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) && (
		count++ < MSG_PROLOGUE ||
		(count%MSG_INTERVAL) == 3
		)) {
	    bu_log("rr_render: %d, %d MAX BOUNCES=%d: %s\n",
		   ap->a_x, ap->a_y,
		   ap->a_level,
		   pp->pt_regionp->reg_name);
	}

	/*
	 * Return the basic color of the object, ignoring the
	 * the fact that it is supposed to be
	 * filtering or reflecting light here.
	 * This is much better than returning just black,
	 * but something better might be done.
	 */
#ifdef RT_MULTISPECTRAL
	BN_CK_TABDATA(swp->msw_color);
	BN_CK_TABDATA(swp->msw_basecolor);
	bn_tabdata_copy(swp->msw_color, swp->msw_basecolor);
#else
	VMOVE(swp->sw_color, swp->sw_basecolor);
#endif
	ap->a_cumlen += pp->pt_inhit->hit_dist;
	goto out;
    }
#ifdef RT_MULTISPECTRAL
    BN_CK_TABDATA(swp->msw_basecolor);
    ms_filter_color = bn_tabdata_dup(swp->msw_basecolor);

#else
    VMOVE(filter_color, swp->sw_basecolor);
#endif

    if ((swp->sw_inputs & (MFI_HIT|MFI_NORMAL)) != (MFI_HIT|MFI_NORMAL))
	shade_inputs(ap, pp, swp, MFI_HIT|MFI_NORMAL);

    /*
     * If this ray is being fired from the exit point of
     * an object, and is directly entering another object,
     * (i.e., there is no intervening air-gap), and
     * the two refractive indices match, then do not fire a
     * reflected ray -- just take the transmission contribution.
     * This is important, e.g., for glass gun tubes projecting
     * through a glass armor plate. :-)
     */
    if (NEAR_ZERO(pp->pt_inhit->hit_dist, AIR_GAP_TOL)
	&& ZERO(ap->a_refrac_index - swp->sw_refrac_index))
    {
	transmit += reflect;
	reflect = 0;
    }

    /*
     * Diminish base color appropriately, and add in
     * contributions from mirror reflection & transparency
     */
    shader_fract = 1 - (reflect + transmit);
    if (shader_fract < 0) {
	shader_fract = 0;
    } else if (shader_fract >= 1) {
	goto out;
    }
    if (R_DEBUG&RDEBUG_REFRACT) {
	bu_log("rr_render: lvl=%d start shader=%g, reflect=%g, transmit=%g %s\n",
	       ap->a_level,
	       shader_fract, reflect, transmit,
	       pp->pt_regionp->reg_name);
    }
#ifdef RT_MULTISPECTRAL
    BN_GET_TABDATA(ms_shader_color, swp->msw_color->table);
    bn_tabdata_scale(ms_shader_color, swp->msw_color, shader_fract);
#else
    VSCALE(shader_color, swp->sw_color, shader_fract);
#endif

    /*
     * Compute transmission through an object.
     * There may be a mirror reflection, which will be handled
     * by the reflection code later
     */
    if (transmit > 0) {
	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: lvl=%d transmit=%g.  Calculate refraction at entrance to %s.\n",
		   ap->a_level, transmit,
		   pp->pt_regionp->reg_name);
	}
	/*
	 * Calculate refraction at entrance.
	 */
	sub_ap = *ap;		/* struct copy */
#ifdef RT_MULTISPECTRAL
	sub_ap.a_spectrum = bn_tabdata_dup((struct bn_tabdata *)ap->a_spectrum);
#endif
	sub_ap.a_level = 0;	/* # of internal reflections */
	sub_ap.a_cumlen = 0;	/* distance through the glass */
	sub_ap.a_user = -1;	/* sanity */
	sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge;
	sub_ap.a_diverge = 0.0;
	sub_ap.a_uptr = (genptr_t)(pp->pt_regionp);
	VMOVE(sub_ap.a_ray.r_pt, swp->sw_hit.hit_point);
	VMOVE(incident_dir, ap->a_ray.r_dir);

	/* If there is an air gap, reset ray's RI to air */
	if (pp->pt_inhit->hit_dist > AIR_GAP_TOL)
	    sub_ap.a_refrac_index = RI_AIR;

	if (!ZERO(sub_ap.a_refrac_index - swp->sw_refrac_index)
	    && !rr_refract(incident_dir,		/* input direction */
			   swp->sw_hit.hit_normal,	/* exit normal */
			   sub_ap.a_refrac_index,	/* current RI */
			   swp->sw_refrac_index,	/* next RI */
			   sub_ap.a_ray.r_dir		/* output direction */
		))
	{
	    /*
	     * Ray was mirror reflected back outside solid.
	     * Just add contribution to reflection,
	     * and quit.
	     */
	    reflect += transmit;
	    transmit = 0;
#ifdef RT_MULTISPECTRAL
	    ms_transmit_color = bn_tabdata_get_constval(0.0, spectrum);
#else
	    VSETALL(transmit_color, 0);
#endif
	    if (R_DEBUG&RDEBUG_REFRACT) {
		bu_log("rr_render: lvl=%d change xmit into reflection %s\n",
		       ap->a_level,
		       pp->pt_regionp->reg_name);
	    }
	    goto do_reflection;
	}
	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: lvl=%d begin transmission through %s.\n",
		   ap->a_level,
		   pp->pt_regionp->reg_name);
	}

	/*
	 * Find new exit point from the inside.
	 * We will iterate, but not recurse, due to the special
	 * (non-recursing) hit and miss routines used here for
	 * internal reflection.
	 *
	 * a_onehit is set to 3, so that where possible,
	 * rr_hit() will be given three accurate hit points:
	 * the entry and exit points of this glass region,
	 * and the entry point into the next region.
	 * This permits calculation of the departing
	 * refraction angle based on the RI of the current and
	 * *next* regions along the ray.
	 */
	sub_ap.a_purpose = "rr first glass transmission ray";
	sub_ap.a_flag = 0;
    do_inside:
	sub_ap.a_hit =  rr_hit;
	sub_ap.a_miss = rr_miss;
	sub_ap.a_logoverlap = ap->a_logoverlap;
	sub_ap.a_onehit = 3;
	sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge;
	sub_ap.a_diverge = 0.0;
	switch (code = rt_shootray(&sub_ap)) {
	    case 3:
		/* More glass to come.
		 * uvec=exit_pt, vvec=N, a_refrac_index = next RI.
		 */
		break;
	    case 2:
		/* No more glass to come.
		 * uvec=exit_pt, vvec=N, a_refrac_index = next RI.
		 */
		break;
	    case 1:
		/* Treat as escaping ray */
		if (R_DEBUG&RDEBUG_REFRACT)
		    bu_log("rr_refract: Treating as escaping ray\n");
		goto do_exit;
	    case 0:
	    default:
		/* Dreadful error */
#ifdef RT_MULTISPECTRAL
		bu_bomb("rr_refract: Stuck in glass. Very green pixel, unsupported in multi-spectral mode\n");
#else
		VSET(swp->sw_color, 0, 99, 0); /* very green */
#endif
		goto out;			/* abandon hope */
	}

	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: calculating refraction @ exit from %s (green)\n", pp->pt_regionp->reg_name);
	    bu_log("Start point to exit point:\n\
vdraw open rr;vdraw params c 00ff00; vdraw write n 0 %g %g %g; vdraw wwrite n 1 %g %g %g; vdraw send\n",
		   V3ARGS(sub_ap.a_ray.r_pt),
		   V3ARGS(sub_ap.a_uvec));
	}
	/* NOTE: rr_hit returns EXIT Point in sub_ap.a_uvec,
	 * and returns EXIT Normal in sub_ap.a_vvec,
	 * and returns next RI in sub_ap.a_refrac_index
	 */
	if (R_DEBUG&RDEBUG_RAYWRITE) {
	    wraypts(sub_ap.a_ray.r_pt,
		    sub_ap.a_ray.r_dir,
		    sub_ap.a_uvec,
		    2, ap, stdout);	/* 2 = ?? */
	}
	if (R_DEBUG&RDEBUG_RAYPLOT) {
	    /* plotfp */
	    bu_semaphore_acquire(BU_SEM_SYSCALL);
	    pl_color(stdout, 0, 255, 0);
	    pdv_3line(stdout,
		      sub_ap.a_ray.r_pt,
		      sub_ap.a_uvec);
	    bu_semaphore_release(BU_SEM_SYSCALL);
	}
	/* Advance.  Exit point becomes new start point */
	VMOVE(sub_ap.a_ray.r_pt, sub_ap.a_uvec);
	VMOVE(incident_dir, sub_ap.a_ray.r_dir);

	/*
	 * Calculate refraction at exit point.
	 * Use "look ahead" RI value from rr_hit.
	 */
	if (!ZERO(sub_ap.a_refrac_index - swp->sw_refrac_index)
	    && !rr_refract(incident_dir,		/* input direction */
			   sub_ap.a_vvec,		/* exit normal */
			   swp->sw_refrac_index,	/* current RI */
			   sub_ap.a_refrac_index,	/* next RI */
			   sub_ap.a_ray.r_dir		/* output direction */
		))
	{
	    static long count = 0;		/* not PARALLEL, should be OK */

	    /* Reflected internally -- keep going */
	    if ((++sub_ap.a_level) <= max_ireflect) {
		sub_ap.a_purpose = "rr reflected internal ray, probing for glass exit point";
		sub_ap.a_flag = 0;
		goto do_inside;
	    }

	    /*
	     * Internal Reflection limit exceeded -- just let
	     * the ray escape, continuing on current course.
	     * This will cause some energy from somewhere in the
	     * scene to be received through this glass,
	     * which is much better than just returning
	     * grey or black, as before.
	     */
	    if ((R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) && (
		    count++ < MSG_PROLOGUE ||
		    (count%MSG_INTERVAL) == 3
		    )) {
		bu_log("rr_render: %d, %d Int.reflect=%d: %s lvl=%d\n",
		       sub_ap.a_x, sub_ap.a_y,
		       sub_ap.a_level,
		       pp->pt_regionp->reg_name,
		       ap->a_level);
	    }
	    VMOVE(sub_ap.a_ray.r_dir, incident_dir);
	    goto do_exit;
	}
    do_exit:
	/*
	 * Compute internal spectral transmittance.
	 * Bouger's law.  pg 30 of "color science"
	 *
	 * Apply attenuation factor due to thickness of the glass.
	 * sw_extinction is in terms of fraction of light absorbed
	 * per linear meter of glass.  a_cumlen is in mm.
	 */
/* XXX extinction should be a spectral curve, not scalor */
	if (swp->sw_extinction > 0 && sub_ap.a_cumlen > 0) {
	    attenuation = pow(10.0, -1.0e-3 * sub_ap.a_cumlen *
			      swp->sw_extinction);
	} else {
	    attenuation = 1;
	}

	/*
	 * Process the escaping refracted ray.
	 * This is the only place we might recurse dangerously,
	 * so we are careful to use our caller's recursion level+1.
	 * NOTE: point & direction already filled in
	 */
	sub_ap.a_hit =  ap->a_hit;
	sub_ap.a_miss = ap->a_miss;
	sub_ap.a_logoverlap = ap->a_logoverlap;
	sub_ap.a_onehit = ap->a_onehit;
	sub_ap.a_level = ap->a_level+1;
	sub_ap.a_uptr = ap->a_uptr;
	sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge;
	sub_ap.a_diverge = 0.0;
	if (code == 3) {
	    sub_ap.a_purpose = "rr recurse on next glass";
	    sub_ap.a_flag = 0;
	} else {
	    sub_ap.a_purpose = "rr recurse on escaping internal ray";
	    sub_ap.a_flag = 1;
	    sub_ap.a_onehit = sub_ap.a_onehit > -3 ? -3 : sub_ap.a_onehit;
	}
	/* sub_ap.a_refrac_index was set to RI of next material by rr_hit().
	 */
	sub_ap.a_cumlen = 0;
	(void) rt_shootray(&sub_ap);

	/* a_user has hit/miss flag! */
	if (sub_ap.a_user == 0) {
#ifdef RT_MULTISPECTRAL
	    ms_transmit_color = bn_tabdata_dup(background);
#else
	    VMOVE(transmit_color, background);
#endif
	    sub_ap.a_cumlen = 0;
	} else {
#ifdef RT_MULTISPECTRAL
	    ms_transmit_color = bn_tabdata_dup(sub_ap.a_spectrum);
#else
	    VMOVE(transmit_color, sub_ap.a_color);
#endif
	}
	transmit *= attenuation;
#ifdef RT_MULTISPECTRAL
	bn_tabdata_mul(ms_transmit_color, ms_filter_color, ms_transmit_color);
#else
	VELMUL(transmit_color, filter_color, transmit_color);
#endif
	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: lvl=%d end of xmit through %s\n",
		   ap->a_level,
		   pp->pt_regionp->reg_name);
	}
    } else {
Ejemplo n.º 13
0
/*
 *			M A I N
 */
int main(int argc, char **argv)
{
    struct rt_i *rtip = NULL;
    char *title_file = NULL, *title_obj = NULL;	/* name of file and first object */
    char idbuf[RT_BUFSIZE] = {0};		/* First ID record info */
    void	application_init();
    struct bu_vls	times;
    int i;

#if defined(_WIN32) && !defined(__CYGWIN__)
    setmode(fileno(stdin), O_BINARY);
    setmode(fileno(stdout), O_BINARY);
    setmode(fileno(stderr), O_BINARY);
#else
    bu_setlinebuf( stdout );
    bu_setlinebuf( stderr );
#endif

#ifdef HAVE_SBRK
    beginptr = (char *) sbrk(0);
#endif
    azimuth = 35.0;			/* GIFT defaults */
    elevation = 25.0;

    AmbientIntensity=0.4;
    background[0] = background[1] = 0.0;
    background[2] = 1.0/255.0; /* slightly non-black */

    /* Before option processing, get default number of processors */
    npsw = bu_avail_cpus();		/* Use all that are present */
    if ( npsw > MAX_PSW )  npsw = MAX_PSW;

    /* Before option processing, do application-specific initialization */
    RT_APPLICATION_INIT( &ap );
    application_init();

    /* Process command line options */
    if ( !get_args( argc, argv ) )  {
	(void)fputs(usage, stderr);
	return 1;
    }
    /* Identify the versions of the libraries we are using. */
    if (rt_verbosity & VERBOSE_LIBVERSIONS) {
	(void)fprintf(stderr, "%s%s%s%s\n",
		      brlcad_ident(title),
		      rt_version(),
		      bn_version(),
		      bu_version()
	    );
    }
#if defined(DEBUG)
    (void)fprintf(stderr, "Compile-time debug symbols are available\n");
#endif
#if defined(NO_BOMBING_MACROS) || defined(NO_MAGIC_CHECKING) || defined(NO_BADRAY_CECHKING) || defined(NO_DEBUG_CHECKING)
    (void)fprintf(stderr, "WARNING: Run-time debugging is disabled and may enhance performance\n");
#endif

    /* Identify what host we're running on */
    if (rt_verbosity & VERBOSE_LIBVERSIONS) {
	char	hostname[512] = {0};
#ifndef _WIN32
	if ( gethostname( hostname, sizeof(hostname) ) >= 0 &&
	     hostname[0] != '\0' )
	    (void)fprintf(stderr, "Running on %s\n", hostname);
#else
	sprintf(hostname, "Microsoft Windows");
	(void)fprintf(stderr, "Running on %s\n", hostname);
#endif
    }

    if ( bu_optind >= argc )  {
	fprintf(stderr, "%s:  MGED database not specified\n", argv[0]);
	(void)fputs(usage, stderr);
	return 1;
    }

    if (rpt_overlap)
	ap.a_logoverlap = ((void (*)())0);
    else
	ap.a_logoverlap = rt_silent_logoverlap;

    /* If user gave no sizing info at all, use 512 as default */
    if ( width <= 0 && cell_width <= 0 )
	width = 512;
    if ( height <= 0 && cell_height <= 0 )
	height = 512;

    /* If user didn't provide an aspect ratio, use the image
     * dimensions ratio as a default.
     */
    if (aspect <= 0.0) {
	aspect = (fastf_t)width / (fastf_t)height;
    }

    if ( sub_grid_mode ) {
	/* check that we have a legal subgrid */
	if ( sub_xmax >= width || sub_ymax >= height ) {
	    fprintf( stderr, "rt: illegal values for subgrid %d,%d,%d,%d\n",
		     sub_xmin, sub_ymin, sub_xmax, sub_ymax );
	    fprintf( stderr, "\tFor a %d X %d image, the subgrid must be within 0, 0,%d,%d\n",
		     width, height, width-1, height-1 );
	    return 1;
	}
    }

    if ( incr_mode )  {
	int x = height;
	if ( x < width )  x = width;
	incr_nlevel = 1;
	while ( (1<<incr_nlevel) < x )
	    incr_nlevel++;
	height = width = 1<<incr_nlevel;
	if (rt_verbosity & VERBOSE_INCREMENTAL)
	    fprintf(stderr,
		    "incremental resolution, nlevels = %d, width=%d\n",
		    incr_nlevel, width);
    }

    /*
     *  Handle parallel initialization, if applicable.
     */
#ifndef PARALLEL
    npsw = 1;			/* force serial */
#endif

    if ( npsw < 0 )  {
	/* Negative number means "all but" npsw */
	npsw = bu_avail_cpus() + npsw;
    }


    /* allow debug builds to go higher than the max */
    if (!(bu_debug & BU_DEBUG_PARALLEL)) {
	if ( npsw > MAX_PSW ) {
	    npsw = MAX_PSW;
	}
    }

    if (npsw > 1) {
	rt_g.rtg_parallel = 1;
	if (rt_verbosity & VERBOSE_MULTICPU)
	    fprintf(stderr, "Planning to run with %d processors\n", npsw );
    } else {
	rt_g.rtg_parallel = 0;
    }

    /* Initialize parallel processor support */
    bu_semaphore_init( RT_SEM_LAST );

    /*
     *  Do not use bu_log() or bu_malloc() before this point!
     */

    if ( bu_debug )  {
	bu_printb( "libbu bu_debug", bu_debug, BU_DEBUG_FORMAT );
	bu_log("\n");
    }

    if ( RT_G_DEBUG )  {
	bu_printb( "librt rt_g.debug", rt_g.debug, DEBUG_FORMAT );
	bu_log("\n");
    }
    if ( rdebug )  {
	bu_printb( "rt rdebug", rdebug, RDEBUG_FORMAT );
	bu_log("\n");
    }

    /* We need this to run rt_dirbuild */
    rt_init_resource( &rt_uniresource, MAX_PSW, NULL );
    bn_rand_init( rt_uniresource.re_randptr, 0 );

    title_file = argv[bu_optind];
    title_obj = argv[bu_optind+1];
    nobjs = argc - bu_optind - 1;
    objtab = &(argv[bu_optind+1]);

    if ( nobjs <= 0 )  {
	bu_log("%s: no objects specified -- raytrace aborted\n", argv[0]);
	return 1;
    }

    /* Echo back the command line arugments as given, in 3 Tcl commands */
    if (rt_verbosity & VERBOSE_MODELTITLE) {
	struct bu_vls str;
	bu_vls_init(&str);
	bu_vls_from_argv( &str, bu_optind, (const char **)argv );
	bu_vls_strcat( &str, "\nopendb "  );
	bu_vls_strcat( &str, title_file );
	bu_vls_strcat( &str, ";\ntree " );
	bu_vls_from_argv( &str,
			  nobjs <= 16 ? nobjs : 16,
			  (const char **)argv+bu_optind+1 );
	if ( nobjs > 16 )
	    bu_vls_strcat( &str, " ...");
	else
	    bu_vls_putc( &str, ';' );
	bu_log("%s\n", bu_vls_addr(&str) );
	bu_vls_free(&str);
    }

    /* Build directory of GED database */
    bu_vls_init( &times );
    rt_prep_timer();
    if ( (rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL ) {
	bu_log("rt:  rt_dirbuild(%s) failure\n", title_file);
	return 2;
    }
    ap.a_rt_i = rtip;
    (void)rt_get_timer( &times, NULL );
    if (rt_verbosity & VERBOSE_MODELTITLE)
	bu_log("db title:  %s\n", idbuf);
    if (rt_verbosity & VERBOSE_STATS)
	bu_log("DIRBUILD: %s\n", bu_vls_addr(&times) );
    bu_vls_free( &times );
    memory_summary();

    /* Copy values from command line options into rtip */
    rtip->rti_space_partition = space_partition;
    rtip->rti_nugrid_dimlimit = nugrid_dimlimit;
    rtip->rti_nu_gfactor = nu_gfactor;
    rtip->useair = use_air;
    rtip->rti_save_overlaps = save_overlaps;
    if ( rt_dist_tol > 0 )  {
	rtip->rti_tol.dist = rt_dist_tol;
	rtip->rti_tol.dist_sq = rt_dist_tol * rt_dist_tol;
    }
    if ( rt_perp_tol > 0 )  {
	rtip->rti_tol.perp = rt_perp_tol;
	rtip->rti_tol.para = 1 - rt_perp_tol;
    }
    if (rt_verbosity & VERBOSE_TOLERANCE)
	rt_pr_tol( &rtip->rti_tol );

    /* before view_init */
    if ( outputfile && strcmp( outputfile, "-") == 0 )
	outputfile = (char *)0;

    /*
     *  Initialize application.
     *  Note that width & height may not have been set yet,
     *  since they may change from frame to frame.
     */
    if ( view_init( &ap, title_file, title_obj, outputfile!=(char *)0, framebuffer!=(char *)0 ) != 0 )  {
	/* Framebuffer is desired */
	register int xx, yy;
	int	zoom;

	/* Ask for a fb big enough to hold the image, at least 512. */
	/* This is so MGED-invoked "postage stamps" get zoomed up big enough to see */
	xx = yy = 512;
	if ( width > xx || height > yy )  {
	    xx = width;
	    yy = height;
	}
	bu_semaphore_acquire( BU_SEM_SYSCALL );
	fbp = fb_open( framebuffer, xx, yy );
	bu_semaphore_release( BU_SEM_SYSCALL );
	if ( fbp == FBIO_NULL )  {
	    fprintf(stderr, "rt:  can't open frame buffer\n");
	    return 12;
	}

	bu_semaphore_acquire( BU_SEM_SYSCALL );
	/* If fb came out smaller than requested, do less work */
	if ( fb_getwidth(fbp) < width )  width = fb_getwidth(fbp);
	if ( fb_getheight(fbp) < height )  height = fb_getheight(fbp);

	/* If the fb is lots bigger (>= 2X), zoom up & center */
	if ( width > 0 && height > 0 )  {
	    zoom = fb_getwidth(fbp)/width;
	    if ( fb_getheight(fbp)/height < zoom )
		zoom = fb_getheight(fbp)/height;
	} else {
	    zoom = 1;
	}
	(void)fb_view( fbp, width/2, height/2,
		       zoom, zoom );
	bu_semaphore_release( BU_SEM_SYSCALL );
    }
    if ( (outputfile == (char *)0) && (fbp == FBIO_NULL) )  {
	/* If not going to framebuffer, or to a file, then use stdout */
	if ( outfp == NULL )  outfp = stdout;
	/* output_is_binary is changed by view_init, as appropriate */
	if ( output_is_binary && isatty(fileno(outfp)) )  {
	    fprintf(stderr, "rt:  attempting to send binary output to terminal, aborting\n");
	    return 14;
	}
    }

    /*
     *  Initialize all the per-CPU memory resources.
     *  The number of processors can change at runtime, init them all.
     */
    for ( i=0; i < MAX_PSW; i++ )  {
	rt_init_resource( &resource[i], i, rtip );
	bn_rand_init( resource[i].re_randptr, i );
    }
    memory_summary();

#ifdef SIGUSR1
    (void)signal( SIGUSR1, siginfo_handler );
#endif
#ifdef SIGINFO
    (void)signal( SIGINFO, siginfo_handler );
#endif

    if ( !matflag )  {
	int frame_retval;
	def_tree( rtip );		/* Load the default trees */
	do_ae( azimuth, elevation );
	frame_retval = do_frame( curframe );
	if (frame_retval != 0) {
	    /* Release the framebuffer, if any */
	    if ( fbp != FBIO_NULL ) {
		fb_close(fbp);
	    }

	    return 1;
	}
    } else if ( !isatty(fileno(stdin)) && old_way( stdin ) )  {
	; /* All is done */
    } else {
	register char	*buf;
	register int	ret;
	/*
	 * New way - command driven.
	 * Process sequence of input commands.
	 * All the work happens in the functions
	 * called by rt_do_cmd().
	 */
	while ( (buf = rt_read_cmd( stdin )) != (char *)0 )  {
	    if ( R_DEBUG&RDEBUG_PARSE )
		fprintf(stderr, "cmd: %s\n", buf );
	    ret = rt_do_cmd( rtip, buf, rt_cmdtab );
	    bu_free( buf, "rt_read_cmd command buffer" );
	    if ( ret < 0 )
		break;
	}
	if ( curframe < desiredframe )  {
	    fprintf(stderr,
		    "rt:  Desired frame %d not reached, last was %d\n",
		    desiredframe, curframe);
	}
    }

    /* Release the framebuffer, if any */
    if (fbp != FBIO_NULL) {
	fb_close(fbp);
    }

    return(0);
}
Ejemplo n.º 14
0
int main(int argc, char **argv)
{
    /*  START # 1  */
    struct application ap;	/*  Structure passed between functions.  */

    static struct rt_i *rtip;	/*  *rtip pointer to structure of  */
				/*  type rt_i  */
    char idbuf[132];	/*  first ID record info, used in  */
			/*  rt_dirbuild  */
    int index;		/*  index for rt_dirbuild & rt_gettree  */

    FILE *fp;		/*  used in opening file for second pass  */
    char spfile[16];	/*  second pass file name  */
    FILE *fp1=NULL;		/*  conductivity file  */
    char confile[16];	/*  conductivity file  */
    FILE *fp2;		/*  conductivity table file  */
    char tblfile[16];	/*  conductivity table file  */

    int i, j;		/*  integers used in loops  */
    int numreg;		/*  number of regions  */
    int nmged;		/*  number of regions in mged file  */
    double gridspace;	/*  spacing between fired rays  */
    int iwrite;		/*  0 => write to standard out, 1 => write  */
			/*  to file  */
    int typeout;		/*  Type of file to be written, 0 => PRISM file,  */
    /*  1 => generic file.  */
    FILE *fp6;		/*  Used in writing generic file.  */
    char genfile[16];	/*  Generic file name.  */
    FILE *fp3=NULL;		/*  used for writing output to file  */
    char filename[16];	/*  output file name  */

    FILE *fp5;		/*  material file  */
    char filemat[16];	/*  material file  */
    char line[150];	/*  used for reading a line from a file  */
    double k[41];	/*  thermal conductivity  */
    int itype;		/*  type of length measurement to use for  */
			/*  rk calculations  */
    double rki, rkj;	/*  used in finding rk  */
    double ki, kj;	/*  thermal conductivity of region  */
    double leni, lenj;	/*  lengths used in finding rk  */
    double areai;	/*  areas used in finding rk  */
    double a1;		/*  area used in writing conductivity table  */
    double l1, l2, l3, l4;	/*  lengths used in writing conductivity table  */
    FILE *fp4;		/*  error file  */
    char fileerr[16];	/*  error file  */

    double angle[3];	/*  Angles of rotation.  angle[0]-rotation about  */
			/*  x-axis, angle[1]-rotation about y-axis, &  */
			/*  angle[2]-rotation about z-axis.  */
    double strtpt[3];	/*  Starting point of fired ray.  */
    double strtdir[3];	/*  Starting direction of fired ray.  */
    double r[3], t[3];	/*  Used in computing rotations.  */
    double center[3];	/*  Center point of bounding rpp.  */
    double diagonal;	/*  Length of diagonal of bounding rpp.  */
    double xmin, xmax;	/*  Maximum & minimum x of grid.  */
    double ymin, ymax;	/*  Maximum & minimum y of grid.  */
    double zmin, zmax;	/*  Maximum & minimum z of grid.  */
    int nadjreg;		/*  Number of adjacent regions.  */
    int prmrel;		/*  PRISM release number, 2=>2.0, 3=>3.0.  */
    int ifire;		/*  Number of sets of rays to be fired, 0=>  */
			/*  fire from 3 orthogonal postions, 1=>fire  */
			/*  from 1 position.  */

    /*  Check to see if arguments implimented correctly.  */
    if (argv[1] == NULL || argv[2] == NULL)
    {
	(void)fprintf(stderr, "\nusage:  secpass file.g objects\n\n");
    }

    else
    {
    	/*  START # 2  */

	/*  Ask if output goes to standard out or to a file.  */
	(void)fprintf(stdout, "Write output to standard out (0) or a file(1) ");
	(void)fprintf(stdout, "not at all (2)?  ");
	(void)fflush(stdout);
	(void)scanf("%d", &iwrite);
	if ((iwrite != 0) && (iwrite != 1)) iwrite=2;
	if (iwrite == 1)
	{
	    (void)fprintf(stdout, "Enter name of output file (15 char max).  ");
	    (void)fflush(stdout);
	    (void)scanf("%15s", filename);
	    fp3 = fopen(filename, "wb");
	}

	/*  Which file that has second pass information in it?  */
	(void)fprintf(stdout, "Enter name of file that has second pass ");
	(void)fprintf(stdout, "information\nin it (15 char max).  ");
	(void)fflush(stdout);
	(void)scanf("%15s", spfile);

	/*  Ask for type of output file to be generated.  */
	(void)printf("Enter type of output file to be generated.\n");
	(void)printf("\t 0 - PRISM File\n");
	(void)printf("\t 1 - Generic File\n");
	(void)fflush(stdout);
	(void)scanf("%d", &typeout);

	/*  Read name of file to write conductivity information  */
	/*  to for use in PRISM.  */
	if (typeout == 0)
	{
	    (void)fprintf(stdout, "Enter name of file to be created for PRISM ");
	    (void)fprintf(stdout, "conductivity\ninformation (15 char max).  ");
	    (void)fflush(stdout);
	    (void)scanf("%15s", confile);

	    /*  Find which release of PRISM is being used.  The format  */
	    /*  for writing region numbers is I3 for PRISM 2.0 & I6 for  */
	    /*  PRISM 3.0.  */
	    prmrel = 2;
	    (void)printf("Which release of PRISM is being used, 2.0 (2) ");
	    (void)printf("or 3.0 (3)?  ");
	    (void)fflush(stdout);
	    (void)scanf("%d", &prmrel);
	    if (prmrel != 3) prmrel = 2;
	}

	/*  Read generic file name if necessary.  */
	if (typeout == 1)
	{
	    (void)printf("Enter name of generic file to be created (15 char ");
	    (void)printf("max).  ");
	    (void)fflush(stdout);
	    (void)scanf("%15s", genfile);
	}

	/*  Which calculated length should be used when writing to  */
	/*  this file:  1 -> average length, 2 -> rms length, 3 ->  */
	/*  minimum length, and 4 -> maximum length.  */
	(void)fprintf(stdout, "Which length calculation should be used when\n");
	(void)fprintf(stdout, "computing conduction\nbetween regions?\n");
	(void)fprintf(stdout, "\t1 - average length\n");
	(void)fprintf(stdout, "\t2 - rms length\n");
	(void)fprintf(stdout, "\t3 - minimum length\n");
	(void)fprintf(stdout, "\t4 - maximum length\n");
	(void)fflush(stdout);
	(void)scanf("%d", &itype);

	/*  Read name of file to write conductivity information to  */
	/*  in table format.  */
	(void)fprintf(stdout, "Enter name of file to be created for ");
	(void)fprintf(stdout, "conductivity\ntable (15 char max).  ");
	(void)fflush(stdout);
	(void)scanf("%15s", tblfile);

	/*  Read name of material file that contains thermal  */
	/*  conductivity information.  */
	(void)fprintf(stdout, "Enter name of material file (15 char max).  ");
	(void)fflush(stdout);
	(void)scanf("%15s", filemat);

	/*  Read name of error file.  */
	(void)fprintf(stdout, "Enter name of error file to be created ");
	(void)fprintf(stdout, "(15 char max).  ");
	(void)fflush(stdout);
	(void)scanf("%15s", fileerr);

	/*  Choose whether 3 orthogonal sets of rays are to be fired  */
	/*  or 1 set of rays is to be fired.  */
	(void)printf("Should there be 3 sets of orhogonal rays fired ");
	(void)printf("(0) or 1 set (1)?\n\t");
	(void)fflush(stdout);
	(void)scanf("%d", &ifire);
	if (ifire != 0) ifire = 1;
	if (ifire == 0)
	{
	    (void)printf("3 sets of orthogonal rays will be fired.\n");
	}
	if (ifire == 1)
	{
	    (void)printf("1 set of rays will be fired.\n");
	}
	(void)fflush(stdout);

	/*  Write out file information.  */
	if (iwrite ==1)
	{
	    (void)fprintf(fp3, "\nsecond pass file:  %s\n", spfile);
	    (void)fprintf(fp3, "material file:  %s\n", filemat);
	    if (typeout == 0)
	    {
		(void)fprintf(fp3, "conductivity file for use ");
		(void)fprintf(fp3, "with PRISM:  %s\n", confile);
		(void)fprintf(fp3, "  (format is PRISM %d.0)\n", prmrel);
	    }
	    if (typeout == 1) (void)fprintf(fp3, "generic file:  %s\n", genfile);
	    (void)fflush(fp3);
	    if (itype == 1) (void)fprintf(fp3, "\taverage length being used\n");
	    if (itype == 2) (void)fprintf(fp3, "\trms length being used\n");
	    if (itype == 3) (void)fprintf(fp3, "\tminimum length being used\n");
	    if (itype == 4) (void)fprintf(fp3, "\tmaximum length being used\n");
	    (void)fprintf(fp3, "conductivity table file:  %s\n", tblfile);
	    (void)fprintf(fp3, "error file:  %s\n\n", fileerr);
	    (void)fflush(fp3);
	}

	/*  Read thermal conductivity file.  */
	fp5 = fopen(filemat, "rb");
	for (i=0; i<41; i++)
	{
	    (void)bu_fgets(line, 151, fp5);
	    (void)sscanf(line, "%*d%*f%*f%*f%*f%lf", &k[i]);
	}

	/*  Print out the thermal conductivity.  */
	/*
	 *	for (i=0; i<41; i++)
	 *	{
	 *	   (void)fprintf(stdout, "  thermal conductivity %d = %f\n", i, k[i]);
	 *	   (void)fflush(stdout);
	 *	}
	 */

	/*  Build the directory.  */
	index = 1;	/*  Set index for rt_dirbuild.  */
	rtip=rt_dirbuild(argv[index], idbuf, sizeof(idbuf));
	(void)fprintf(stdout, "Database title:  %s\n", idbuf);
	(void)fflush(stdout);

	/*  Set useair to 1, to show hits of air.  */
	rtip->useair = 1;

	/*  Load desired objects.  */
	index = 2;	/*  Set index for rt_gettree.  */
	while (argv[index] != NULL)
	{
	    rt_gettree(rtip, argv[index]);
	    index += 1;
	}

	/*  Find total number of regions in mged file.  */
	nmged = (int)rtip->nregions;

	(void)fprintf(stdout, "Number of regions in mged file:  %d\n", nmged);
	(void)fflush(stdout);

	if (iwrite == 1)
	{
	    (void)fprintf(fp3, "Number of regions in mged file:  %d\n", nmged);
	    (void)fflush(fp3);
	}

	/*  Number of regions known, everything can be malloced.  */
	(void)fprintf(stdout, "Mallocing arrays.\n");
	(void)fflush(stdout);

	cond = (struct table *)bu_malloc( nmged * sizeof(struct table), "cond" );
	(void)fprintf(stdout, "cond malloced\n");
	(void)fflush(stdout);
	for (i=0; i<nmged; i++)
	{
	    cond[i].shrarea = (double *)bu_malloc( nmged * sizeof(double), "cond[i].shrarea" );
	    cond[i].avglen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].avglen" );
	    cond[i].rmslen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rmslen" );
	    cond[i].minlen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].minlen" );
	    cond[i].maxlen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].maxlen" );
	    cond[i].numcal = (double *)bu_malloc( nmged * sizeof(double), "cond[i].numcal" );
	    cond[i].rkavg = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkavg" );
	    cond[i].rkrms = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkrms" );
	    cond[i].rkmin = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkmin" );
	    cond[i].rkmax = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkmax" );
	}
	(void)fprintf(stdout, "loop malloced\n");
	(void)fflush(stdout);

	/*  All variables 'dimensioned', now zero all variables.  */
	for (i=0; i<nmged; i++)
	{
	    cond[i].centroid[0] = (double)0.;
	    cond[i].centroid[1] = (double)0.;
	    cond[i].centroid[2] = (double)0.;
	    cond[i].mat = (int)0;
	    for (j=0; j<nmged; j++)
	    {
		cond[i].shrarea[j] = (double)0.;
		cond[i].avglen[j] = (double)0.;
		cond[i].rmslen[j] = (double)0.;
		cond[i].minlen[j] = (double)0.;
		cond[i].maxlen[j] = (double)0.;
		cond[i].numcal[j] = (double)0.;
		cond[i].rkavg[j] = (double)0.;
		cond[i].rkrms[j] = (double)0.;
		cond[i].rkmin[j] = (double)0.;
		cond[i].rkmax[j] = (double)0.;
	    }
	}
	(void)fprintf(stdout, "All variables zeroed.\n");
	(void)fflush(stdout);

	/*  Now open file with second pass information in it.  */
	fp = fopen(spfile, "rb");
	(void)fprintf(stdout, "second pass file opened\n");
	(void)fflush(stdout);

	/*  Read number of regions in file.  */
	(void)fscanf(fp, "%d\n", &numreg);
	(void)fprintf(stdout, "The number of regions read was %d\n", numreg);
	(void)fflush(stdout);

	if (iwrite == 1)
	{
	    (void)fprintf(fp3, "number of regions read from second ");
	    (void)fprintf(fp3, "pass file:  %d\n", numreg);
	    (void)fflush(fp3);
	}

	/*  Read all information in file.  */
	for (i=0; i<numreg; i++)
	{
	    (void)fscanf(fp, "%*d%le%le%le%d\n", &cond[i].centroid[0],
			 &cond[i].centroid[1],
			 &cond[i].centroid[2], &cond[i].mat);
	    /*
	     *	   (void)fprintf(stdout, "reg=%8d, centroid:  %10.0f, %10.0f, %10.0f\n",
	     *		i, cond[i].centroid[0], cond[i].centroid[1], cond[i].centroid[2]);
	     *	   (void)fflush(stdout);
	     */

	    for (j=0; j<numreg; j++)
	    {
		(void)fscanf(fp, "%*d%le\n", &cond[i].shrarea[j]);
		/*
		 *		(void)fprintf(stdout, "\treg=%8d, area=%10.0f\n",
		 *		   j, cond[i].shrarea[j]);
		 *		(void)fflush(stdout);
		 */
	    }
	}

	(void)fclose(fp);

	/*  Check that the number of regions in the mged file  */
	/*  and the second pass file are equal.  */
	if (nmged != numreg)
	{
	    (void)fprintf(stdout, "ERROR -- The number of regions in the mged\n");
	    (void)fprintf(stdout, "file (%d) does not equal the number of\n",
			  nmged);
	    (void)fprintf(stdout, "regions in the second pass file (%d).\n",
			  numreg);
	    (void)fprintf(stdout, "Watch for unexplained errors.\n");
	    (void)fflush(stdout);

	    if (iwrite == 1)
	    {
		(void)fprintf(fp3, "ERROR -- The number of regions in the mged\n");
		(void)fprintf(fp3, "file (%d) does not equal the number of\n",
			      nmged);
		(void)fprintf(fp3, "regions in the second pass file (%d).\n",
			      numreg);
		(void)fprintf(fp3, "Watch for unexplained errors.\n");
		(void)fflush(fp3);
	    }
	}

	/*  Get database ready by starting preparation.  */
	rt_prep(rtip);

	/*  Find center of bounding rpp.  */
	center[X] = rtip->mdl_min[X] + (rtip->mdl_max[X] -
					rtip->mdl_min[X]) / 2.;
	center[Y] = rtip->mdl_min[Y] + (rtip->mdl_max[Y] -
					rtip->mdl_min[Y]) / 2.;
	center[Z] = rtip->mdl_min[Z] + (rtip->mdl_max[Z] -
					rtip->mdl_min[Z]) / 2.;

	/*  Find length of diagonal.  */
	diagonal = (rtip->mdl_max[X] - rtip->mdl_min[X])
	    * (rtip->mdl_max[X] - rtip->mdl_min[X])
	    + (rtip->mdl_max[Y] - rtip->mdl_min[Y])
	    * (rtip->mdl_max[Y] - rtip->mdl_min[Y])
	    + (rtip->mdl_max[Z] - rtip->mdl_min[Z])
	    * (rtip->mdl_max[Z] - rtip->mdl_min[Z]);
	diagonal = sqrt(diagonal) / 2. + .5;

	/*  Find minimum & maximum of grid.  */
	xmin = center[X] - diagonal;
	xmax = center[X] + diagonal;
	ymin = center[Y] - diagonal;
	ymax = center[Y] + diagonal;
	zmin = center[Z] - diagonal;
	zmax = center[Z] + diagonal;

	/*  Print center of bounding rpp, diagonal, & maximum  */
	/*  & minimum of grid.  */
	(void)fprintf(stdout, "Center of bounding rpp ( %f, %f, %f )\n",
		      center[X], center[Y], center[Z]);
	(void)fprintf(stdout, "Length of diagonal of bounding rpp:  %f\n",
		      diagonal);
	(void)fprintf(stdout, "Minimums & maximums of grid:\n");
	(void)fprintf(stdout, "  %f - %f\n", xmin, xmax);
	(void)fprintf(stdout, "  %f - %f\n", ymin, ymax);
	(void)fprintf(stdout, "  %f - %f\n\n", zmin, zmax);
	(void)fflush(stdout);

	/*  Write model minimum & maximum.  */
	(void)fprintf(stdout, "Model minimum & maximum.\n");
	(void)fprintf(stdout, "\tX:  %f to %f\n\tY:  %f to %f\n\tZ:  %f to %f\n\n",
		      rtip->mdl_min[X], rtip->mdl_max[X],
		      rtip->mdl_min[Y], rtip->mdl_max[Y],
		      rtip->mdl_min[Z], rtip->mdl_max[Z]);
	(void)fflush(stdout);

	if (iwrite == 1)
	{
	    (void)fprintf(fp3, "Model minimum & maximum.\n");
	    (void)fprintf(fp3, "\tX:  %f to %f\n\tY:  %f kto %f\n",
			  rtip->mdl_min[X], rtip->mdl_max[X],
			  rtip->mdl_min[Y], rtip->mdl_max[Y]);
	    (void)fprintf(fp3, "\tZ:  %f to %f\n\n",
			  rtip->mdl_min[Z], rtip->mdl_max[Z]);
	    (void)fflush(fp3);
	}

	/*  User enters grid spacing.  All units are in mm.  */
	(void)fprintf(stdout, "Enter spacing (mm) between fired rays.  ");
	(void)fflush(stdout);
	(void)scanf("%lf", &gridspace);

	(void)fprintf(stdout, "\ngrid spacing:  %f\n", gridspace);
	(void)fflush(stdout);

	if (iwrite == 1)
	{
	    (void)fprintf(fp3, "gridspacing:  %f\n\n", gridspace);
	    (void)fflush(fp3);
	}

	/*  Set up parameters for rt_shootray.  */
	RT_APPLICATION_INIT(&ap);
	ap.a_hit = hit;		/*  User supplied hit function.  */
	ap.a_miss = miss;	/*  User supplied miss function.  */
	ap.a_overlap = ovrlap;	/*  user supplied overlap function.  */
	ap.a_rt_i = rtip;	/*  Pointer from rt_dirbuild.  */
	ap.a_onehit = 0;	/*  Hit flag (returns all hits).  */
	ap.a_level = 0;		/*  Recursion level for diagnostics.  */
	ap.a_resource = 0;	/*  Address of resource structure (NULL).  */

	/*  Put angles for rotation into radians.  */
	angle[X] = radians((double)GAMMA);
	angle[Y] = radians((double)BETA);
	angle[Z] = radians((double)ALPHA);

	/*  Set up and shoot down the 1st axis, positive to negative  */
	/*  (x-axis).  */

	(void)fprintf(stdout, "\nShooting down 1st axis.\n");
	(void)fflush(stdout);

	strtpt[X] = xmax;
	strtpt[Y] = ymin + gridspace / 2.;
	strtpt[Z] = zmin + gridspace / 2.;
	strtdir[X] = (-1);
	strtdir[Y] = 0;
	strtdir[Z] = 0;

	/*  Rotate starting point.  (new pt = C + R[P -C])  */
	t[X] = strtpt[X] - center[X];
	t[Y] = strtpt[Y] - center[Y];
	t[Z] = strtpt[Z] - center[Z];

	(void)rotate(t, angle, r);

	ap.a_ray.r_pt[X] = center[X] + r[X];
	ap.a_ray.r_pt[Y] = center[Y] + r[Y];
	ap.a_ray.r_pt[Z] = center[Z] + r[Z];

	/*  Rotate firing direction.  (new dir = R[D])  */
	(void)rotate(strtdir, angle, r);
	ap.a_ray.r_dir[X] = r[X];
	ap.a_ray.r_dir[Y] = r[Y];
	ap.a_ray.r_dir[Z] = r[Z];

	while (strtpt[Z] <= zmax)
	{
	    /*  START # 3  */

	    iprev = (-1);	/*  No previous shots.  */

	    /*  Call rt_shootray.  */
	    (void)rt_shootray ( &ap );

	    strtpt[Y] += gridspace;
	    if (strtpt[Y] > ymax)
	    {
		strtpt[Y] = ymin + gridspace / 2.;
		strtpt[Z] += gridspace;
	    }

	    t[X] = strtpt[X] - center[X];
	    t[Y] = strtpt[Y] - center[Y];
	    t[Z] = strtpt[Z] - center[Z];

	    (void)rotate(t, angle, r);

	    ap.a_ray.r_pt[X] = center[X] + r[X];
	    ap.a_ray.r_pt[Y] = center[Y] + r[Y];
	    ap.a_ray.r_pt[Z] = center[Z] + r[Z];

	}	/*  END # 3  */

	/*  Shoot down 2nd & 3rd axes if necessary.  */
	if (ifire == 0)
	{
	    /*  START # 1000  */
	    /*  Set up & shoot down the 2nd axis (y-axis).  */
	    (void)printf("\nShooting down the 2nd axis.\n");
	    (void)fflush(stdout);

	    strtpt[X] = xmin + gridspace / 2.;
	    strtpt[Y] = ymax;
	    strtpt[Z] = zmin + gridspace / 2.;
	    strtdir[X] = 0.;
	    strtdir[Y] = (-1.);
	    strtdir[X] = 0.;

	    /*  Rotate starting point (new pt = C + R[P - C]).  */
	    t[X] = strtpt[X] - center [X];
	    t[Y] = strtpt[Y] - center [Y];
	    t[Z] = strtpt[Z] - center [Z];

	    (void)rotate(t, angle, r);

	    ap.a_ray.r_pt[X] = center[X] + r[X];
	    ap.a_ray.r_pt[Y] = center[Y] + r[Y];
	    ap.a_ray.r_pt[Z] = center[Z] + r[Z];

	    /*  Rotate firing direction (new dir = R[D])  */
	    (void)rotate(strtdir, angle, r);

	    ap.a_ray.r_dir[X] = r[X];
	    ap.a_ray.r_dir[Y] = r[Y];
	    ap.a_ray.r_dir[Z] = r[Z];

	    while (strtpt[Z] <= zmax)
	    {
		/*  START # 1010  */
		iprev = (-1);		/*  No previous shots.  */

		/*  Call rt_shootray.  */
		(void)rt_shootray(&ap);

		strtpt[X] += gridspace;
		if (strtpt[X] > xmax)
		{
		    strtpt[X] = xmin + gridspace / 2.;
		    strtpt[Z] += gridspace;
		}

		t[X] = strtpt[X] - center[X];
		t[Y] = strtpt[Y] - center[Y];
		t[Z] = strtpt[Z] - center[Z];

		(void)rotate(t, angle, r);

		ap.a_ray.r_pt[X] = center[X] + r[X];
		ap.a_ray.r_pt[Y] = center[Y] + r[Y];
		ap.a_ray.r_pt[Z] = center[Z] + r[Z];
	    }						/*  END # 1010  */

	    /*  Set up & shoot down the 3rd axis (z-axis).  */
	    (void)printf("\nShooting down the 3rd axis.\n");
	    (void)fflush(stdout);

	    strtpt[X] = xmin + gridspace / 2.;
	    strtpt[Y] = ymin + gridspace / 2.;
	    strtpt[Z] = zmax;
	    strtdir[X] = 0.;
	    strtdir[Y] = 0.;
	    strtdir[Z] = (-1.);

	    /*  Rotate starting points (new pt = C + R[P - C]).  */
	    t[X] = strtpt[X] - center[X];
	    t[Y] = strtpt[Y] - center[Y];
	    t[Z] = strtpt[Z] - center[Z];

	    (void)rotate(t, angle, r);

	    ap.a_ray.r_pt[X] = r[X];
	    ap.a_ray.r_pt[Y] = r[Y];
	    ap.a_ray.r_pt[Z] = r[Z];

	    while (strtpt[Y] <= ymax)
	    {
		/*  START # 1020  */
		iprev = (-1);		/*  No previous shots.  */

		/*  Call rt_shootray.  */
		(void)rt_shootray(&ap);

		strtpt[X] += gridspace;
		if (strtpt[X] > xmax)
		{
		    strtpt[X] = xmin + gridspace / 2.;
		    strtpt[Y] += gridspace;
		}

		t[X] = strtpt[X] - center[X];
		t[Y] = strtpt[Y] - center[Y];
		t[Z] = strtpt[Z] - center[Z];

		(void)rotate(t, angle, r);

		ap.a_ray.r_pt[X] = center[X] + r[X];
		ap.a_ray.r_pt[Y] = center[Y] + r[Y];
		ap.a_ray.r_pt[Z] = center[Z] + r[Z];
	    }						/*  END # 1020  */
	}						/*  END # 1000  */

	/*  Calculate final length between centroid & shared surface area.  */
	if (iwrite == 0)
	{
	    (void)fprintf(stdout, "\n\nFinal numbers.\n");
	    (void)fflush(stdout);
	}

	for (i=0; i<numreg; i++)
	{

	    if (iwrite == 0)
	    {
		(void)fprintf(stdout, "reg#=%d, matid=%d\n", (i+1), cond[i].mat);
		(void)fflush(stdout);
	    }

	    if (iwrite == 1)
	    {
		(void)fprintf(fp3, "reg#=%d, matid=%d\n", (i+1), cond[i].mat);
		(void)fflush(fp3);
	    }

	    for (j=0; j<numreg; j++)
	    {
		if (cond[i].numcal[j] > ZEROTOL)
		{
		    cond[i].avglen[j] /= cond[i].numcal[j];
		    cond[i].rmslen[j] /= cond[i].numcal[j];
		    cond[i].rmslen[j] = sqrt(cond[i].rmslen[j]);

		    if (iwrite == 0)
		    {
			(void)fprintf(stdout, "\tadjreg=%d, numcal=%f, shrarea=%f, ",
				      (j+1), cond[i].numcal[j], cond[i].shrarea[j]);
			(void)fprintf(stdout, "avglen=%f\n", cond[i].avglen[j]);
			(void)fprintf(stdout, "\t\trmslen=%f, ", cond[i].rmslen[j]);
			(void)fprintf(stdout, "minlen=%f, maxlen=%f\n",
				      cond[i].minlen[j], cond[i].maxlen[j]);
			(void)fflush(stdout);
		    }

		    if (iwrite == 1)
		    {
			(void)fprintf(fp3, "\tadjreg=%d, numcal=%f, shrarea=%f, ",
				      (j+1), cond[i].numcal[j], cond[i].shrarea[j]);
			(void)fprintf(fp3, "avglen=%f\n", cond[i].avglen[j]);
			(void)fprintf(fp3, "\t\trmslen=%f, ", cond[i].rmslen[j]);
			(void)fprintf(fp3, "minlen=%f, maxlen=%f\n",
				      cond[i].minlen[j], cond[i].maxlen[j]);
			(void)fflush(fp3);
		    }

		}
		else
		{
		    cond[i].avglen[j] = 0.;
		    cond[i].rmslen[j] = 0.;
		}
	    }
	}

	if (iwrite == 1)
	{
	    /*  Print summary of all files used.  */
	    (void)fprintf(fp3, "\n\nSUMMARY OF FILES USED & CREATED\n");
	    (void)fprintf(fp3, "\t.g file used:  %s\n", argv[1]);
	    (void)fprintf(fp3, "\tregions used:\n");
	    (void)fflush(fp3);
	    i=2;
	    while (argv[i] != NULL)
	    {
		(void)fprintf(fp3, "\t\t%s\n", argv[i]);
		(void)fflush(fp3);
		i++;
	    }
	    (void)fprintf(fp3, "\tfile containing second pass information:  %s\n",
			  spfile);
	    (void)fprintf(fp3, "\tmaterial file used:  %s\n", filemat);
	    (void)fprintf(fp3, "\toutput file created:  %s\n", filename);
	    if (typeout == 0)
	    {
		(void)fprintf(fp3, "\tconductivity file created:  %s\n", confile);
		(void)fprintf(fp3, "\t  (format is PRISM %d.0)\n", prmrel);
	    }
	    if (typeout == 1) (void)fprintf(fp3, "\tgeneric file created:  %s\n"
					    , genfile);
	    (void)fprintf(fp3, "\tconductivity table file created:  %s\n",
			  tblfile);
	    (void)fprintf(fp3, "\terror file created:  %s\n\n\n", fileerr);
	    (void)fflush(fp3);

	    (void)fclose(fp3);
	}

	/*------------------------------------------------------------------*/

	/*  Open conductivity file to be used with PRISM if needed.  */
	if (typeout == 0)
	{
	    fp1=fopen(confile, "wb");
	    (void)fprintf(fp1, "Conductivity file for use with PRISM.\n");
	    (void)fflush(fp1);
	}

	/*  Make calculations & write to conductivity file.  */
	for (i=0; i<numreg; i++)
	{
	    /*  START # 6  */

	    /*  Make conductivity file triangular.  This program still  */
	    /*  computes the ENTIRE matrix.  */

	    for (j=(i+1); j<numreg; j++)
	    {
	    	/*  START # 7  */

		if ( (cond[i].avglen[j] != 0) )
		{
		    /*  START # 8  */
		    /*  Find correct thermal conductivity.  */
		    /*  If ki or kj = 0 => rk = 0.  */
		    ki = k[cond[i].mat];
		    kj = k[cond[j].mat];

		    /*  All calculations will be in meters &  */
		    /*  square meters.  */

		    areai = cond[i].shrarea[j] * 1.e-6;

		    /*  average length  */
		    leni = cond[i].avglen[j] * 1.e-3;
		    lenj = cond[j].avglen[i] * 1.e-3;
		    if (((-ZEROTOL < ki) && (ki < ZEROTOL)) ||
			((-ZEROTOL < kj) && (kj < ZEROTOL)))
			cond[i].rkavg[j] = 0.;
		    else
		    {
			rki = leni / (ki * areai);
			rkj = lenj / (kj * areai);
			cond[i].rkavg[j] = 1. / (rki + rkj);
		    }

		    /*  rms length  */
		    leni = cond[i].rmslen[j] * 1.e-3;
		    lenj = cond[j].rmslen[i] * 1.e-3;
		    if (((-ZEROTOL < ki) && (ki < ZEROTOL)) ||
			((-ZEROTOL < kj) && (kj < ZEROTOL)))
			cond[i].rkrms[j] = 0.;
		    else
		    {
			rki = leni / (ki * areai);
			rkj = lenj / (kj * areai);
			cond[i].rkrms[j] = 1. / (rki + rkj);
		    }

		    /*  minimum length  */
		    leni = cond[i].minlen[j] * 1.e-3;
		    lenj = cond[j].minlen[i] * 1.e-3;
		    if (((-ZEROTOL < ki) && (ki < ZEROTOL)) ||
			((-ZEROTOL < kj) && (kj < ZEROTOL)))
			cond[i].rkmin[j] = 0.;
		    else
		    {
			rki = leni / (ki * areai);
			rkj = lenj / (kj * areai);
			cond[i].rkmin[j] = 1. / (rki + rkj);
		    }

		    /*  maximum length  */
		    leni = cond[i].maxlen[j] * 1.e-3;
		    lenj = cond[j].maxlen[i] * 1.e-3;
		    if (((-ZEROTOL < ki) && (ki < ZEROTOL)) ||
			((-ZEROTOL < kj) && (kj < ZEROTOL)))
			cond[i].rkmax[j] = 0.;
		    else
		    {
			rki = leni / (ki * areai);
			rkj = lenj / (kj * areai);
			cond[i].rkmax[j] = 1. / (rki + rkj);
		    }

		    /*  Print if had adjacent regions, conductivity  */
		    /*  may be zero.  */

		    /*  Print only if PRISM file is to be created.  */
		    if (typeout == 0) {
			/*  START # 8A  */
			if ( (itype == 1) && (cond[i].shrarea[j] > ZEROTOL) )
			{
			    if (prmrel == 2)
				(void)fprintf(fp1, "%3d %3d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkavg[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			    if (prmrel == 3)
				(void)fprintf(fp1, "%6d %6d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkavg[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			}

			if ( (itype == 2) && (cond[i].shrarea[j] > ZEROTOL) )
			{
			    if (prmrel == 2)
				(void)fprintf(fp1, "%3d %3d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkrms[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			    if (prmrel == 3)
				(void)fprintf(fp1, "%6d %6d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkrms[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			}

			if ( (itype == 3) && (cond[i].shrarea[j] > ZEROTOL) )
			{
			    if (prmrel == 2)
				(void)fprintf(fp1, "%3d %3d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkmin[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			    if (prmrel == 3)
				(void)fprintf(fp1, "%6d %6d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkmin[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			}

			if ( (itype == 4) && (cond[i].shrarea[j] > ZEROTOL) )
			{
			    if (prmrel == 2)
				(void)fprintf(fp1, "%3d %3d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkmax[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			    if (prmrel == 3)
				(void)fprintf(fp1, "%6d %6d %7.3f %.3e\n",
					      (j+1), (i+1), cond[i].rkmax[j],
					      (cond[i].shrarea[j] * 1.0e-6));
			}

			(void)fflush(fp1);
		    }				/*  END of # 8A  */
		}	/*  END # 8  */
	    }	/*  END # 7  */
	}	/*  END # 6  */

	if (typeout == 0) (void)fclose(fp1);

	/*------------------------------------------------------------------*/

	/*  Open and write to generic file if necessary. */
	/*  The format follows.  */
	/*  4  region number  number of adjacent regions  */
	/*     adjacent region  shared area  conduction distance  */

	if (typeout == 1)
	{
	    /*  Open file.  */
	    fp6 = fopen(genfile, "wb");
	    (void)printf("Opened generic file.\n");
	    (void)fflush(stdout);

	    for (i=0; i<numreg; i++)
	    {
		/*  Find number of adjacent regions.  */
		/*
		 *		(void)printf("Ready to find number of adjacent areas.\n");
		 *		(void)fflush(stdout);
		 */
		nadjreg = 0;
		/*
		 *		(void)printf("nadjreg = %d\n", nadjreg);
		 *		(void)fflush(stdout);
		 */
		for (j=0; j<numreg; j++)
		{
		    /*
		     *		   (void)printf("%d, %d, %f\n", i, j, cond[i].shrarea[j]);
		     *		   (void)fflush(stdout);
		     */
		    if (cond[i].shrarea[j] > ZEROTOL) nadjreg += 1;
		}
		/*
		 *		(void)printf("Found number of adjacent areas.\n");
		 *		(void)fflush(stdout);
		 */

		(void)fprintf(fp6, "4  %5d  %5d\n", (i+1), nadjreg);
		(void)fflush(fp6);

		for (j=0; j<numreg; j++)
		{
		    if (cond[i].shrarea[j] > ZEROTOL)
		    {
			(void)fprintf(fp6, "   %5d  %.3e  ", (j+1),
				      (cond[i].shrarea[j] * 1.e-6));
			if (itype == 1) (void)fprintf(fp6, "%.3e\n",
						      (cond[i].avglen[j] * 1.e-3));
			if (itype == 2) (void)fprintf(fp6, "%.3e\n",
						      (cond[i].rmslen[j] * 1.e-3));
			if (itype == 3) (void)fprintf(fp6, "%.3e\n",
						      (cond[i].minlen[j] * 1.e-3));
			if (itype == 4) (void)fprintf(fp6, "%.3e\n",
						      (cond[i].maxlen[j] * 1.e-3));
		    }
		    (void)fflush(fp6);
		}
	    }
	    (void)fclose(fp6);
	}

	/*------------------------------------------------------------------*/

	/*  Open conductivity table file and write information to  */
	/*  it.  All units will be in meters or square meters.  */
	fp2=fopen(tblfile, "wb");
	(void)fprintf(fp2, "Conductivity table.  Units are in meters or ");
	(void)fprintf(fp2, "square meters.\n");

	(void)fprintf(fp2, " reg, mat, adj,   shrarea,");
	(void)fprintf(fp2, "    avglen,     rkavg,");
	(void)fprintf(fp2, "    rmslen,     rkrms,");
	(void)fprintf(fp2, "    minlen,     rkmin,");
	(void)fprintf(fp2, "    maxlen,     rkmax\n");

	(void)fflush(fp2);

	for (i=0; i<numreg; i++)
	{
	    /*  START # 9  */
	    for (j=0; j<numreg; j++)
	    {
	    	/*  START # 10  */
		if (cond[i].shrarea[j] != 0)
		{
		    /*  START # 11  */
		    a1 = cond[i].shrarea[j] * 1.e-6;
		    l1 = cond[i].avglen[j] * 1.e-3;
		    l2 = cond[i].rmslen[j] * 1.e-3;
		    l3 = cond[i].minlen[j] * 1.e-3;
		    l4 = cond[i].maxlen[j] * 1.e-3;

		    (void)fprintf(fp2, "%4d,%4d,%4d, %.3e,",
				  (i+1), cond[i].mat, (j+1), a1);
		    if (j > i)
		    {
			(void)fprintf(fp2, " %.3e, %.3e,", l1, cond[i].rkavg[j]);
			(void)fprintf(fp2, " %.3e, %.3e,", l2, cond[i].rkrms[j]);
			(void)fprintf(fp2, " %.3e, %.3e,", l3, cond[i].rkmin[j]);
			(void)fprintf(fp2, " %.3e, %.3e\n", l4, cond[i].rkmax[j]);
		    }
		    else
		    {
			(void)fprintf(fp2, " %.3e, %.3e,", l1, cond[j].rkavg[i]);
			(void)fprintf(fp2, " %.3e, %.3e,", l2, cond[j].rkrms[i]);
			(void)fprintf(fp2, " %.3e, %.3e,", l3, cond[j].rkmin[i]);
			(void)fprintf(fp2, " %.3e, %.3e\n", l4, cond[j].rkmax[i]);
		    }

		    (void)fflush(fp2);
		}	/*  END # 11  */
	    }	/*  END # 10  */
	}	/*  END # 9  */

	(void)fclose(fp2);

	/*------------------------------------------------------------------*/

	/*  Print summary of all files used.  */
	(void)fprintf(stdout, "\n\nSUMMARY OF FILES USED & CREATED\n");
	(void)fprintf(stdout, "\t.g file used:  %s\n", argv[1]);
	(void)fprintf(stdout, "\tregions used:\n");
	(void)fflush(stdout);
	i=2;
	while (argv[i] != NULL)
	{
	    (void)fprintf(stdout, "\t\t%s\n", argv[i]);
	    (void)fflush(stdout);
	    i++;
	}
	(void)fprintf(stdout, "\tfile containing second pass information:  %s\n",
		      spfile);
	(void)fprintf(stdout, "\tmaterial file used:  %s\n", filemat);
	if (iwrite == 1)
	{
	    (void)fprintf(stdout, "\toutput file created:  %s\n", filename);
	}
	if (typeout == 0)
	{
	    (void)fprintf(stdout, "\tconductivity file created:  %s\n", confile);
	    (void)fprintf(stdout, "\t  (format is PRISM %d.0)\n", prmrel);
	}
	if (typeout == 1) (void)printf("\tgeneric file created:  %s\n", genfile);
	(void)fprintf(stdout, "\tconductivity table file created:  %s\n", tblfile);
	(void)fprintf(stdout, "\terror file created:  %s\n\n\n", fileerr);
	(void)fflush(stdout);

	/*------------------------------------------------------------------*/

	/*  Open error file.  */
	fp4 = fopen(fileerr, "wb");

	/*  Write errors to error file.  */
	(void)fprintf(fp4, "\nERRORS from secpass\n\n");
	/*  Write type of file created to error file.  */
	if (typeout == 0)
	{
	    (void)fprintf(fp4, "PRISM %d.0 conductivity file, %s, created.\n\n",
			  prmrel, confile);
	}
	if (typeout == 1) (void)fprintf(fp4, "Generic file, %s, created.\n\n",
					genfile);
	(void)fflush(fp4);
	for (i=0; i<numreg; i++)
	{
	    for (j=0; j<numreg;  j++)
	    {
		if ( (cond[i].numcal[j] > ZEROTOL) &&
		     ( cond[i].numcal[j] < MINCAL ) )
		{
		    (void)fprintf(fp4, "region %d, adjacent region %d:\n",
				  (i+1), (j+1));
		    (void)fprintf(fp4, "\tnumber of length calculations ");
		    (void)fprintf(fp4, "below minimum of %d\n", MINCAL);
		    (void)fflush(fp4);
		}
	    }
	}
	(void)fclose(fp4);

	/*------------------------------------------------------------------*/

	/*  Everything completed, free memory.  */
	(void)fprintf(stdout, "Freeing memory.\n");
	(void)fflush(stdout);
	for (i=0; i<nmged; i++)
	{
	    bu_free(cond[i].shrarea, "cond[i].shrarea");
	    bu_free(cond[i].avglen, "cond[i].avglen");
	    bu_free(cond[i].rmslen, "cond[i].rmslen");
	    bu_free(cond[i].minlen, "cond[i].minlen");
	    bu_free(cond[i].maxlen, "cond[i].maxlen");
	    bu_free(cond[i].numcal, "cond[i].numcal");
	    bu_free(cond[i].rkavg, "cond[i].rkavg");
	    bu_free(cond[i].rkrms, "cond[i].rkrms");
	    bu_free(cond[i].rkmin, "cond[i].rkmin");
	    bu_free(cond[i].rkmax, "cond[i].rkmax");
	}
	bu_free(cond, "cond");

    }	/*  END # 2  */
    return(0);
}	/*  END # 1  */
Ejemplo n.º 15
0
/**
 * absurdly inefficient way to perform sub-pixel anti-aliasing.  we
 * shoot additional rays to estimate the intensity contribution of
 * this edge cell.
 */
static void
get_intensity(double *intensity, struct application *ap, const struct cell *UNUSED(here), const struct cell *left, const struct cell *below, const struct cell *right, const struct cell *above)
{
    vect_t dy, dx, dy3, dx3;
    struct application aaap;
    struct cell grid[4][4];

    /* Grid layout:
     *
     *    left      right
     * _____________________
     * |0, 0 | AL | AR | 0, 3|  above
     * |____|____|____|____|
     * | TL | UL | UR | TR |  top/upper
     * |____|____|____|____|
     * | BL | LL | LR | BR |  bottom/lower
     * |____|____|____|____|
     * |3, 0 | DL | DR | 3, 3|  debajo
     * |____|____|____|____|
     */

    struct cell *AL = &grid[0][1];
    struct cell *AR = &grid[0][2];
    struct cell *TL = &grid[1][0];
    struct cell *UL = &grid[1][1];
    struct cell *UR = &grid[1][2];
    struct cell *TR = &grid[1][3];
    struct cell *BL = &grid[2][0];
    struct cell *LL = &grid[2][1];
    struct cell *LR = &grid[2][2];
    struct cell *BR = &grid[2][3];
    struct cell *DL = &grid[3][1];
    struct cell *DR = &grid[3][2];

    RT_APPLICATION_INIT(&aaap);
    memset(&grid, 0, sizeof(struct cell) * 16);

    /* 4x4 sub-pixel grid, dx gets to inner cells */
    VSCALE(dy, dy_model, 0.125);
    VSCALE(dx, dx_model, 0.125);

    /* 4x4 sub-pixel grid, dx*3 gets to outer cells */
    VSCALE(dy3, dy_model, 0.375);
    VSCALE(dx3, dx_model, 0.375);

    /* setup */
    aaap.a_hit = rayhit2;
    aaap.a_miss = raymiss2;
    aaap.a_onehit = 1;
    aaap.a_rt_i = ap->a_rt_i;
    aaap.a_resource = ap->a_resource;
    aaap.a_logoverlap = ap->a_logoverlap;

    /* Above Left */
    aaap.a_uptr = (void *)AL;
    VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3);
    VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("AL", aaap.a_ray.r_pt);
#endif

    /* Above Right */
    aaap.a_uptr = (void *)AR;
    VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3);
    VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("AR", aaap.a_ray.r_pt);
#endif

    /* Top Left */
    aaap.a_uptr = (void *)TL;
    VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("TL", aaap.a_ray.r_pt);
#endif

    /* Upper Left */
    aaap.a_uptr = (void *)UL;
    VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("UL", aaap.a_ray.r_pt);
#endif

    /* Upper Right */
    aaap.a_uptr = (void *)UR;
    VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("UR", aaap.a_ray.r_pt);
#endif

    /* Top Right */
    aaap.a_uptr = (void *)TR;
    VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("TR", aaap.a_ray.r_pt);
#endif

    /* Bottom Left */
    aaap.a_uptr = (void *)BL;
    VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("BL", aaap.a_ray.r_pt);
#endif

    /* Lower Left */
    aaap.a_uptr = (void *)LL;
    VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("LL", aaap.a_ray.r_pt);
#endif

    /* Lower Right */
    aaap.a_uptr = (void *)LR;
    VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("LR", aaap.a_ray.r_pt);
#endif

    /* Bottom Right */
    aaap.a_uptr = (void *)BR;
    VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy);
    VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("BR", aaap.a_ray.r_pt);
#endif

    /* Debajo Left */
    aaap.a_uptr = (void *)DL;
    VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3);
    VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("DL", aaap.a_ray.r_pt);
#endif

    /* Debajo Right */
    aaap.a_uptr = (void *)DR;
    VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3);
    VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx);
    VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir);
    rt_shootray(&aaap);

#ifdef VEDEBUG
    VPRINT("DR", aaap.a_ray.r_pt);
#endif

#define TWOBYTWO 1
#ifdef TWOBYTWO
    if (is_edge(NULL, NULL, UL, left, LL, UR, above)) {
	*intensity += 0.25;
    }
    if (is_edge(NULL, NULL, UR, UL, LR, right, above)) {
	*intensity += 0.25;
    }
    if (is_edge(NULL, NULL, LL, left, below, LR, UL)) {
	*intensity += 0.25;
    }
    if (is_edge(NULL, NULL, LR, LL, below, right, UR)) {
	*intensity += 0.25;
    }
#else
    if (is_edge(NULL, NULL, UL, TL, LL, UR, AL)) {
	*intensity += 0.25;
    }
    if (is_edge(NULL, NULL, UR, UL, LR, TR, AR)) {
	*intensity += 0.25;
    }
    if (is_edge(NULL, NULL, LL, BL, DL, LR, UL)) {
	*intensity += 0.25;
    }
    if (is_edge(NULL, NULL, LR, LL, DR, BR, UR)) {
	*intensity += 0.25;
    }
#endif
}
Ejemplo n.º 16
0
/*
 *			M A I N
 */
int
main(int argc, char **argv)
{
    struct application	ap;

    static struct rt_i *rtip;
    char *title_file;
    char idbuf[RT_BUFSIZE] = {0};		/* First ID record info */
    char *ptr;
    int attr_count=0, i;
    char **attrs = (char **)NULL;

    if ( argc < 3 )  {
	bu_exit(1, usage);
    }

    RT_APPLICATION_INIT(&ap);

    argc--;
    argv++;
    while ( argv[0][0] == '-' ) switch ( argv[0][1] )  {
	case 'R':
	    bundle_radius = atof( argv[1] );
	    argc -= 2;
	    argv += 2;
	    break;
	case 'n':
	    num_rings = atoi( argv[1] );
	    argc -= 2;
	    argv += 2;
	    break;
	case 'c':
	    rays_per_ring = atoi( argv[1] );
	    argc -= 2;
	    argv += 2;
	    break;
	case 'v':
	    /* count the number of attribute names provided */
	    ptr = argv[1];
	    while ( *ptr ) {
		while ( *ptr && isspace( *ptr ) )
		    ptr++;
		if ( *ptr )
		    attr_count++;
		while ( *ptr && !isspace( *ptr ) )
		    ptr++;
	    }

	    if ( attr_count == 0 ) {
		bu_log( "missing list of attribute names!\n" );
		bu_exit( 1, usage );
	    }

	    /* allocate enough for a null terminated list */
	    attrs = (char **)bu_calloc( attr_count + 1, sizeof( char *), "attrs" );

	    /* use strtok to actually grab the names */
	    i = 0;
	    ptr = strtok( argv[1], "\t " );
	    while ( ptr && i < attr_count ) {
		attrs[i] = bu_strdup( ptr );
		ptr = strtok( (char *)NULL, "\t " );
		i++;
	    }
	    argc -= 2;
	    argv += 2;
	    break;
	case 't':
	    rt_bot_tri_per_piece = atoi( argv[1] );
	    argc -= 2;
	    argv += 2;
	    break;
	case 'b':
	    rt_bot_minpieces = atoi( argv[1] );
	    argc -= 2;
	    argv += 2;
	    break;
	case 'o':
	    sscanf( argv[1], "%d", &set_onehit );
	    argc -= 2;
	    argv += 2;
	    break;
	case 'r':
	{
	    float ray_len;

	    sscanf( argv[1], "%f", &ray_len );
	    set_ray_length = ray_len;
	}
	argc -= 2;
	argv += 2;
	break;
	case 'U':
	    sscanf( argv[1], "%d", &use_air );
	    argc -= 2;
	    argv += 2;
	    break;
	case 'u':
	    sscanf( argv[1], "%x", (unsigned int *)&bu_debug );
	    fprintf(stderr, "librt bu_debug=x%x\n", bu_debug);
	    argc -= 2;
	    argv += 2;
	    break;
	case 'x':
	    sscanf( argv[1], "%x", (unsigned int *)&rt_g.debug );
	    fprintf(stderr, "librt rt_g.debug=x%x\n", rt_g.debug);
	    argc -= 2;
	    argv += 2;
	    break;
	case 'X':
	    sscanf( argv[1], "%x", (unsigned int *)&rdebug );
	    fprintf(stderr, "rdebug=x%x\n", rdebug);
	    argc -= 2;
	    argv += 2;
	    break;
	case 'N':
	    sscanf( argv[1], "%x", (unsigned int *)&rt_g.NMG_debug);
	    fprintf(stderr, "librt rt_g.NMG_debug=x%x\n", rt_g.NMG_debug);
	    argc -= 2;
	    argv += 2;
	    break;
	case 'd':
	    if ( argc < 4 )  goto err;
	    ap.a_ray.r_dir[X] = atof( argv[1] );
	    ap.a_ray.r_dir[Y] = atof( argv[2] );
	    ap.a_ray.r_dir[Z] = atof( argv[3] );
	    set_dir = 1;
	    argc -= 4;
	    argv += 4;
	    continue;

	case 'p':
	    if ( argc < 4 )  goto err;
	    ap.a_ray.r_pt[X] = atof( argv[1] );
	    ap.a_ray.r_pt[Y] = atof( argv[2] );
	    ap.a_ray.r_pt[Z] = atof( argv[3] );
	    set_pt = 1;
	    argc -= 4;
	    argv += 4;
	    continue;

	case 'a':
	    if ( argc < 4 )  goto err;
	    at_vect[X] = atof( argv[1] );
	    at_vect[Y] = atof( argv[2] );
	    at_vect[Z] = atof( argv[3] );
	    set_at = 1;
	    argc -= 4;
	    argv += 4;
	    continue;

	case 'O':
	{
	    if ( !strcmp( argv[1], "resolve" ) || !strcmp( argv[1], "0") )
		overlap_claimant_handling = 0;
	    else if ( !strcmp( argv[1], "rebuild_fastgen" ) || !strcmp( argv[1], "1") )
		overlap_claimant_handling = 1;
	    else if ( !strcmp( argv[1], "rebuild_all" ) || !strcmp( argv[1], "2") )
		overlap_claimant_handling = 2;
	    else if ( !strcmp( argv[1], "retain" ) || !strcmp( argv[1], "3") )
		overlap_claimant_handling = 3;
	    else
	    {
		bu_log( "Illegal argument (%s) to '-O' option.  Must be:\n", argv[1] );
		bu_log( "\t'resolve' or '0'\n");
		bu_log( "\t'rebuild_fastgen' or '1'\n");
		bu_log( "\t'rebuild_all' or '2'\n");
		bu_log( "\t'retain' or '3'\n");
		bu_exit(1, NULL);
	    }
	    argc -= 2;
	    argv += 2;
	}
	continue;

	default:
    err:
	    bu_exit(1, usage);
    }
    if ( argc < 2 )  {
	(void)fputs(usage, stderr);
	bu_exit(1, "rtshot: MGED database not specified\n");
    }

    if ( set_dir + set_pt + set_at != 2 )  goto err;

    if ( num_rings != 0 || rays_per_ring != 0 || bundle_radius != 0.0 ) {
	if ( num_rings <= 0 || rays_per_ring <= 0 || bundle_radius <= 0.0 ) {
	    fprintf( stderr, "Must have all of \"-R\", \"-n\", and \"-c\" set\n" );
	    goto err;
	}
    }

    /* Load database */
    title_file = argv[0];
    argv++;
    argc--;
    if ( (rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL ) {
	bu_exit(2, "rtshot:  rt_dirbuild failure\n");
    }

    if ( overlap_claimant_handling )
	rtip->rti_save_overlaps = 1;

    ap.a_rt_i = rtip;
    fprintf(stderr, "db title:  %s\n", idbuf);
    rtip->useair = use_air;

    /* Walk trees */
    if ( rt_gettrees_and_attrs( rtip, (const char **)attrs, argc, (const char **)argv, 1 ) ) {
	bu_exit(1, "rt_gettrees FAILED\n");
    }
    ap.attrs = attrs;

    rt_prep(rtip);

    if ( R_DEBUG&RDEBUG_RAYPLOT )  {
	if ( (plotfp = fopen("rtshot.plot", "w")) == NULL )  {
	    perror("rtshot.plot");
	    bu_exit(1, NULL);
	}
	pdv_3space( plotfp, rtip->rti_pmin, rtip->rti_pmax );
    }

    /* Compute r_dir and r_pt from the inputs */
    if ( set_at )  {
	if ( set_dir ) {
	    vect_t	diag;
	    fastf_t	viewsize;
	    VSUB2( diag, rtip->mdl_max, rtip->mdl_min );
	    viewsize = MAGNITUDE( diag );
	    VJOIN1( ap.a_ray.r_pt, at_vect,
		    -viewsize/2.0, ap.a_ray.r_dir );
	} else {
	    /* set_pt */
	    VSUB2( ap.a_ray.r_dir, at_vect, ap.a_ray.r_pt );
	}
    }
    VUNITIZE( ap.a_ray.r_dir );

    if ( rays_per_ring ) {
	bu_log( "Central Ray:\n" );
    }
    VPRINT( "Pnt", ap.a_ray.r_pt );
    VPRINT( "Dir", ap.a_ray.r_dir );

    if ( set_onehit )
	ap.a_onehit = set_onehit;
    else
	ap.a_onehit = 0;

    if ( set_ray_length > 0.0 )
	ap.a_ray_length = set_ray_length;
    else
	ap.a_ray_length = 0.0;

    /* Shoot Ray */
    ap.a_purpose = "main ray";
    ap.a_hit = hit;
    ap.a_miss = miss;

    if ( rays_per_ring ) {
	vect_t avec, bvec;
	struct xray *rp;

	/* create orthogonal rays for basis of bundle */
	bn_vec_ortho( avec, ap.a_ray.r_dir );
	VCROSS( bvec, ap.a_ray.r_dir, avec );
	VUNITIZE( bvec );

	rp = (struct xray *)bu_calloc( sizeof( struct xray ),
				       (rays_per_ring * num_rings) + 1,
				       "ray bundle" );
	rp[0] = ap.a_ray;	/* struct copy */
	rp[0].magic = RT_RAY_MAGIC;
	rt_raybundle_maker( rp, bundle_radius, avec, bvec, rays_per_ring, num_rings );
	(void)rt_shootray_bundle( &ap, rp, (rays_per_ring * num_rings) + 1 );
    } else {
	(void)rt_shootray( &ap );
    }

    return(0);
}
Ejemplo n.º 17
0
/**
 * NOTE that the [0] element here corresponds with the caller's (1)
 * element.
 */
void
BU_FORTRAN(frshot, FRSHOT)(int *nloc,			/* input & output */
			   double *indist,		/* output only */
			   double *outdist,
			   int *region_ids,
			   struct context *context,
			   struct rt_i **rtip,		/* input only */
			   double *pt,
			   double *dir)
{
    struct application ap;
    register struct partition *pp;
    int ret;
    register int i;

    RT_CHECK_RTI(*rtip);

    if (*nloc <= 0) {
	bu_log("ERROR frshot: nloc=%d\n", *nloc);
	*nloc = 0;
	return;
    }

    RT_APPLICATION_INIT(&ap);
    ap.a_ray.r_pt[X] = pt[0];
    ap.a_ray.r_pt[Y] = pt[1];
    ap.a_ray.r_pt[Z] = pt[2];
    ap.a_ray.r_dir[X] = dir[0];
    ap.a_ray.r_dir[Y] = dir[1];
    ap.a_ray.r_dir[Z] = dir[2];
    VUNITIZE(ap.a_ray.r_dir);
    ap.a_hit = fr_hit;
    ap.a_miss = fr_miss;
    ap.a_level = 0;
    ap.a_onehit = *nloc * 2;
    ap.a_resource = &rt_uniresource;
    rt_uniresource.re_magic = RESOURCE_MAGIC;
    ap.a_purpose = "frshot";
    ap.a_rt_i = *rtip;

    /*
     * Actually fire the ray.  The list of results will be linked to
     * fr_global_head by fr_hit(), for further use below.
     *
     * It is a bit risky to rely on the segment structures pointed to
     * by the partition list to still be valid, because rt_shootray
     * has already put them back on the free segment queue.  However,
     * they will remain unchanged until the next call to
     * rt_shootray(), so copying out the data here will work fine.
     */
    ret = rt_shootray(&ap);

    if (ret <= 0) {
	/* Signal no hits */
	*nloc = 0;
	return;
    }

    /* Copy hit information from linked list to argument arrays */
    pp = fr_global_head.pt_forw;
    if (pp == &fr_global_head) {
	*nloc = 0;
	return;
    }
    for (i=0; i < *nloc; i++, pp=pp->pt_forw) {
	register struct context *ctp;

	if (pp == &fr_global_head) break;
	indist[i] = pp->pt_inhit->hit_dist;
	outdist[i] = pp->pt_outhit->hit_dist;
	/* This might instead be reg_regionid ?? */
	region_ids[i] = pp->pt_regionp->reg_bit+1;
	ctp = &context[i];
	ctp->co_stp = pp->pt_inseg->seg_stp;
	VMOVE(ctp->co_vpriv, pp->pt_inhit->hit_vpriv);
	ctp->co_priv = pp->pt_inhit->hit_private;
	ctp->co_inflip = pp->pt_inflip;
    }
    *nloc = i;	/* Will have been incremented above, if successful */

    /* Free linked list storage */
    for (pp = fr_global_head.pt_forw; pp != &fr_global_head;) {
	register struct partition *newpp;

	newpp = pp;
	pp = pp->pt_forw;
	FREE_PT(newpp, (&rt_uniresource));
    }
}
Ejemplo n.º 18
0
int main(int argc, char **argv)
{
    struct application ap;	/* Structure passed between functions.  */
    struct rt_i *rtip;
    int idx;		/* Index for rt_dirbuild & rt_gettree.  */
    char idbuf[32];	/* Contains database name.  */
    struct region *pr;	/* Used in finding region names.  */
    double rho, phi, theta;/* Spherical coordinates for starting point.  */
    double areabs=0.0;	/* Area of bounding sphere (mm**2).  */
    int ians;		/* Answer of question.  */
    double strtpt[3];	/* Starting point of ray.  */
    double strtdir[3];	/* Starting direction.  */
    size_t loops;	/* Number of rays fired.  */
    size_t r;		/* Variable in loops.  */
    int i, j, k;		/* Variable in loops.  */
    long seed;		/* Initial seed for random number generator.  */
    double denom;	/* Denominator.  */
    double elev;		/* Elevation, used to find point on yz-plane.  */
    double az;		/* Azimuth, used to find point on yz-plane.  */
    double rad;		/* Radius, used to find point on yz-plane.  */
    double s[3], t[3];	/* Temporary variables used to find points.  */
    double q;		/* Temporary variable used to find points.  */
    int numreg;		/* Number of regions.  */
    double center[3];	/* Center of the bounding rpp.  */
    double sf;		/* Used to print shape factor.  */
    double dump;		/* How often a dump is to occur.  */
    int idump;		/* 1=>dump to occur.  */

    FILE *fp;		/* Used to open files.  */
    char outfile[16];	/* Output file.  */
    FILE *fp1;		/* Used to read region # & name file.  */
    char rnnfile[16];	/* Region # & name file.  */
    FILE *fp2;		/* Used to write the error file.  */
    char errfile[16];	/* Error file.  */
    double totalsf;	/* Sum of shape factors.  */
    double totalnh;	/* Sum of number of hits.  */
    int itype;		/* Type of file to be created, 0=>regular,  */
			/* 1=>generic.  */
    char line[500];	/* Buffer to read a line of data into.  */
    int c;		/* Reads one character of information.  */
    int icnt;		/* Counter for shape factor.  */
    char tmpname[150];	/* Temporary name.  */
    int tmpreg;		/* Temporary region number.  */
    char rnnname[800][150];  /* Region name from region # & name file.  */
    int rnnnum;		/* Number of regions in region # & name file.  */
    int rnnchar[800];	/* Number of characters in name.  */
    int rnnreg[800];	/* Region number from region # & name file.  */
    int jcnt;		/* Counter.  */
    int equal;		/* 0=>equal, 1=>not equal.  */
    double rcpi, rcpj;	/* Used to check reciprocity.  */
    double rcp_diff;	/* Difference in reciprocity.  */
    double rcp_pdiff;	/* Percent difference in reciprocity.  */
    int ret;

    struct bn_unif *msr = NULL;

    /* Check to see if arguments are implemented correctly.  */
    if ((argc < 3 || argv[1] == NULL) || (argv[2] == NULL)) {
	fprintf(stderr, "\nUsage:  %s file.g objects\n\n", *argv);
    } else {
	/* START # 1 */

	/* Ask what type of file is to be created - regular */
	/* or generic.  */
	printf("Enter type of file to be written (0=>regular or ");
	printf("1=>generic).  ");
	(void)fflush(stdout);
	ret = scanf("%1d", &itype);
	if (ret == 0)
	    bu_exit(-1, "scanf failure when reading file type");
	if (itype != 1) itype = 0;

	/* Enter names of files to be used.  */
	fprintf(stderr, "Enter name of output file (15 char max).\n\t");
	(void)fflush(stderr);
	ret = scanf("%15s", outfile);
	if (ret == 0)
	    bu_exit(-1, "scanf failure when reading output file name");

	/* Read name of the error file to be written.  */
	printf("Enter the name of the error file (15 char max).\n\t");
	(void)fflush(stdout);
	ret = scanf("%15s", errfile);
	if (ret == 0)
	    bu_exit(-1, "scanf failure when reading error file name");

	{
	    /* Enter name of region # & name file to be read.  */
	    printf("Enter region # & name file to be read ");
	    printf("(15 char max).\n\t");
	    (void)fflush(stdout);
	    ret = scanf("%15s", rnnfile);
	    if (ret == 0)
		bu_exit(-1, "scanf failure when reading region # + name file");
	}

	/* Check if dump is to occur.  */
	idump = 0;
	printf("Do you want to dump intermediate shape factors to ");
	printf("screen (0-no, 1-yes)?  ");
	(void)fflush(stdout);
	ret = scanf("%1d", &idump);
	if (ret == 0)
	    bu_exit(-1, "scanf failure - intermediate shape factors setting");

	/* Find number of rays to be fired.  */
	fprintf(stderr, "Enter number of rays to be fired.  ");
	(void)fflush(stderr);
	ret = scanf("%llu", (unsigned long long *)&loops);
	if (ret == 0)
	    bu_exit(-1, "scanf failure - number of rays to be fired");

	/* clamp loops */
	if (loops > UINT32_MAX)
	    loops = UINT32_MAX;

	/* Set seed for random number generator.  */
	seed = 1;
	fprintf(stderr, "Do you wish to enter your own seed (0) or ");
	fprintf(stderr, "use the default of 1 (1)?  ");
	(void)fflush(stderr);
	ret = scanf("%1d", &ians);
	if (ret == 0)
	    bu_exit(-1, "scanf failure - seed use setting");
	if (ians == 0) {
	    fprintf(stderr, "Enter unsigned integer seed.  ");
	    (void)fflush(stderr);
	    ret = scanf("%ld", &seed);
	    if (ret == 0)
		bu_exit(-1, "scanf failure - seed");
	}
	msr = bn_unif_init(seed, 0);
	bu_log("seed initialized\n");

	/* Read region # & name file.  */
	rnnnum = 0;
	fp1 = fopen(rnnfile, "rb");
	c = getc(fp1);
	while (c != EOF) {
	    (void)ungetc(c, fp1);
	    (void)bu_fgets(line, 200, fp1);
	    sscanf(line, "%d%149s", &tmpreg, tmpname);
	    for (i=0; i<150; i++) {
		rnnname[rnnnum][i] = tmpname[i];
	    }
	    rnnreg[rnnnum] = tmpreg;
	    rnnnum++;
	    c = getc(fp1);
	}
	(void)fclose(fp1);

	printf("Number of regions read from region # & name file:  %d\n",		rnnnum);
	(void)fflush(stdout);

	/* Find number of characters in each region name.  */
	for (i=0; i<rnnnum; i++) {
	    jcnt = 0;
	    while (rnnname[i][jcnt] != '\0') {
		jcnt++;
	    }
	    rnnchar[i] = jcnt;
	}

	/* Build directory.  */
	idx = 1;	/* Set index for rt_dirbuild.  */
	rtip = rt_dirbuild(argv[idx], idbuf, sizeof(idbuf));
	printf("Database Title:  %s\n", idbuf);
	(void)fflush(stdout);

	/* Set useair to 1 to show hits of air.  */
	rtip->useair = 1;

	/* Load desired objects.  */
	idx = 2;	/* Set index.  */
	while (argv[idx] != NULL) {
	    rt_gettree(rtip, argv[idx]);
	    idx += 1;
	}

	/* Find number of regions.  */
	numreg = (int)rtip->nregions;

	fprintf(stderr, "Number of regions:  %d\n", numreg);
	(void)fflush(stderr);

	/* Zero all arrays.  */
	for (i=0; i<numreg; i++) {
	    info[i].name = "\0";
	    info[i].regnum = (-1);
	    info[i].numchar = 0;
	    info[i].lvrays = 0.0;
	    info[i].engarea = 0.0;
	    for (j=0; j<numreg; j++) {
		info[i].intrays[j] = 0.0;
	    }
	}
	nummiss = 0.0;

	/* Get database ready by starting prep.  */
	rt_prep(rtip);

	/* Find the center of the bounding rpp.  */
	center[X] = rtip->mdl_min[X] +
	    (rtip->mdl_max[X] - rtip->mdl_min[X]) / 2.0;
	center[Y] = rtip->mdl_min[Y] +
	    (rtip->mdl_max[Y] - rtip->mdl_min[Y]) / 2.0;
	center[Z] = rtip->mdl_min[Z] +
	    (rtip->mdl_max[Z] - rtip->mdl_min[Z]) / 2.0;

	/* Put region names into structure.  */
	pr = BU_LIST_FIRST(region, &rtip->HeadRegion);
	for (i=0; i<numreg; i++) {
	    info[(int)(pr->reg_bit)].name = pr->reg_name;
	    pr = BU_LIST_FORW(region, &(pr->l));
	}

	/* Set up parameters for rt_shootray.  */
	RT_APPLICATION_INIT(&ap);
	ap.a_hit = hit;		/* User supplied hit function.  */
	ap.a_miss = miss;	/* User supplied miss function.  */
	ap.a_overlap = overlap;	/* User supplied overlap function.  */
	ap.a_rt_i = rtip;	/* Pointer from rt_dirbuild.  */
	ap.a_onehit = 0;	/* Look at all hits.  */
	ap.a_level = 0;		/* Recursion level for diagnostics.  */
	ap.a_resource = 0;	/* Address for resource structure.  */

	dump = 1000000.0;	/* Used for dumping info.  */

	for (r=0; r<loops; r++) {
	    /* Number of rays fired.  */
	    /* START # 2 */

	    /* Find length of 'diagonal' (rho).  (In reality rho is */
	    /* the radius of bounding sphere).  */
	    rho = (rtip->mdl_max[X] - rtip->mdl_min[X])
		* (rtip->mdl_max[X] - rtip->mdl_min[X])
		+(rtip->mdl_max[Y] - rtip->mdl_min[Y])
		* (rtip->mdl_max[Y] - rtip->mdl_min[Y])
		+(rtip->mdl_max[Z] - rtip->mdl_min[Z])
		* (rtip->mdl_max[Z] - rtip->mdl_min[Z]);
	    rho = sqrt(rho) / 2.0 + .5;

	    /* find surface area of bounding sphere.  */
	    areabs = 4.0 * M_PI * rho * rho;

	    /* Second way to find starting point and direction.  */
	    /* This approach finds the starting point and direction */
	    /* by using parallel rays.  */

	    /* Find point on the bounding sphere.  (The negative */
	    /* of the unit vector of this point will eventually be */
	    /* the firing direction.  */
	    q = BN_UNIF_DOUBLE(msr) + 0.5;
	    theta = q * M_2PI;
	    q = BN_UNIF_DOUBLE(msr) + 0.5;
	    phi = (q * 2.0) - 1.0;
	    phi = acos(phi);
	    strtdir[X] = rho * sin(phi) * cos(theta);
	    strtdir[Y] = rho * sin(phi) * sin(theta);
	    strtdir[Z] = rho * cos(phi);

	    /* Elevation and azimuth for finding a vector in a plane.  */
	    elev = M_PI_2 - phi;
	    az = theta;

	    /* Find vector in yz-plane.  */

	    q = BN_UNIF_DOUBLE(msr) + 0.5;
	    theta = q * M_2PI;
	    q = BN_UNIF_DOUBLE(msr) + 0.5;
	    rad = rho * sqrt(q);
	    s[X] = 0.0;
	    s[Y] = rad * cos(theta);
	    s[Z] = rad * sin(theta);

	    /* Rotate vector.  */
	    t[X] = s[X] * cos(elev) * cos(az) - s[Z] * sin(elev) * cos(az)
		- s[Y] * sin(az);
	    t[Y] = s[X] * cos(elev) * sin(az) - s[Z] * sin(elev) * sin(az)
		+ s[Y] * cos(az);
	    t[Z] = s[X] * sin(elev) + s[Z] * cos(elev);

	    /* Translate the point.  This is starting point.  */
	    strtpt[X] = t[X] + strtdir[X];
	    strtpt[Y] = t[Y] + strtdir[Y];
	    strtpt[Z] = t[Z] + strtdir[Z];

	    /* Now transfer starting point so that it is in */
	    /* the absolute coordinates not the origin's.  */
	    strtpt[X] += center[X];
	    strtpt[Y] += center[Y];
	    strtpt[Z] += center[Z];

	    /* Normalize starting direction and make negative.  */
	    denom = strtdir[X] * strtdir[X] +
		strtdir[Y] * strtdir[Y] +
		strtdir[Z] * strtdir[Z];
	    denom = sqrt(denom);
	    strtdir[X] /= (-denom);
	    strtdir[Y] /= (-denom);
	    strtdir[Z] /= (-denom);

	    /* Set up firing point and direction.  */
	    ap.a_ray.r_pt[X] = strtpt[X];
	    ap.a_ray.r_pt[Y] = strtpt[Y];
	    ap.a_ray.r_pt[Z] = strtpt[Z];
	    ap.a_ray.r_dir[X] = strtdir[X];
	    ap.a_ray.r_dir[Y] = strtdir[Y];
	    ap.a_ray.r_dir[Z] = strtdir[Z];

	    /* Call rt_shootray for "forward ray".  */
	    (void)rt_shootray(&ap);

	    if (EQUAL(r, (dump - 1.0))) {
		printf("%llu rays have been fired in forward direction.\n",
		       (unsigned long long)(r+1));
		(void)fflush(stdout);
		if (idump == 1) {
		    /* START # 3 */
		    printf("\n****************************************");
		    printf("****************************************\n");
		    (void)fflush(stdout);
		    /* Dump info to file.  */
		    for (i=0; i<numreg; i++) {
			for (j=0; j<numreg; j++) {
			    sf = 0.0;
			    if ((info[i].lvrays < -ZEROTOL) || (ZEROTOL <
								info[i].lvrays))
				sf = info[i].intrays[j] / info[i].lvrays;

			    printf("%d\t%d\t%f\n", i, j, sf);
			    (void)fflush(stdout);
			}
		    }
		}						/* START # 3 */

		dump = dump + 1000000.0;
	    }

	}					/* END # 2 */

	/* Find area bounded by engine air using Monte Carlo method.  */
	for (i=0; i<numreg; i++) {
	    /* Old way, only incrementing info[i].allvrays for forward */
	    /* ray therefore do not divide by 2.  Division by 2 is to */
	    /* include the backwards ray also.  */
	    /*
	     * info[i].engarea = info[i].allvrays * areabs / loops / 2.0;
	     */
	    info[i].engarea = info[i].allvrays * areabs / (double)loops;

	    /* Put area into square meters.  */
	    info[i].engarea *= 1.e-6;
	}

	/* Find number of characters in each region name.  */
	for (i=0; i<numreg; i++) {
	    jcnt = 0;
	    while (info[i].name[jcnt] != '\0') {
		jcnt++;
	    }
	    info[i].numchar = jcnt;
	}

	/* Find correct region number.  */
	printf("Finding correct region numbers.\n");
	(void)fflush(stdout);
	for (i=0; i<numreg; i++) {
	    for (j=0; j<rnnnum; j++) {
		equal = 0;	/* 1=>not equal.  */
		jcnt = rnnchar[j];
		for (k=info[i].numchar; k>=0; k--) {
		    if (jcnt<0) equal = 1;
		    else if (info[i].name[k] != rnnname[j][jcnt])
			equal = 1;
		    jcnt--;
		}
		if (equal == 0) info[i].regnum = rnnreg[j];
	    }
	}
	printf("Finished finding correct region numbers.\n");
	(void)fflush(stdout);

	/******************************************************************/

	/* Check for reciprocity.  */
	/* Open error file.  */
	fp2 = fopen(errfile, "wb");
	fprintf(fp2, "\nError file for shapefact.\n");
	fprintf(fp2, "Shape factor file created:  %s\n\n", outfile);
	fprintf(fp2, "Regions with reciprocity errors greater ");
	fprintf(fp2, "than 10%%.\n\n");
	(void)fflush(fp2);

	for (i=0; i<numreg; i++) {
	    for (j=0; j<numreg; j++) {
		rcpi = 0.0;
		rcpj = 0.0;
		if ((info[i].lvrays < -ZEROTOL) || (ZEROTOL < info[i].lvrays))
		    rcpi = info[i].intrays[j] * info[i].engarea /info[i].lvrays;
		if ((info[j].lvrays < -ZEROTOL) || (ZEROTOL < info[j].lvrays))
		    rcpj = info[j].intrays[i] * info[j].engarea /info[j].lvrays;
		rcp_diff = rcpi - rcpj;
		if (rcp_diff < 0.0) rcp_diff = (-rcp_diff);
		if ((rcpi < -ZEROTOL) || (ZEROTOL < rcpi))
		    rcp_pdiff = rcp_diff / rcpi;
		else rcp_pdiff = 0.0;	/* Don't divide by 0.  */
		/* Print reciprocity errors greater than 10%.  */
		if (rcp_pdiff > 0.1) {
		    fprintf(fp2, "%d   %d   %f   %f   %f   %f\n",
			    info[i].regnum, info[j].regnum, rcpi, rcpj, rcp_diff,
			    (rcp_pdiff * 100.0));
		    (void)fflush(fp2);
		}
	    }
	}
	/* Close error file.  */
	(void)fclose(fp2);

	/******************************************************************/

	/* Print out shape factor to regular output file.  */
	if (itype == 0) {
	    fp = fopen(outfile, "wb");
	    fprintf(fp, "Number of forward rays fired:  %llu\n\n", (unsigned long long)loops);
	    (void)fflush(fp);

	    /* Print out structure.  */
	    for (i=0; i<numreg; i++) {
		/* Print region number, region name, & engine area.  */
		fprintf(fp, "%d\t%s\t%e\n",
			info[i].regnum, info[i].name, info[i].engarea);
		(void)fflush(fp);

		/* Zero sums for shape factors & rays hit.  */
		totalsf = 0.0;
		totalnh = 0.0;

		for (j=0; j<numreg; j++) {
		    sf = 0.0;
		    if ((info[i].lvrays < -ZEROTOL) || (ZEROTOL <
							info[i].lvrays))
			sf = info[i].intrays[j] / info[i].lvrays;

		    /* Print region number & shape factor.  */
		    fprintf(fp, "   %d\t%e\n",
			    info[j].regnum, sf);
		    (void)fflush(fp);

		    /* Add to sum of shape factors & number of hits.  */
		    totalsf += sf;
		    totalnh += info[i].intrays[j];

		}

		/* Print sum of hits & sum of shape factors.  */
		fprintf(fp, " sum of hits:  %f\n", totalnh);
		fprintf(fp, " sum of shape factors:  %f\n\n", totalsf);
		(void)fflush(fp);
	    }
	    (void)fclose(fp);
	}

	/******************************************************************/

	/* Create and write to generic shape factor file.  */
	if (itype == 1) {
	    fp = fopen(outfile, "wb");
	    for (i=0; i<numreg; i++) {
		/* Count the number of shape factors.  */
		icnt = 0;
		for (j=0; j<numreg; j++) {
		    if (info[i].intrays[j] > ZEROTOL) icnt++;
		}
		/* Print the # 5, region number (matches firpass &  */
		/* secpass), engine area, & number of shape factors.  */
		fprintf(fp, " 5  %d  %e  %d\n",
			info[i].regnum, info[i].engarea, icnt);
		(void)fflush(fp);
		for (j=0; j<numreg; j++) {
		    if (info[i].intrays[j] > ZEROTOL) {
			sf = info[i].intrays[j] / info[i].lvrays;
			/* Print each region # & shape factor.  */
			fprintf(fp, "    %d  %e\n", info[j].regnum, sf);
			(void)fflush(fp);
		    }
		}
	    }
	    (void)fclose(fp);
	}

    }						/* END # 1 */
    return 0;
}
Ejemplo n.º 19
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;
}
void
_rt_gen_worker(int cpu, void *ptr)
{
    int i, j;
    struct application ap;
    struct rt_parallel_container *state = (struct rt_parallel_container *)ptr;
    point_t min, max;
    int ymin, ymax;
    int dir1, dir2, dir3;
    fastf_t d[3];
    int n[3];
    RT_APPLICATION_INIT(&ap);
    ap.a_rt_i = state->rtip;
    ap.a_hit = add_hit_pnts;
    ap.a_miss = ignore_miss;
    ap.a_onehit = 0;
    ap.a_logoverlap = rt_silent_logoverlap;
    ap.a_resource = &state->resp[cpu];
    ap.a_uptr = (void *)(&state->npts[cpu]);

    /* get min and max points of bounding box */
    VMOVE(min, state->rtip->mdl_min);
    VMOVE(max, state->rtip->mdl_max);

    /* Make sure we've got at least 10 steps in all 3 dimensions,
     * regardless of delta */
    for (i = 0; i < 3; i++) {
	n[i] = (max[i] - min[i])/state->delta;
	if(n[i] < 10) n[i] = 10;
	d[i] = (max[i] - min[i])/n[i];
    }

    dir1 = state->ray_dir;
    dir2 = (state->ray_dir+1)%3;
    dir3 = (state->ray_dir+2)%3;

    if (state->ncpus == 1) {
	ymin = 0;
	ymax = n[dir3];
    } else {
	ymin = n[dir3]/state->ncpus * (cpu - 1) + 1;
	ymax = n[dir3]/state->ncpus * (cpu);
	if (cpu == 1) ymin = 0;
	if (cpu == state->ncpus) ymax = n[dir3];
    }

    ap.a_ray.r_dir[state->ray_dir] = -1;
    ap.a_ray.r_dir[dir2] = 0;
    ap.a_ray.r_dir[dir3] = 0;
    VMOVE(ap.a_ray.r_pt, min);
    ap.a_ray.r_pt[state->ray_dir] = max[state->ray_dir] + 100;

    for (i = 0; i < n[dir2]; i++) {
	ap.a_ray.r_pt[dir3] = min[dir3] + d[dir3] * ymin;
	for (j = ymin; j < ymax; j++) {
	    rt_shootray(&ap);
	    ap.a_ray.r_pt[dir3] += d[dir3];
	}
	ap.a_ray.r_pt[dir2] += d[dir2];
    }
}