Ejemplo n.º 1
0
/**
 * Check to see if the curve control polygon wanders outside the
 * parametric range given.  This is useful if a trimming curve
 * control polygon is outside but the evaluated curve is not. We will
 * want to refine the curve so that it lies within the range;
 * otherwise it breaks the surface evaluation.
 */
int
rt_nurb_crv_in_range(struct edge_g_cnurb *crv, fastf_t u_min, fastf_t u_max, fastf_t v_min, fastf_t v_max)
{
    point_t eval;
    fastf_t *pts;
    int coords = RT_NURB_EXTRACT_COORDS(crv->pt_type);
    int rat = RT_NURB_IS_PT_RATIONAL(crv->pt_type);
    int i;

    pts = &crv->ctl_points[0];

    for (i = 0; i < crv->c_size; i++) {
	if (rat) {
	    eval[0] = pts[0] / pts[2];
	    eval[1] = pts[1] / pts[2];
	    eval[2] = 1;
	} else {
	    eval[0] = pts[0];
	    eval[1] = pts[1];
	    eval[2] = 1;
	}

	if (eval[0] < u_min || eval[0] > u_max)
	    return 0;

	if (eval[1] < v_min || eval[1] > v_max)
	    return 0;

	pts += coords;
    }
    return 1;
}
Ejemplo n.º 2
0
/**
 * Algorithm -
 *
 * From the four corners of the surface, return the two parts split by
 * the diagonal from the first and third corner point making sure
 * Homogeneous points are divided.
 */
struct rt_nurb_poly *
rt_nurb_to_poly(struct face_g_snurb *srf)
{
    int coords = srf->pt_type;
    fastf_t * p1, *p2, *p3, *p4;
    fastf_t uv1[2], uv2[2], uv3[2], uv4[2];
    struct rt_nurb_poly *p, *p_head;

    /* Extract the four corners from the mesh */

    p1 = srf->ctl_points;
    p2 = srf->ctl_points + coords * srf->s_size[1];
    p3 = srf->ctl_points + (coords * srf->s_size[1] *
			    (srf->s_size[0] - 1)) +
	((srf->s_size[1] - 1) * coords);
    p4 = srf->ctl_points + (coords * srf->s_size[1] *
			    (srf->s_size[0] - 1));

    /* If the point is rational then divide out the w component */
    if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
	int w_index;

	if (RT_NURB_EXTRACT_PT_TYPE(srf->pt_type) == RT_NURB_PT_XY)
	    w_index = 2;
	else if (RT_NURB_EXTRACT_PT_TYPE(srf->pt_type) == RT_NURB_PT_UV)
	    w_index = 2;
	else if (RT_NURB_EXTRACT_PT_TYPE(srf->pt_type) == RT_NURB_PT_XYZ)
	    w_index = 3;
	else /* assume the forth coordinate */
	    w_index = 3;

	p1[0] = p1[0] / p1[w_index];
	p2[0] = p2[0] / p1[w_index];
	p3[0] = p3[0] / p1[w_index];
	p4[0] = p4[0] / p1[w_index];
    }

    uv1[0] = srf->u.knots[0];
    uv1[1] = srf->v.knots[0];

    uv2[0] = srf->u.knots[srf->u.k_size -1];
    uv2[1] = srf->v.knots[0];

    uv3[0] = srf->u.knots[srf->u.k_size -1];
    uv3[1] = srf->v.knots[srf->v.k_size -1];

    uv4[0] = srf->u.knots[0];
    uv4[1] = srf->v.knots[srf->v.k_size -1];

    p = rt_nurb_mk_poly(p1, p2, p3, uv1, uv2, uv3);
    p_head = p;
    p = rt_nurb_mk_poly(p3, p4, p1, uv3, uv4, uv1);
    p->next = p_head;
    p_head = p;

    return p_head;
}
Ejemplo n.º 3
0
int
rt_nurb_uv_dist(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
{

    fastf_t dist;
    fastf_t * ptr;
    int coords;
    int rat;
    fastf_t u2, v2;

    ptr = trim->ctl_points;
    coords = RT_NURB_EXTRACT_COORDS(trim->pt_type);
    rat = RT_NURB_IS_PT_RATIONAL(trim->pt_type);

    u2 = 0.0;
    v2 = 0.0;

    if ( rat )
    {
	u2 = ptr[0]/ptr[2] - u; u2 *= u2;
	v2 = ptr[1]/ptr[2] - v; v2 *= v2;
    }
    else
    {
	u2 = ptr[0] - u; u2 *= u2;
	v2 = ptr[1] - v; v2 *= v2;
    }

    dist = sqrt( u2 + v2);
    if ( NEAR_ZERO( dist, 1.0e-4) )
	return TRIM_ON;

    ptr = trim->ctl_points + coords * (trim->c_size -1);

    u2 = 0.0;
    v2 = 0.0;

    if ( rat )
    {
	u2 = ptr[0]/ptr[2] - u; u2 *= u2;
	v2 = ptr[1]/ptr[2] - v; v2 *= v2;
    }
    else
    {
	u2 = ptr[0] - u; u2 *= u2;
	v2 = ptr[1] - v; v2 *= v2;
    }

    dist = sqrt( u2 + v2);
    if ( NEAR_ZERO( dist, 1.0e-4) )
	return TRIM_ON;

    return TRIM_OUT;

}
Ejemplo n.º 4
0
int
rt_trim_case(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
{
    int quadrant;
    int qstats;
    fastf_t * pts;
    int coords, rat;
    int i;

    qstats = 0;

    coords = RT_NURB_EXTRACT_COORDS(trim->pt_type);
    pts = trim->ctl_points;
    rat = RT_NURB_IS_PT_RATIONAL( trim->pt_type );

    /* Handle rational specially since we need to divide the rational
     * portion.
     */

    if ( rat )
	for ( i = 0; i < trim->c_size; i++)
	{
	    if (pts[0]/pts[2] > u )
		quadrant = (pts[1]/pts[2] >= v)? QUAD1:QUAD4;
	    else
		quadrant = (pts[1]/pts[2] >= v)? QUAD2:QUAD3;

	    qstats |= (1 << quadrant);
	    pts += coords;
	}
    else
	for ( i = 0; i < trim->c_size; i++)
	{
	    if (pts[0] > u )
		quadrant = (pts[1] >= v)? QUAD1:QUAD4;
	    else
		quadrant = (pts[1] >= v)? QUAD2:QUAD3;

	    qstats |= (1 << quadrant);
	    pts += coords;
	}

    return quad_table[qstats];	/* return the special case of the curve */
}
Ejemplo n.º 5
0
/* Process Case B curves.
 *
 * If the two endpoints of the curve lie in different quadrants than
 * the axis crosses the curve an odd number of times (TRIM_IN). Otherwise
 * the curve crosses the u, v axis a even number of times (TRIM_OUT).
 * No further processing is required.
 */
int
rt_process_caseb(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
{
    int q1, q2;
    fastf_t * pts;
    int rat;

    rat = RT_NURB_IS_PT_RATIONAL( trim->pt_type );

    pts = trim->ctl_points;

    if ( rat)
    {
	if ( pts[0]/pts[2] > u) q1 = (pts[1]/pts[2] >= v)?QUAD1:QUAD4;
	else 		 q1 = (pts[1]/pts[2] >= v)?QUAD2:QUAD3;


	pts = trim->ctl_points + RT_NURB_EXTRACT_COORDS(trim->pt_type) *
	    (trim->c_size -1);
	if ( pts[0]/pts[2] > u) q2 = (pts[1]/pts[2] >= v)?QUAD1:QUAD4;
	else 		 q2 = (pts[1]/pts[2] >= v)?QUAD2:QUAD3;

    } else
    {
	if ( pts[0] > u) q1 = (pts[1] >= v)?QUAD1:QUAD4;
	else 		 q1 = (pts[1] >= v)?QUAD2:QUAD3;


	pts = trim->ctl_points +
	    RT_NURB_EXTRACT_COORDS(trim->pt_type) 	*
	    (trim->c_size -1);
	if ( pts[0] > u) q2 = (pts[1] >= v)?QUAD1:QUAD4;
	else 		 q2 = (pts[1] >= v)?QUAD2:QUAD3;
    }

    if ( q1 != q2 )
	return TRIM_IN;
    else
	return TRIM_OUT;

}
void
rt_nurb_print_pt_type(int c)
{
    int rat;

    rat = RT_NURB_IS_PT_RATIONAL(c);

    if (RT_NURB_EXTRACT_PT_TYPE(c) == RT_NURB_PT_XY)
	bu_log("Point Type = RT_NURB_PT_XY");
    else
	if (RT_NURB_EXTRACT_PT_TYPE(c) == RT_NURB_PT_XYZ)
	    bu_log("Point Type = RT_NURB_PT_XYX");
	else
	    if (RT_NURB_EXTRACT_PT_TYPE(c) == RT_NURB_PT_UV)
		bu_log("Point Type = RT_NURB_PT_UV");

    if (rat)
	bu_log("W\n");
    else
	bu_log("\n");
}
Ejemplo n.º 7
0
fastf_t
rt_trim_line_pt_dist(struct _interior_line *l, fastf_t *pt, int pt_type)
{
    fastf_t h;
    int h_flag;

    h_flag = RT_NURB_IS_PT_RATIONAL(pt_type);

    if ( l->axis == 0)
    {
	if ( h_flag) h = (pt[1] / pt[2] - l->o_dist) * pt[2]; /* pt[2] is weight */
	else h = pt[1] - l->o_dist;

    } else
    {
	if ( h_flag) h = (pt[0] / pt[2] - l->o_dist) * pt[2];
	else h = pt[0] - l->o_dist;

    }

    return h;
}
Ejemplo n.º 8
0
/**
 * Calculates the bounding Right Parallel Piped (RPP) of the NURB
 * surface, and returns the minimum and maximum points of the surface.
 */
int
rt_nurb_s_bound(struct face_g_snurb *srf, fastf_t *bmin, fastf_t *bmax)
{
    register fastf_t *p_ptr;	/* Mesh pointer */
    register int coords;		/* Elements per vector */
    int i;
    int rat;

    VSETALL(bmin, INFINITY);
    VSETALL(bmax, -INFINITY);

    if (srf == (struct face_g_snurb *)0) {
	bu_log("nurb_s_bound:  NULL surface\n");
	return -1;		/* BAD */
    }

    p_ptr = srf->ctl_points;
    coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
    rat =    RT_NURB_IS_PT_RATIONAL(srf->pt_type);

    for (i = (srf->s_size[RT_NURB_SPLIT_ROW] *
	      srf->s_size[RT_NURB_SPLIT_COL]); i > 0; i--) {
	if (!rat) {
	    VMINMAX(bmin, bmax, p_ptr);
	} else if (rat) {
	    point_t tmp_pt;
	    if (ZERO(p_ptr[H])) {
		HPRINT("mesh point", p_ptr);
		bu_log("nurb_s_bound:  H too small\n");
	    } else {
		HDIVIDE(tmp_pt, p_ptr);
		VMINMAX(bmin, bmax, tmp_pt);
	    }
	}
	p_ptr += coords;
    }
    return 0;	/* OK */
}
/**
 * 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;
}
Ejemplo n.º 10
0
struct face_g_snurb *
rt_nurb_project_srf(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, struct resource *res)
{

    register struct face_g_snurb *psrf;
    register fastf_t *mp1, *mp2;
    int n_pt_type;
    int rational;
    int i;

    if (RTG.NMG_debug & DEBUG_RT_ISECT)
	bu_log("rt_nurb_project_srf: projecting surface, planes = (%g %g %g %g) (%g %g %g %g)\n",
	       V4ARGS(plane1), V4ARGS(plane2));

    rational = RT_NURB_IS_PT_RATIONAL(srf->pt_type);

    n_pt_type = RT_NURB_MAKE_PT_TYPE(2, RT_NURB_PT_PROJ, 0);

    psrf = (struct face_g_snurb *) rt_nurb_new_snurb(srf->order[0], srf->order[1],
						     srf->u.k_size, srf->v.k_size,
						     srf->s_size[0], srf->s_size[1], n_pt_type, res);

    psrf->dir = RT_NURB_SPLIT_COL;

    for (i = 0; i < srf->u.k_size; i++) {
	psrf->u.knots[i] = srf->u.knots[i];
    }

    for (i = 0; i < srf->v.k_size; i++) {
	psrf->v.knots[i] = srf->v.knots[i];
    }

    mp1 = srf->ctl_points;
    mp2 = psrf->ctl_points;

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

	if (rational) {
	    mp2[0] = (mp1[0] / mp1[3] * plane1[0] +
		      mp1[1] / mp1[3] * plane1[1] +
		      mp1[2] / mp1[3] * plane1[2] - plane1[3]) *
		mp1[3];
	    mp2[1] = (mp1[0] / mp1[3] * plane2[0] +
		      mp1[1] / mp1[3] * plane2[1] +
		      mp1[2] / mp1[3] * plane2[2] - plane2[3]) *
		mp1[3];
	} else {
	    mp2[0] = mp1[0] * plane1[0] + mp1[1] * plane1[1] +
		mp1[2] * plane1[2] - plane1[3];
	    mp2[1] = mp1[0] * plane2[0] + mp1[1] * plane2[1] +
		mp1[2] * plane2[2] - plane2[3];
	}

	if (RTG.NMG_debug & DEBUG_RT_ISECT) {
	    if (rational)
		bu_log("\tmesh pt (%g %g %g %g), becomes (%g %g)\n", V4ARGS(mp1), mp2[0], mp2[1]);
	    else
		bu_log("\tmesh pt (%g %g %g), becomes (%g %g)\n", V3ARGS(mp1), mp2[0], mp2[1]);
	}

	mp1 += RT_NURB_EXTRACT_COORDS(srf->pt_type);
	mp2 += RT_NURB_EXTRACT_COORDS(psrf->pt_type);
    }

    return (struct face_g_snurb *) psrf;
}
Ejemplo n.º 11
0
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;
}
int
rt_nurb_s_flat(struct face_g_snurb *srf, fastf_t epsilon)

    /* Epsilon value for flatness testing */
{
    register fastf_t max_row_dist;
    register fastf_t max_col_dist;
    register fastf_t max_dist;
    int dir;
    fastf_t * mesh_ptr = srf->ctl_points;
    int coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
    int j, i, k;
    int mesh_elt;
    vect_t p1, p2, p3, p4, v1, v2, v3;
    vect_t nrm;
    fastf_t nrmln;
    fastf_t dist;
    fastf_t * crv;
    int otherdir;

    dir = srf->dir;

    otherdir = (dir == RT_NURB_SPLIT_ROW) ? RT_NURB_SPLIT_COL : RT_NURB_SPLIT_ROW;

    max_row_dist = max_col_dist = -INFINITY;

    crv = (fastf_t *) bu_malloc(sizeof(fastf_t) *
				RT_NURB_EXTRACT_COORDS(srf->pt_type) * srf->s_size[1],
				"rt_nurb_s_flat: crv");

    /* Test Row and RT_NURB_SPLIT_COL curves for flatness, If a curve
     * is not flat than get distance to line
     */

    /* Test Row Curves */

    for (i = 0; i < (srf->s_size[0]); i++) {
	fastf_t rdist;
	for (j = 0;
	     j < (srf->s_size[1] *
		  RT_NURB_EXTRACT_COORDS(srf->pt_type));
	     j++)
	    crv[j] = *mesh_ptr++;

	rdist = rt_nurb_crv_flat(crv, srf->s_size[1],
				 srf->pt_type);
	max_row_dist = FMAX(max_row_dist, rdist);
    }

    bu_free((char *)crv, "rt_nurb_s_flat: crv");

    crv = (fastf_t *) bu_malloc(sizeof(fastf_t) *
				RT_NURB_EXTRACT_COORDS(srf->pt_type) *
				srf->s_size[0], 	"rt_nurb_s_flat: crv");

    for (i = 0; i < (coords * srf->s_size[1]); i += coords) {
	fastf_t rdist;

	for (j = 0; j < (srf->s_size[0]); j++) {
	    mesh_elt =
		(j * (srf->s_size[1] * coords)) + i;

	    for (k = 0; k < coords; k++)
		crv[j * coords + k] =
		    srf->ctl_points[mesh_elt + k];
	}

	rdist = rt_nurb_crv_flat(crv,
				 srf->s_size[0], srf->pt_type);

	max_col_dist = FMAX(max_col_dist, rdist);
    }

    bu_free((char *)crv, "rt_nurb_s_flat: crv");

    max_dist = FMAX(max_row_dist, max_col_dist);

    if (max_dist > epsilon) {
	if (max_row_dist > max_col_dist)
	    return RT_NURB_SPLIT_ROW;
	else
	    return RT_NURB_SPLIT_COL;
    }

    /* Test the corners to see if they lie in a plane. */

    /*
     * Extract the four corners and put a plane through three of them
     * and see how far the fourth is to the plane.
     */

    mesh_ptr = srf->ctl_points;

    if (!RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {

	VMOVE(p1, mesh_ptr);
	VMOVE(p2,
	      (mesh_ptr + (srf->s_size[1] - 1) * coords));
	VMOVE(p3,
	      (mesh_ptr +
	       ((srf->s_size[1] *
		 (srf->s_size[0] - 1)) +
		(srf->s_size[1] - 1)) * coords));

	VMOVE(p4,
	      (mesh_ptr +
	       (srf->s_size[1] *
		(srf->s_size[0] - 1)) * coords));
    } else {
	hvect_t h1, h2, h3, h4;
	int offset;

	HMOVE(h1, mesh_ptr);
	HDIVIDE(p1, h1);

	offset = (srf->s_size[1] - 1) * coords;
	HMOVE(h2, mesh_ptr + offset);
	HDIVIDE(p2, h2);

	offset =
	    ((srf->s_size[1] *
	      (srf->s_size[0] - 1)) +
	     (srf->s_size[1] - 1)) * coords;
	HMOVE(h3, mesh_ptr + offset);
	HDIVIDE(p3, h3);

	offset =
	    (srf->s_size[1] *
	     (srf->s_size[0] - 1)) * coords;
	HMOVE(h4, mesh_ptr + offset);
	HDIVIDE(p4, h4);
    }

    VSUB2(v1, p2, p1);
    VSUB2(v2, p3, p1);

    VCROSS(nrm, v1, v2);

    nrmln = MAGNITUDE(nrm);
    if (nrmln < 0.0001)			/* XXX Why this constant? */
	return RT_NURB_SPLIT_FLAT;

    VSUB2(v3, p4, p1);

    dist = fabs(VDOT(v3, nrm)) / nrmln;

    if (dist > epsilon)
	return otherdir;

    return RT_NURB_SPLIT_FLAT;		/* Must be flat */

}
fastf_t
rt_nurb_crv_flat(fastf_t *crv, int size, int pt_type)
{
    point_t p1, p2;
    vect_t ln;
    int i;
    fastf_t dist;
    fastf_t max_dist;
    fastf_t length;
    fastf_t * c_ptr;
    vect_t testv, xp;
    hvect_t h1, h2;
    int coords;
    int rational;

    coords = RT_NURB_EXTRACT_COORDS(pt_type);
    rational = RT_NURB_IS_PT_RATIONAL(pt_type);
    max_dist = -INFINITY;

    if (!rational) {
	VMOVE(p1, crv);
    } else {
	HMOVE(h1, crv);
	HDIVIDE(p1, h1);
    }

    length = 0.0;

    /*
     * loop through all of the points until a line is found which may
     * not be the end pts of the curve if the endpoints are the same.
     */
    for (i = size - 1; (i > 0) && length < SQRT_SMALL_FASTF; i--) {
	if (!rational) {
	    VMOVE(p2, (crv + (i * coords)));
	} else {
	    HMOVE(h2, (crv + (i * coords)));
	    HDIVIDE(p2, h2);
	}

	VSUB2(ln, p1, p2);
	length = MAGNITUDE(ln);
    }


    if (length >= SQRT_SMALL_FASTF) {
	VSCALE(ln, ln, 1.0 / length);
	c_ptr = crv + coords;

	for (i = 1; i < size; i++) {
	    if (!rational) {
		VSUB2(testv, p1, c_ptr);
	    } else {
		HDIVIDE(h2, c_ptr);
		VSUB2(testv, p1, h2);
	    }

	    VCROSS(xp, testv, ln);
	    dist = MAGNITUDE(xp);
	    max_dist = FMAX(max_dist, dist);
	    c_ptr += coords;
	}
    }
    return max_dist;
}
Ejemplo n.º 14
0
int
nmg_uv_in_lu(const fastf_t u, const fastf_t v, const struct loopuse *lu)
{
    struct edgeuse *eu;
    int crossings=0;

    NMG_CK_LOOPUSE( lu );

    if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
	return( 0 );

    for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
    {
	struct edge_g_cnurb *eg;

	if ( !eu->g.magic_p )
	{
	    bu_log( "nmg_uv_in_lu: eu (x%x) has no geometry!!!\n", eu );
	    bu_bomb( "nmg_uv_in_lu: eu has no geometry!!!\n" );
	}

	if ( *eu->g.magic_p != NMG_EDGE_G_CNURB_MAGIC )
	{
	    bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing eu (x%x) that is not CNURB!!!!\n",
		    lu, eu );
	    bu_bomb( "nmg_uv_in_lu: Called with lu containing eu that is not CNURB!!!\n" );
	}

	eg = eu->g.cnurb_p;

	if ( eg->order <= 0 )
	{
	    struct vertexuse *vu1, *vu2;
	    struct vertexuse_a_cnurb *vua1, *vua2;
	    point_t uv1, uv2;
	    fastf_t slope, intersept;
	    fastf_t u_on_curve;

	    vu1 = eu->vu_p;
	    vu2 = eu->eumate_p->vu_p;

	    if ( !vu1->a.magic_p || !vu2->a.magic_p )
	    {
		bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu with no attribute!!!!\n",
			lu );
		bu_bomb( "nmg_uv_in_lu: Called with lu containing vu with no attribute!!!\n" );
	    }

	    if ( *vu1->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC ||
		 *vu2->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
	    {
		bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu that is not CNURB!!!!\n",
			lu );
		bu_bomb( "nmg_uv_in_lu: Called with lu containing vu that is not CNURB!!!\n" );
	    }

	    vua1 = vu1->a.cnurb_p;
	    vua2 = vu2->a.cnurb_p;

	    VMOVE( uv1, vua1->param );
	    VMOVE( uv2, vua2->param );

	    if ( RT_NURB_IS_PT_RATIONAL( eg->pt_type ) )
	    {
		uv1[0] /= uv1[2];
		uv1[1] /= uv1[2];
		uv2[0] /= uv2[2];
		uv2[1] /= uv2[2];
	    }

	    if ( uv1[1] < v && uv2[1] < v )
		continue;
	    if ( uv1[1] > v && uv2[1] > v )
		continue;
	    if ( uv1[0] <= u && uv2[0] <= u )
		continue;
	    if ( uv1[0] == uv2[0] )
	    {
		if ( (uv1[1] <= v && uv2[1] >= v) ||
		     (uv2[1] <= v && uv1[1] >= v) )
		    crossings++;

		continue;
	    }

	    /* need to calculate intersection */
	    slope = (uv1[1] - uv2[1])/(uv1[0] - uv2[0]);
	    intersept = uv1[1] - slope * uv1[0];
	    u_on_curve = (v - intersept)/slope;
	    if ( u_on_curve > u )
		crossings++;
	}
	else
	    crossings += rt_uv_in_trim( eg, u, v );
    }

    if ( crossings & 01 )
	return( 1 );
    else
	return( 0 );
}