예제 #1
0
/*
 *			R T _ N U R B _ B E Z I E R
 *
 *  Given a single snurb, if it is in Bezier form,
 *  duplicate the snurb, and enqueue it on the bezier_hd list.
 *  If the original snurb is NOT in Bezier form,
 *  subdivide it a set of snurbs which are,
 *  each of which are enqueued on the bezier_hd list.
 *
 *  In either case, the original surface remains untouched.
 *
 *  Returns -
 *	0	Surface splitting was done.
 *	1	Original surface was Bezier, only a copy was done.
 */
int
rt_nurb_bezier(struct bu_list *bezier_hd, const struct face_g_snurb *orig_surf, struct resource *res)
{
    struct face_g_snurb	*s;
    int		dir;
    struct bu_list	todo;

    NMG_CK_SNURB(orig_surf);

    if ( (dir = rt_bez_check( orig_surf )) == -1)  {
	s = rt_nurb_scopy( orig_surf, res );
	BU_LIST_APPEND( bezier_hd, &s->l );
	return 1;	/* Was already Bezier, nothing done */
    }

    BU_LIST_INIT( &todo );
    rt_nurb_s_split( &todo, orig_surf, dir, res );

    while ( BU_LIST_WHILE( s, face_g_snurb, &todo ) )  {
	if ( (dir = rt_bez_check(s)) == -1)  {
	    /* This snurb is now a Bezier */
	    BU_LIST_DEQUEUE( &s->l );
	    BU_LIST_APPEND( bezier_hd, &s->l );
	} else {
	    /* Split, and keep going */
	    BU_LIST_DEQUEUE( &s->l );
	    rt_nurb_s_split( &todo, s, dir, res );
	    rt_nurb_free_snurb(s, res);
	}
    }
    return 0;		/* Bezier snurbs on bezier_hd list */
}
/**
 * If the order of the surface is linear either direction than
 * approximate it.
 */
void
rt_nurb_s_norm(struct face_g_snurb *srf, fastf_t u, fastf_t v, fastf_t *norm)
{
    struct face_g_snurb *usrf, *vsrf;
    point_t uvec, vvec;
    fastf_t p;
    fastf_t se[4], ue[4], ve[4];
    int i;

    /* Case (linear, lienar) find the normal from the polygon */
    if (srf->order[0] == 2 && srf->order[1] == 2) {
	/* Find the correct span to get the normal */
	rt_nurb_s_eval(srf, u, v, se);

	p = 0.0;
	for (i = 0; i < srf->u.k_size -1; i++) {
	    if (srf->u.knots[i] <= u
		&& u < srf->u.knots[i+1]) {
		p = srf->u.knots[i];

		if (ZERO(u - p))
		    p = srf->u.knots[i+1];
		if (ZERO(u - p) && i > 1)
		    p = srf->u.knots[i-1];
	    }
	}

	rt_nurb_s_eval(srf, p, v, ue);

	p = 0.0;
	for (i = 0; i < srf->v.k_size -1; i++) {
	    if (srf->v.knots[i] < v
		&& !ZERO(srf->v.knots[i+1])) {
		p = srf->v.knots[i];
		if (ZERO(v - p))
		    p = srf->v.knots[i+1];
		if (ZERO(v - p) && i > 1)
		    p = srf->v.knots[i-1];
	    }
	}

	rt_nurb_s_eval(srf, u, p, ve);

	if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
	    ue[0] = ue[0] / ue[3];
	    ue[1] = ue[1] / ue[3];
	    ue[2] = ue[2] / ue[3];
	    ue[3] = ue[3] / ue[3];

	    ve[0] = ve[0] / ve[3];
	    ve[1] = ve[1] / ve[3];
	    ve[2] = ve[2] / ve[3];
	    ve[3] = ve[3] / ve[3];

	}

	VSUB2(uvec, se, ue);
	VSUB2(vvec, se, ve);

	VCROSS(norm, uvec, vvec);
	VUNITIZE(norm);

	return;

    }
    /* Case (linear, > linear) Use the linear direction to approximate
     * the tangent to the surface
     */
    if (srf->order[0] == 2 && srf->order[1] > 2) {
	rt_nurb_s_eval(srf, u, v, se);

	p = 0.0;
	for (i = 0; i < srf->u.k_size -1; i++) {
	    if (srf->u.knots[i] <= u
		&& u < srf->u.knots[i+1]) {
		p = srf->u.knots[i];

		if (ZERO(u - p))
		    p = srf->u.knots[i+1];
		if (ZERO(u - p) && i > 1)
		    p = srf->u.knots[i-1];
	    }
	}

	rt_nurb_s_eval(srf, p, v, ue);

	vsrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);

	rt_nurb_s_eval(vsrf, u, v, ve);

	if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
	    fastf_t w, inv_w;

	    w = se[3];
	    inv_w = 1.0 / w;

	    ve[0] = (inv_w * ve[0]) -
		ve[3] / (w * w) * se[0];
	    ve[1] = (inv_w * ve[1]) -
		ve[3] / (w * w) * se[1];
	    ve[2] = (inv_w * ve[2]) -
		ve[3] / (w * w) * se[2];

	    ue[0] = ue[0] / ue[3];
	    ue[1] = ue[1] / ue[3];
	    ue[2] = ue[2] / ue[3];
	    ue[3] = ue[3] / ue[3];

	    se[0] = se[0] / se[3];
	    se[1] = se[1] / se[3];
	    se[2] = se[2] / se[3];
	    se[3] = se[3] / se[3];
	}

	VSUB2(uvec, se, ue);

	VCROSS(norm, uvec, ve);
	VUNITIZE(norm);

	rt_nurb_free_snurb(vsrf, (struct resource *)NULL);
	return;
    }
    if (srf->order[1] == 2 && srf->order[0] > 2) {
	rt_nurb_s_eval(srf, u, v, se);

	p = 0.0;
	for (i = 0; i < srf->v.k_size -1; i++) {
	    if (srf->v.knots[i] <= v
		&& v < srf->v.knots[i+1]) {
		p = srf->v.knots[i];

		if (ZERO(v - p))
		    p = srf->v.knots[i+1];
		if (ZERO(v - p) && i > 1)
		    p = srf->v.knots[i-1];
	    }
	}

	rt_nurb_s_eval(srf, u, p, ve);

	usrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);

	rt_nurb_s_eval(usrf, u, v, ue);

	if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
	    fastf_t w, inv_w;

	    w = se[3];
	    inv_w = 1.0 / w;

	    ue[0] = (inv_w * ue[0]) -
		ue[3] / (w * w) * se[0];
	    ue[1] = (inv_w * ue[1]) -
		ue[3] / (w * w) * se[1];
	    ue[2] = (inv_w * ue[2]) -
		ue[3] / (w * w) * se[2];

	    ve[0] = ve[0] / ve[3];
	    ve[1] = ve[1] / ve[3];
	    ve[2] = ve[2] / ve[3];
	    ve[3] = ve[3] / ve[3];

	    se[0] = se[0] / se[3];
	    se[1] = se[1] / se[3];
	    se[2] = se[2] / se[3];
	    se[3] = se[3] / se[3];
	}

	VSUB2(vvec, se, ve);

	VCROSS(norm, ue, vvec);
	VUNITIZE(norm);

	rt_nurb_free_snurb(usrf, (struct resource *)NULL);
	return;
    }

    /* Case Non Rational (order > 2, order > 2) */
    if (!RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {

	usrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);
	vsrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);

	rt_nurb_s_eval(usrf, u, v, ue);
	rt_nurb_s_eval(vsrf, u, v, ve);

	VCROSS(norm, ue, ve);
	VUNITIZE(norm);

	rt_nurb_free_snurb(usrf, (struct resource *)NULL);
	rt_nurb_free_snurb(vsrf, (struct resource *)NULL);

	return;
    }

    /* Case Rational (order > 2, order > 2) */
    if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
	fastf_t w, inv_w;
	vect_t unorm, vnorm;

	rt_nurb_s_eval(srf, u, v, se);

	usrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);
	vsrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);

	rt_nurb_s_eval(usrf, u, v, ue);

	rt_nurb_s_eval(vsrf, u, v, ve);

	w = se[3];
	inv_w = 1.0 / w;

	for (i = 0; i < 3; i++) {
	    unorm[i] = (inv_w * ue[i]) -
		ue[3] / (w*w) * se[i];
	    vnorm[i] = (inv_w * ve[i]) -
		ve[3] / (w*w) * se[i];
	}

	VCROSS(norm, unorm, vnorm);
	VUNITIZE(norm);

	rt_nurb_free_snurb(usrf, (struct resource *)NULL);
	rt_nurb_free_snurb(vsrf, (struct resource *)NULL);

	return;
    }
    return;
}
예제 #3
0
파일: nurb_ray.c 프로젝트: kanzure/brlcad
struct rt_nurb_uv_hit *
rt_nurb_intersect(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, double uv_tol, struct resource *res, struct bu_list *plist)
{
    struct rt_nurb_uv_hit * h;
    struct face_g_snurb * psrf,
	* osrf;
    int dir,
	sub;

    point_t vmin,
	vmax;
    fastf_t u[2],
	v[2];
    struct bu_list rni_plist;

    NMG_CK_SNURB(srf);

    h = (struct rt_nurb_uv_hit *) 0;
    if (plist == NULL) {
	plist = &rni_plist;
	BU_LIST_INIT(plist);
    }

    /* project the surface to a 2 dimensional problem */
    /* NOTE that this gives a single snurb back, NOT a list */
    psrf = rt_nurb_project_srf(srf, plane2, plane1, res);
    psrf->dir = 1;
    BU_LIST_APPEND(plist, &psrf->l);

    if (RT_G_DEBUG & DEBUG_SPLINE)
	rt_nurb_s_print("srf", psrf);

    /* This list starts out with only a single snurb, but more may be
     * added on as work progresses.
     */
    while (BU_LIST_WHILE(psrf, face_g_snurb, plist)) {
	int flat;

	BU_LIST_DEQUEUE(&psrf->l);
	NMG_CK_SNURB(psrf);
	sub = 0;
	flat = 0;
	dir = psrf->dir;

	while (!flat) {
	    fastf_t smin = 0.0, smax = 0.0;

	    sub++;
	    dir = (dir == 0)?1:0;	/* change direction */

	    if (RT_G_DEBUG & DEBUG_SPLINE)
		rt_nurb_s_print("psrf", psrf);

	    rt_nurb_pbound(psrf, vmin, vmax);

	    /* Check for origin to be included in the bounding box */
	    if (!(vmin[0] <= 0.0 && vmin[1] <= 0.0 &&
		  vmax[0] >= 0.0 && vmax[1] >= 0.0)) {
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("this srf doesn't include the origin\n");
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
		continue;
	    }

	    rt_nurb_clip_srf(psrf, dir, &smin, &smax);

	    if ((smax - smin) > .8) {
		struct rt_nurb_uv_hit *hp;

		/* Split surf, requeue both sub-surfs at head */
		/* New surfs will have same dir as arg, here */
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("splitting this surface\n");
		rt_nurb_s_split(plist, psrf, dir, res);
		rt_nurb_free_snurb(psrf, res);

		hp = rt_nurb_intersect(srf, plane1, plane2, uv_tol, res, plist);
		return hp;
	    }
	    if (smin > 1.0 || smax < 0.0) {
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("eliminating this surface (smin=%g, smax=%g)\n", smin, smax);
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
		continue;
	    }
	    if (dir == RT_NURB_SPLIT_ROW) {
		smin = (1.0 - smin) * psrf->u.knots[0] +
		    smin * psrf->u.knots[
			psrf->u.k_size -1];
		smax = (1.0 - smax) * psrf->u.knots[0] +
		    smax * psrf->u.knots[
			psrf->u.k_size -1];
	    } else {
		smin = (1.0 - smin) * psrf->v.knots[0] +
		    smin * psrf->v.knots[
			psrf->v.k_size -1];
		smax = (1.0 - smax) * psrf->v.knots[0] +
		    smax * psrf->v.knots[
			psrf->v.k_size -1];
	    }

	    osrf = psrf;
	    psrf = (struct face_g_snurb *) rt_nurb_region_from_srf(
		osrf, dir, smin, smax, res);

	    psrf->dir = dir;
	    rt_nurb_free_snurb(osrf, res);

	    if (RT_G_DEBUG & DEBUG_SPLINE) {
		bu_log("After call to rt_nurb_region_from_srf() (smin=%g, smax=%g)\n", smin, smax);
		rt_nurb_s_print("psrf", psrf);
	    }

	    u[0] = psrf->u.knots[0];
	    u[1] = psrf->u.knots[psrf->u.k_size -1];

	    v[0] = psrf->v.knots[0];
	    v[1] = psrf->v.knots[psrf->v.k_size -1];

	    if ((u[1] - u[0]) < uv_tol && (v[1] - v[0]) < uv_tol) {
		struct rt_nurb_uv_hit * hit;

		if (RT_G_DEBUG & DEBUG_SPLINE) {
		    fastf_t p1[4], p2[4];
		    int coords;
		    vect_t diff;

		    coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
		    rt_nurb_s_eval(srf, u[0], v[0], p1);
		    rt_nurb_s_eval(srf, u[1], v[1], p2);

		    if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
			fastf_t inv_w;

			inv_w = 1.0 / p1[coords-1];
			VSCALE(p1, p1, inv_w);

			inv_w = 1.0 / p2[coords-1];
			VSCALE(p2, p2, inv_w);
		    }

		    VSUB2(diff, p1, p2);
		    bu_log("Precision of hit point = %g (%f %f %f) <-> (%f %f %f)\n",
			   MAGNITUDE(diff), V3ARGS(p1), V3ARGS(p2));
		}

		hit = (struct rt_nurb_uv_hit *) bu_malloc(
		    sizeof(struct rt_nurb_uv_hit),  "hit");

		hit->next = (struct rt_nurb_uv_hit *)0;
		hit->sub = sub;
		hit->u = (u[0] + u[1])/2.0;
		hit->v = (v[0] + v[1])/2.0;

		if (h == (struct rt_nurb_uv_hit *)0)
		    h = hit;
		else {
		    hit->next = h;
		    h = hit;
		}
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
	    }
	    if ((u[1] - u[0]) > (v[1] - v[0]))
		dir = 1;
	    else dir = 0;
	}
    }

    return (struct rt_nurb_uv_hit *)h;
}
fastf_t
rt_nurb_par_edge(const struct face_g_snurb *srf, fastf_t epsilon)
{
    struct face_g_snurb * us, *vs, * uus, * vvs, *uvs;
    fastf_t d1, d2, d3;
    int i;
    fastf_t *pt;


    us = rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);
    vs = rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);
    uus = rt_nurb_s_diff(us, RT_NURB_SPLIT_ROW);
    vvs = rt_nurb_s_diff(vs, RT_NURB_SPLIT_COL);
    uvs = rt_nurb_s_diff(vs, RT_NURB_SPLIT_ROW);

    d1 = 0.0;
    d2 = 0.0;
    d3 = 0.0;

    pt = (fastf_t *) uus->ctl_points;

    /* Find the maximum value of the 2nd derivative in U */

    for (i = 0; i < uus->s_size[0] * uus->s_size[1]; i++) {
	fastf_t mag;

	mag = MAGNITUDE(pt);

	if (mag > d1) d1 = mag;

	pt += RT_NURB_EXTRACT_COORDS(uus->pt_type);

    }

    /* Find the maximum value of the partial derivative in UV */

    pt = (fastf_t *) uvs->ctl_points;

    for (i = 0; i < uvs->s_size[0] * uvs->s_size[1]; i++) {
	fastf_t mag;

	mag = MAGNITUDE(pt);

	if (mag > d2) d2 = mag;

	pt += RT_NURB_EXTRACT_COORDS(uvs->pt_type);

    }


    /* Find the maximum value of the 2nd derivative in V */
    pt = (fastf_t *) vvs->ctl_points;

    for (i = 0; i < vvs->s_size[0] * vvs->s_size[1]; i++) {
	fastf_t mag;

	mag = MAGNITUDE(pt);

	if (mag > d3) d3 = mag;

	pt += RT_NURB_EXTRACT_COORDS(vvs->pt_type);

    }

    /* free up storage */

    rt_nurb_free_snurb(us, (struct resource *)NULL);
    rt_nurb_free_snurb(vs, (struct resource *)NULL);
    rt_nurb_free_snurb(uus, (struct resource *)NULL);
    rt_nurb_free_snurb(vvs, (struct resource *)NULL);
    rt_nurb_free_snurb(uvs, (struct resource *)NULL);


    /* The paper uses the following to calculate the longest edge size
     * 1/2
     * 3.0 * ()
     * (2.0)
     * _________________________
     * (2.0 * (d1 + 2 D2 + d3)
     */

    return 3.0 * sqrt(epsilon / (2.0*(d1 + (2.0 * d2)+ d3)));
}
예제 #5
0
void
build_spline(char *name, int npts, double radius)
{
    struct face_g_snurb *bp;
    int i;
    int nv;
    int cur_kv;
    fastf_t *meshp;
    int col;
    vect_t point;

    /*
     * This spline will look like a cylinder.
     * In the mesh, the circular cross section will be presented
     * across the first row by filling in the 9 (NCOLS) columns.
     *
     * The U direction is across the first row,
     * and has NCOLS+order[U] positions, 12 in this instance.
     * The V direction is down the first column,
     * and has NROWS+order[V] positions.
     */
    bp = rt_nurb_new_snurb(3,	4,		/* u, v order */
			   N_CIRCLE_KNOTS,	npts+6,		/* u, v knot vector size */
			   npts+2,		NCOLS,		/* nrows, ncols */
			   RT_NURB_MAKE_PT_TYPE(4, 2, 1),
			   &rt_uniresource);

    /* Build the U knots */
    for (i=0; i<N_CIRCLE_KNOTS; i++)
	bp->u.knots[i] = circle_knots[i];

    /* Build the V knots */
    cur_kv = 0;		/* current knot value */
    nv = 0;			/* current knot subscript */
    for (i=0; i<4; i++)
	bp->v.knots[nv++] = cur_kv;
    cur_kv++;
    for (i=4; i<(npts+4-2); i++)
	bp->v.knots[nv++] = cur_kv++;
    for (i=0; i<4; i++)
	bp->v.knots[nv++] = cur_kv;

    /*
     * The control mesh is stored in row-major order,
     * which works out well for us, as a row is one
     * circular slice through the tube.  So we just
     * have to write down the slices, one after another.
     * The first and last "slice" are the center points that
     * create the end caps.
     */
    meshp = bp->ctl_points;

    /* Row 0 */
    for (col=0; col<9; col++) {
	*meshp++ = sample[0][X];
	*meshp++ = sample[0][Y];
	*meshp++ = sample[0][Z];
	*meshp++ = 1;
    }

    /* Rows 1..npts */
    for (i=0; i<npts; i++) {
	/* row = i; */
	VMOVE(point, sample[i]);
	for (col=0; col<9; col++) {
	    fastf_t h;

	    h = polyline[col*4+H];
	    *meshp++ = polyline[col*4+X]*radius + point[X]*h;
	    *meshp++ = polyline[col*4+Y]*radius + point[Y]*h;
	    *meshp++ = polyline[col*4+Z]*radius + point[Z]*h;
	    *meshp++ = h;
	}
    }

    /* Row npts+1 */
    for (col=0; col<9; col++) {
	*meshp++ = sample[npts-1][X];
	*meshp++ = sample[npts-1][Y];
	*meshp++ = sample[npts-1][Z];
	*meshp++ = 1;
    }

    {
	struct face_g_snurb *surfp[2];
	surfp[0] = bp;
	surfp[1] = NULL;
	mk_bspline(outfp, name, surfp);
    }

    rt_nurb_free_snurb(bp, &rt_uniresource);
}