/**
 *@brief
 * Draw a vector between points "from" and "to", with the option of
 * having an arrowhead on either or both ends.
 *
 * The fromheadfract and toheadfract values indicate the length of the
 * arrowheads relative to the length of the vector to-from.  A typical
 * value is 0.1, making the head 10% of the size of the vector.  The
 * sign of the "fract" values indicates the pointing direction.
 * Positive points towards the "to" point, negative points towards
 * "from".  Upon return, the virtual pen is left at the "to" position.
 */
void
tp_3vector(FILE *plotfp, fastf_t *from, fastf_t *to, double fromheadfract, double toheadfract)
{
    register fastf_t len;
    register fastf_t hooklen;
    vect_t diff;
    vect_t c1, c2;
    vect_t h1, h2;
    vect_t backup;
    point_t tip;

    pdv_3line(plotfp, from, to);
    /* "pen" is left at "to" position */

    VSUB2(diff, to, from);
    if ((len = MAGNITUDE(diff)) < SMALL)  return;
    VSCALE(diff, diff, 1/len);
    bn_vec_ortho(c1, diff);
    VCROSS(c2, c1, diff);

    if (!ZERO(fromheadfract)) {
	hooklen = fromheadfract*len;
	VSCALE(backup, diff, -hooklen);

	VSCALE(h1, c1, hooklen);
	VADD3(tip, from, h1, backup);
	pdv_3move(plotfp, from);
	pdv_3cont(plotfp, tip);

	VSCALE(h2, c2, hooklen);
	VADD3(tip, from, h2, backup);
	pdv_3move(plotfp, tip);
    }
    if (!ZERO(toheadfract)) {
	hooklen = toheadfract*len;
	VSCALE(backup, diff, -hooklen);

	VSCALE(h1, c1, hooklen);
	VADD3(tip, to, h1, backup);
	pdv_3move(plotfp, to);
	pdv_3cont(plotfp, tip);

	VSCALE(h2, c2, hooklen);
	VADD3(tip, to, h2, backup);
	pdv_3move(plotfp, tip);
    }
    /* Be certain "pen" is left at "to" position */
    if (!ZERO(fromheadfract) || !ZERO(toheadfract))
	pdv_3cont(plotfp, to);

}
Example #2
0
void
rt_vlist_to_uplot(FILE *fp, const struct bu_list *vhead)
{
    register struct bn_vlist *vp;

    for (BU_LIST_FOR(vp, bn_vlist, vhead)) {
	register int i;
	register int nused = vp->nused;
	register const int *cmd = vp->cmd;
	register point_t *pt = vp->pt;

	for (i = 0; i < nused; i++, cmd++, pt++) {
	    switch (*cmd) {
		case BN_VLIST_POLY_START:
		case BN_VLIST_TRI_START:
		    break;
		case BN_VLIST_POLY_MOVE:
		case BN_VLIST_LINE_MOVE:
		case BN_VLIST_TRI_MOVE:
		    pdv_3move(fp, *pt);
		    break;
		case BN_VLIST_POLY_DRAW:
		case BN_VLIST_POLY_END:
		case BN_VLIST_LINE_DRAW:
		case BN_VLIST_TRI_DRAW:
		case BN_VLIST_TRI_END:
		    pdv_3cont(fp, *pt);
		    break;
		default:
		    bu_log("rt_vlist_to_uplot: unknown vlist cmd x%x\n",
			   *cmd);
	    }
	}
    }
}
Example #3
0
int
main(int argc, char *argv)
{
    double	xyz[3];
    int	i;
    int	first = 1;

    for (;;)  {
        xyz[0] = xyz[1] = xyz[2] = 0.0;

        buf[0] = '\0';
        bu_fgets( buf, sizeof(buf), stdin );
        if ( feof(stdin) )  break;
        i = sscanf( buf, "%lf %lf %lf",
                    &xyz[0], &xyz[1], &xyz[2] );
        if (debug)  {
            fprintf(stderr, "buf=%s", buf);
            fprintf(stderr, "%d: %f\t%f\t%f\n",
                    i, xyz[0], xyz[1], xyz[2] );
        }
        if ( i <= 0 )
            break;
        if ( first )  {
            first = 0;
            pdv_3move( stdout, xyz );
        } else {
            pdv_3cont( stdout, xyz );
        }
    }

    return 0;
}
void
plot_face(ON_3dPoint *pt1, ON_3dPoint *pt2, ON_3dPoint *pt3, int r, int g, int b, FILE *c_plot)
{
    point_t p1, p2, p3;

    VSET(p1, pt1->x, pt1->y, pt1->z);
    VSET(p2, pt2->x, pt2->y, pt2->z);
    VSET(p3, pt3->x, pt3->y, pt3->z);

    pl_color(c_plot, r, g, b);

    pdv_3move(c_plot, p1);
    pdv_3cont(c_plot, p2);
    pdv_3move(c_plot, p1);
    pdv_3cont(c_plot, p3);
    pdv_3move(c_plot, p2);
    pdv_3cont(c_plot, p3);
}
Example #5
0
/**
 *  Draw a ray
 */
void
pdv_3ray(FILE *fp, const fastf_t *pt, const fastf_t *dir, double t)
{
    point_t	tip;

    VJOIN1( tip, pt, t, dir );
    pdv_3move( fp, pt );
    pdv_3cont( fp, tip );
}
Example #6
0
HIDDEN
void plot_obr(int test_num, const point_t *pnt_array, int pnt_cnt)
{
    int i = 0;
    struct bu_vls name;
    FILE *plot_file = NULL;
    bu_vls_init(&name);
    bu_vls_printf(&name, "obr_test_%.3d.pl", test_num);
    plot_file = fopen(bu_vls_addr(&name), "w");
    pl_color(plot_file, 0, 255, 0);
    for (i = 0; i < pnt_cnt; i++) {
	pdv_3move(plot_file, pnt_array[i]);
	if (i < pnt_cnt - 1) {
	    pdv_3cont(plot_file, pnt_array[i+1]);
	} else {
	    pdv_3cont(plot_file, pnt_array[0]);
	}
    }
    fclose(plot_file);
    bu_vls_free(&name);
}
Example #7
0
void
view_eol(struct application *UNUSED(ap))
{
    struct cell	*posp;
    size_t i;
    int		cont;		/* continue flag */

    posp = &(cellp[0]);
    cont = 0;

    /* Plot the starting point and set cont to 0.  Then
     * march along the entire array and continue to plot the
     * hit points based on their distance from the emanation
     * plane. When consecutive hit-points with identical distances
     * are found, cont is set to one so that the entire sequence
     * of like-distanced hit-points can be plotted together.
     */

    pdv_3move( outfp, posp->c_hit );

    for ( i = 0; i < width-1; i++, posp++ )  {
	if (EQUAL(posp->c_dist, (posp+1)->c_dist))  {
	    cont = 1;
	    continue;
	} else  {
	    if (cont)  {
		pdv_3cont(outfp, posp->c_hit);
		cont = 0;
	    }
	    pdv_3cont(outfp, (posp+1)->c_hit);
	}
    }

    /* Catch the boundary condition if the last couple of cells
     * heve the same distance.
     */

    pdv_3cont(outfp, posp->c_hit);
}
Example #8
0
/*
 *			R A Y H I T
 *
 *  Rayhit() is called by rt_shootray() when the ray hits one or more objects.
 *  A per-shotline header record is written, followed by information about
 *  each object hit.
 *
 *  Note that the GIFT-3 format uses a different convention for the "zero"
 *  distance along the ray.  RT has zero at the ray origin (emanation plain),
 *  while GIFT has zero at the screen plain translated so that it contains
 *  the model origin.  This difference is compensated for by adding the
 *  'dcorrection' distance correction factor.
 *
 *  Also note that the GIFT-3 format requires information about the start
 *  point of the ray in two formats.  First, the h, v coordinates of the
 *  grid cell CENTERS (in screen space coordinates) are needed.
 *  Second, the ACTUAL h, v coordinates fired from are needed.
 *
 *  An optional rtg3.pl UnixPlot file is written, permitting a
 *  color vector display of ray-model intersections.
 */
int
rayhit(struct application *ap, register struct partition *PartHeadp, struct seg *segp)
{
    register struct partition *pp = PartHeadp->pt_forw;
    int 			comp_count;	/* component count */
    fastf_t			dfirst, dlast;	/* ray distances */
    static fastf_t		dcorrection = 0; /* RT to GIFT dist corr */
    int			card_count;	/* # comp. on this card */
    const char		*fmt;		/* printf() format string */
    struct bu_vls		str;
    char			buf[128];	/* temp. sprintf() buffer */
    point_t			hv;		/* GIFT h, v coords, in inches */
    point_t			hvcen;
    int			prev_id=-1;
    point_t			first_hit;
    int			first;

    if ( pp == PartHeadp )
	return(0);		/* nothing was actually hit?? */

    if ( ap->a_rt_i->rti_save_overlaps )
	rt_rebuild_overlaps( PartHeadp, ap, 1 );

    part_compact(ap, PartHeadp, TOL);

    /* count components in partitions */
    comp_count = 0;
    for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw )  {
	if ( pp->pt_regionp->reg_regionid > 0 ) {
	    prev_id = pp->pt_regionp->reg_regionid;
	    comp_count++;
	} else if ( prev_id <= 0 ) {
	    /* normally air would be output along with a solid partition, but this will require a '111' partition */
	    prev_id = pp->pt_regionp->reg_regionid;
	    comp_count++;
	} else
	    prev_id = pp->pt_regionp->reg_regionid;
    }
    pp = PartHeadp->pt_back;
    if ( pp!=PartHeadp && pp->pt_regionp->reg_regionid <= 0 )
	comp_count++;  /* a trailing '111' ident */
    if ( comp_count == 0 )
	return( 0 );

    /* Set up variable length string, to buffer this shotline in.
     * Note that there is one component per card, and that each card
     * (line) is 80 characters long.  Hence the parameters given to
     * rt-vls-extend().
     */

    bu_vls_init( &str );
    bu_vls_extend( &str, 80 * (comp_count+1) );

    /*
     *  Find the H, V coordinates of the grid cell center.
     *  RT uses the lower left corner of each cell.
     */
    {
	point_t		center;
	fastf_t		dx;
	fastf_t		dy;

	dx = ap->a_x + 0.5;
	dy = ap->a_y + 0.5;
	VJOIN2( center, viewbase_model, dx, dx_model, dy, dy_model );
	MAT4X3PNT( hvcen, model2hv, center );
    }

    /*
     *  Find exact h, v coordinates of actual ray start by
     *  projecting start point into GIFT h, v coordinates.
     */
    MAT4X3PNT( hv, model2hv, ap->a_ray.r_pt );

    /*
     *  In RT, rays are launched from the plane of the screen,
     *  and ray distances are relative to the start point.
     *  In GIFT-3 output files, ray distances are relative to
     *  the (H, V) plane translated so that it contains the origin.
     *  A distance correction is required to convert between the two.
     *  Since this really should be computed only once, not every time,
     *  the trip_count flag was added.
     */
    {

	static int  trip_count;
	vect_t	tmp;
	vect_t	viewZdir;

	if ( trip_count == 0) {

	    VSET( tmp, 0, 0, -1 );		/* viewing direction */
	    MAT4X3VEC( viewZdir, view2model, tmp );
	    VUNITIZE( viewZdir );
	    /* dcorrection will typically be negative */
	    dcorrection = VDOT( ap->a_ray.r_pt, viewZdir );
	    trip_count = 1;
	}
    }

    /* This code is for diagnostics.
     * bu_log("dcorrection=%g\n", dcorrection);
     */

    /* dfirst and dlast have been made negative to account for GIFT looking
     * in the opposite direction of RT.
     */

    dfirst = -(PartHeadp->pt_forw->pt_inhit->hit_dist + dcorrection);
    dlast = -(PartHeadp->pt_back->pt_outhit->hit_dist + dcorrection);
#if 0
    /* This code is to note any occurances of negative distances. */
    if ( PartHeadp->pt_forw->pt_inhit->hit_dist < 0)  {
	bu_log("ERROR: dfirst=%g at partition x%x\n", dfirst, PartHeadp->pt_forw );
	bu_log("\tdcorrection = %f\n", dcorrection );
	bu_log("\tray start point is ( %f %f %f ) in direction ( %f %f %f )\n", V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ) );
	VJOIN1( PartHeadp->pt_forw->pt_inhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_inhit->hit_dist, ap->a_ray.r_dir );
	VJOIN1( PartHeadp->pt_back->pt_outhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_outhit->hit_dist, ap->a_ray.r_dir );
	rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
    }
    /* End of bug trap. */
#endif
    /*
     *  Output the ray header.  The GIFT statements that
     *  would have generated this are:
     *  410	write(1, 411) hcen, vcen, h, v, ncomp, dfirst, dlast, a, e
     *  411	format(2f7.1, 2f9.3, i3, 2f8.2,' A', f6.1,' E', f6.1)
     */

#define	SHOT_FMT	"%7.1f%7.1f%9.3f%9.3f%3d%8.2f%8.2f A%6.1f E%6.1f"

    if ( rt_perspective > 0 )  {
	bn_ae_vec( &azimuth, &elevation, ap->a_ray.r_dir );
    }

    bu_vls_printf( &str, SHOT_FMT,
		   hvcen[0], hvcen[1],
		   hv[0], hv[1],
		   comp_count,
		   dfirst * MM2IN, dlast * MM2IN,
		   azimuth, elevation );

    /*
     *  As an aid to debugging, take advantage of the fact that
     *  there are more than 80 columns on UNIX "cards", and
     *  add debugging information to the end of the line to
     *  allow this shotline to be reproduced offline.
     *   -b gives the shotline x, y coordinates when re-running RTG3,
     *   -p and -d are used with RTSHOT
     *  The easy way to activate this is with the harmless -!1 option
     *  when running RTG3.
     */
    if ( R_DEBUG || bu_debug || RT_G_DEBUG )  {
	bu_vls_printf( &str, "   -b%d,%d -p %26.20e %26.20e %26.20e -d %26.20e %26.20e %26.20e\n",
		       ap->a_x, ap->a_y,
		       V3ARGS(ap->a_ray.r_pt),
		       V3ARGS(ap->a_ray.r_dir) );
    } else {
	bu_vls_putc( &str, '\n' );
    }

    /* loop here to deal with individual components */
    card_count = 0;
    prev_id = -1;
    first = 1;
    for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw )  {
	/*
	 *  The GIFT statements that would have produced
	 *  this output are:
	 *	do 632 i=icomp, iend
	 *	if (clos(icomp).gt.999.99.or.slos(i).gt.999.9) goto 635
	 * 632	continue
	 * 	write(1, 633)(item(i), clos(i), cangi(i), cango(i),
	 * &			kspac(i), slos(i), i=icomp, iend)
	 * 633	format(1x, 3(i4, f6.2, 2f5.1, i1, f5.1))
	 *	goto 670
	 * 635	write(1, 636)(item(i), clos(i), cangi(i), cango(i),
	 * &			kspac(i), slos(i), i=icomp, iend)
	 * 636	format(1x, 3(i4, f6.1, 2f5.1, i1, f5.0))
	 */
	fastf_t	comp_thickness;	/* component line of sight thickness */
	fastf_t	in_obliq;	/* in obliquity angle */
	fastf_t	out_obliq;	/* out obliquity angle */
	int	region_id;	/* solid region's id */
	int	air_id;		/* air id */
	fastf_t	dot_prod;	/* dot product of normal and ray dir */
	fastf_t	air_thickness;	/* air line of sight thickness */
	vect_t	normal;		/* surface normal */
	register struct partition	*nextpp = pp->pt_forw;

	region_id = pp->pt_regionp->reg_regionid;

	if ( region_id <= 0 && prev_id > 0 )
	{
	    /* air region output with previous partition */
	    prev_id = region_id;
	    continue;
	}
	comp_thickness = pp->pt_outhit->hit_dist -
	    pp->pt_inhit->hit_dist;

	/* The below code is meant to catch components with zero or
	 * negative thicknesses.  This is not supposed to be possible,
	 * but the condition has been seen.
	 */
#if 0
	if ( comp_thickness <= 0 )  {
	    VJOIN1( pp->pt_inhit->hit_point, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	    VJOIN1( pp->pt_outhit->hit_point, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir );
	    bu_log("ERROR: comp_thickness=%g for region id = %d at h=%g, v=%g (x=%d, y=%d), partition at x%x\n",
		   comp_thickness, region_id, hv[0], hv[1], ap->a_x, ap->a_y, pp );
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	    bu_log("Send this output to the BRL-CAD Developers ([email protected])\n");
	    if ( ! (RT_G_DEBUG & DEBUG_ARB8)) {
		rt_g.debug |= DEBUG_ARB8;
		rt_shootray(ap);
		rt_g.debug &= ~DEBUG_ARB8;
	    }
	}
#endif

	if ( nextpp == PartHeadp )  {
	    if ( region_id <= 0 ) {
		/* last partition is air, need a 111 'phantom armor' before AND after */
		bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before and after air region %s\n",
			pp->pt_regionp->reg_name );
		region_id = 111;
		air_id = pp->pt_regionp->reg_aircode;
		air_thickness = comp_thickness;
		comp_thickness = 0.0;
	    } else {
		/* Last partition, no air follows, use code 9 */
		air_id = 9;
		air_thickness = 0.0;
	    }
	} else if ( region_id <= 0 ) {
	    /* air region, need a 111 'phantom armor' */
	    bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before air region %s\n",
		    pp->pt_regionp->reg_name );
	    prev_id = region_id;
	    region_id = 111;
	    air_id = pp->pt_regionp->reg_aircode;
	    air_thickness = comp_thickness;
	    comp_thickness = 0.0;
	} else if ( nextpp->pt_regionp->reg_regionid <= 0 &&
		    nextpp->pt_regionp->reg_aircode != 0 )  {
	    /* Next partition is air region */
	    air_id = nextpp->pt_regionp->reg_aircode;
	    air_thickness = nextpp->pt_outhit->hit_dist -
		nextpp->pt_inhit->hit_dist;
	    prev_id = air_id;
	} else {
	    /* 2 solid regions, maybe with gap */
	    air_id = 0;
	    air_thickness = nextpp->pt_inhit->hit_dist -
		pp->pt_outhit->hit_dist;
	    if ( air_thickness < 0.0 )
		air_thickness = 0.0;
	    if ( !NEAR_ZERO( air_thickness, 0.1 ) )  {
		air_id = 1;	/* air gap */
		if ( R_DEBUG & RDEBUG_HITS )
		    bu_log("air gap added\n");
	    } else {
		air_thickness = 0.0;
	    }
	    prev_id = region_id;
	}

	/*
	 *  Compute the obliquity angles in degrees, ie,
	 *  the "declension" angle down off the normal vector.
	 *  RT normals always point outwards;
	 *  the "inhit" normal points opposite the ray direction,
	 *  the "outhit" normal points along the ray direction.
	 *  Hence the one sign change.
	 *  XXX this should probably be done with atan2()
	 */

	if ( first ) {
	    first = 0;
	    VJOIN1( first_hit, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	}
    out:
	RT_HIT_NORMAL( normal, pp->pt_inhit, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip );
	dot_prod = VDOT( ap->a_ray.r_dir, normal );
	if ( dot_prod > 1.0 )
	    dot_prod = 1.0;
	if ( dot_prod < -1.0 )
	    dot_prod = (-1.0);

	in_obliq = acos( -dot_prod ) *
	    bn_radtodeg;
	RT_HIT_NORMAL( normal, pp->pt_outhit, pp->pt_outseg->seg_stp, &(ap->a_ray), pp->pt_outflip );
	dot_prod = VDOT( ap->a_ray.r_dir, normal );
	if ( dot_prod > 1.0 )
	    dot_prod = 1.0;
	if ( dot_prod < -1.0 )
	    dot_prod = (-1.0);

	out_obliq = acos( dot_prod ) *
	    bn_radtodeg;

	/* Check for exit obliquties greater than 90 degrees. */
#if 0
	if ( in_obliq > 90 || in_obliq < 0 )  {
	    bu_log("ERROR: in_obliquity=%g\n", in_obliq);
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	}
	if ( out_obliq > 90 || out_obliq < 0 )  {
	    bu_log("ERROR: out_obliquity=%g\n", out_obliq);
	    VPRINT(" r_dir", ap->a_ray.r_dir);
	    VPRINT("normal", normal);
	    bu_log("dot=%g, acos(dot)=%g\n",
		   VDOT( ap->a_ray.r_dir, normal ),
		   acos( VDOT( ap->a_ray.r_dir, normal ) ) );
	    /* Print the defective one */
	    rt_pr_pt( ap->a_rt_i, pp );
	    /* Print the whole ray's partition list */
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	}
#endif

	if ( in_obliq > 90.0 )
	    in_obliq = 90.0;
	if ( in_obliq < 0.0 )
	    in_obliq = 0.0;
	if ( out_obliq > 90.0 )
	    out_obliq = 90.0;
	if ( out_obliq < 0.0 )
	    out_obliq = 0.0;

	/*
	 *  Handle 3-components per card output format, with
	 *  a leading space in front of the first component.
	 */
	if ( card_count == 0 )  {
	    bu_vls_strcat( &str, " " );
	}
	comp_thickness *= MM2IN;
	/* Check thickness fields for format overflow */
	if ( comp_thickness > 999.99 || air_thickness*MM2IN > 999.9 )
	    fmt = "%4d%6.1f%5.1f%5.1f%1d%5.0f";
	else
	    fmt = "%4d%6.2f%5.1f%5.1f%1d%5.1f";
#ifdef SPRINTF_NOT_PARALLEL
	bu_semaphore_acquire( BU_SEM_SYSCALL );
#endif
	snprintf(buf, 128, fmt,
		 region_id,
		 comp_thickness,
		 in_obliq, out_obliq,
		 air_id, air_thickness*MM2IN );
#ifdef SPRINTF_NOT_PARALLEL
	bu_semaphore_release( BU_SEM_SYSCALL );
#endif
	bu_vls_strcat( &str, buf );
	card_count++;
	if ( card_count >= 3 )  {
	    bu_vls_strcat( &str, "\n" );
	    card_count = 0;
	}

	/* A color rtg3.pl UnixPlot file of output commands
	 * is generated.  This is processed by plot(1)
	 * plotting filters such as pl-fb or pl-sgi.
	 * Portions of a ray passing through air within the
	 * model are represented in blue, while portions
	 * passing through a solid are assigned green.
	 * This will always be done single CPU,
	 * to prevent output garbling.  (See view_init).
	 */
	if (R_DEBUG & RDEBUG_RAYPLOT) {
	    vect_t     inpt;
	    vect_t     outpt;
	    VJOIN1(inpt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist,
		   ap->a_ray.r_dir);
	    VJOIN1(outpt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist,
		   ap->a_ray.r_dir);
	    pl_color(plotfp, 0, 255, 0);	/* green */
	    pdv_3line(plotfp, inpt, outpt);

	    if (air_thickness > 0) {
		vect_t     air_end;
		VJOIN1(air_end, ap->a_ray.r_pt,
		       pp->pt_outhit->hit_dist + air_thickness,
		       ap->a_ray.r_dir);
		pl_color(plotfp, 0, 0, 255);	/* blue */
		pdv_3cont(plotfp, air_end);
	    }
	}
	if ( nextpp == PartHeadp && air_id != 9 ) {
	    /* need to output a 111 'phantom armor' at end of shotline */
	    air_id = 9;
	    air_thickness = 0.0;
	    region_id = 111;
	    comp_thickness = 0.0;
	    goto out;
	}
    }

    /* If partway through building the line, add a newline */
    if ( card_count > 0 )  {
	/*
	 *  Note that GIFT zero-fills the unused component slots,
	 *  but neither COVART II nor COVART III require it,
	 *  so just end the line here.
	 */
	bu_vls_strcat( &str, "\n" );
    }

    /* Single-thread through file output.
     * COVART will accept non-sequential ray data provided the
     * ray header and its associated data are not separated.  CAVEAT:
     * COVART will not accept headers out of sequence.
     */
    bu_semaphore_acquire( BU_SEM_SYSCALL );

    fputs( bu_vls_addr( &str ), outfp );

    if ( shot_fp )
    {
	fprintf( shot_fp, "%.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %ld %.5f %.5f %.5f\n",
		 azimuth, elevation, V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ),
		 line_num, V3ARGS( first_hit) );

	line_num +=  1 + (comp_count / 3 );
	if ( comp_count % 3 )
	    line_num++;
    }

    /* End of single-thread region */
    bu_semaphore_release( BU_SEM_SYSCALL );

    /* Release vls storage */
    bu_vls_free( &str );

    return(0);
}
Example #9
0
/*
 *			T P _ 3 S Y M B O L
 */
void
tp_3symbol(FILE *fp, char *string, fastf_t *origin, fastf_t *rot, double scale)

/* string of chars to be plotted */
/* lower left corner of 1st char */
/* Transform matrix (WARNING: may xlate) */
/* scale factor to change 1x1 char sz */
{
    register unsigned char *cp;
    double	offset;			/* offset of char from given x, y */
    int	ysign;			/* sign of y motion, either +1 or -1 */
    vect_t	temp;
    vect_t	loc;
    mat_t	xlate_to_origin;
    mat_t	mat;

    if ( string == NULL || *string == '\0' )
	return;			/* done before begun! */

    /*
     *  The point "origin" will be the center of the axis rotation.
     *  The text is located in a local coordinate system with the
     *  lower left corner of the first character at (0, 0, 0), with
     *  the text proceeding onward towards +X.
     *  We need to rotate the text around its local (0, 0, 0),
     *  and then translate to the user's designated "origin".
     *  If the user provided translation or
     *  scaling in his matrix, it will *also* be applied.
     */
    MAT_IDN( xlate_to_origin );
    MAT_DELTAS_VEC( xlate_to_origin, origin );
    bn_mat_mul( mat, xlate_to_origin, rot );

    /* Check to see if initialization is needed */
    if ( tp_cindex[040] == 0 )  tp_setup();

    /* Draw each character in the input string */
    offset = 0;
    for ( cp = (unsigned char *)string; *cp; cp++, offset += scale )  {
	register int *p;	/* pointer to stroke table */
	register int stroke;

	VSET( temp, offset, 0, 0 );
	MAT4X3PNT( loc, mat, temp );
	pdv_3move( fp, loc );

	for ( p = tp_cindex[*cp]; (stroke= *p) != LAST; p++ )  {
	    int	draw;

	    if ( stroke==NEGY )  {
		ysign = (-1);
		stroke = *++p;
	    } else
		ysign = 1;

	    /* Detect & process pen control */
	    if ( stroke < 0 )  {
		stroke = -stroke;
		draw = 0;
	    } else
		draw = 1;

	    /* stroke co-ordinates in string coord system */
	    VSET( temp, (stroke/11) * 0.1 * scale + offset,
		  (ysign * (stroke%11)) * 0.1 * scale, 0 );
	    MAT4X3PNT( loc, mat, temp );
	    if ( draw )
		pdv_3cont( fp, loc );
	    else
		pdv_3move( fp, loc );
	}
    }
}