struct edge_g_cnurb *
rt_nurb_c_diff(const struct edge_g_cnurb *crv)
{

    struct edge_g_cnurb *ncrv;
    fastf_t * opts, *npts;
    int i;

    NMG_CK_CNURB(crv);

    ncrv = (struct edge_g_cnurb *) rt_nurb_new_cnurb(crv->order - 1,
						     crv->k.k_size - 2, crv->c_size - 1,
						     crv->pt_type);

    opts = (fastf_t *) crv->ctl_points;
    npts = (fastf_t *) ncrv->ctl_points;

    rt_nurb_mesh_diff(crv->order, opts, npts, crv->k.knots,
		      RT_NURB_EXTRACT_COORDS(crv->pt_type),
		      RT_NURB_EXTRACT_COORDS(ncrv->pt_type),
		      crv->c_size, crv->pt_type);

    for (i = 1; i < crv->k.k_size - 1; i++)
	ncrv->k.knots[ i - 1] = crv->k.knots[i];

    return ncrv;

}
void
rt_nurb_c_print(const struct edge_g_cnurb *crv)
{
    register fastf_t * ptr;
    int i, j;

    NMG_CK_CNURB(crv);
    bu_log("curve = {\n");
    bu_log("\tOrder = %d\n", crv->order);
    bu_log("\tKnot Vector = {\n\t\t");

    for (i = 0; i < crv->k.k_size; i++)
	bu_log("%10.8f ", crv->k.knots[i]);

    bu_log("\n\t}\n");
    bu_log("\t");
    rt_nurb_print_pt_type(crv->pt_type);
    bu_log("\tmesh = {\n");
    for (ptr = &crv->ctl_points[0], i= 0;
	 i < crv->c_size; i++, ptr += RT_NURB_EXTRACT_COORDS(crv->pt_type))
    {
	bu_log("\t\t");
	for (j = 0; j < RT_NURB_EXTRACT_COORDS(crv->pt_type); j++)
	    bu_log("%4.5f\t", ptr[j]);
	bu_log("\n");

    }
    bu_log("\t}\n}\n");


}
示例#3
0
文件: nmg_copy.c 项目: kanzure/brlcad
static struct edge_g_cnurb *
nmg_construct_edge_g_cnurb(const struct edge_g_cnurb *original, void **structArray)
{
    struct edge_g_cnurb *ret;

    NMG_GETSTRUCT(ret, edge_g_cnurb);

    ret->l.magic = NMG_EDGE_G_CNURB_MAGIC;

    BU_LIST_INIT(&ret->eu_hd2);

    ret->order = original->order;

    ret->k.magic  = NMG_KNOT_VECTOR_MAGIC;
    ret->k.k_size = original->k.k_size;
    ret->k.knots = (fastf_t *)bu_malloc(ret->k.k_size * sizeof(fastf_t), "nmg_construct_edge_g_cnurb(): k.knots");
    memcpy(ret->k.knots, original->k.knots, ret->k.k_size * sizeof(fastf_t));

    ret->c_size     = original->c_size;
    ret->pt_type    = original->pt_type;
    ret->ctl_points = (fastf_t *)bu_malloc(ret->c_size * RT_NURB_EXTRACT_COORDS(ret->pt_type) * sizeof(fastf_t),
					   "nmg_construct_edge_g_cnurb(): ctl_points");
    memcpy(ret->ctl_points, original->ctl_points, ret->c_size * RT_NURB_EXTRACT_COORDS(ret->pt_type) * sizeof(fastf_t));

    ret->index              = original->index;
    structArray[ret->index] = ret;

    return ret;
}
示例#4
0
/**
 * rt_nurb_c_xsplit()
 *
 * Split a NURB curve by inserting a multiple knot and return the
 * result of the two curves.
 *
 * Algorithm:
 *
 * Insert a multiple knot of the curve order. A parameter is give for
 * the knot value for which the curve will be split.
 */
struct edge_g_cnurb *
rt_nurb_c_xsplit(struct edge_g_cnurb *crv, fastf_t param)
{
    struct knot_vector new_kv;
    struct oslo_mat * oslo;
    int k_index;
    struct edge_g_cnurb * crv1, * crv2;
    int coords;

    NMG_CK_CNURB(crv);

    coords = RT_NURB_EXTRACT_COORDS(crv->pt_type),

	k_index = crv->order;
    rt_nurb_kvmult(&new_kv, &crv->k, crv->order, param, (struct resource *)NULL);

    oslo = (struct oslo_mat *)
	rt_nurb_calc_oslo(crv->order, &crv->k, &new_kv, (struct resource *)NULL);

    GET_CNURB(crv1);
    crv1->order  = crv->order;
    rt_nurb_kvextract(&crv1->k, &new_kv, 0, k_index + crv->order, (struct resource *)NULL);
    crv1->pt_type = crv->pt_type;
    crv1->c_size = crv1->k.k_size - crv1->order;
    crv1->ctl_points = (fastf_t *)
	bu_malloc(sizeof(fastf_t) * crv1->c_size *
		  RT_NURB_EXTRACT_COORDS(crv1->pt_type),
		  "rt_nurb_c_xsplit: crv1 control points");

    GET_CNURB(crv2);
    crv2->order  = crv->order;
    rt_nurb_kvextract(&crv2->k, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
    crv2->pt_type = crv->pt_type;
    crv2->c_size = crv2->k.k_size - crv2->order;
    crv2->ctl_points = (fastf_t *)
	bu_malloc(sizeof(fastf_t) * crv2->c_size *
		  RT_NURB_EXTRACT_COORDS(crv2->pt_type),
		  "rt_nurb_c_xsplit: crv2 row mesh control points");

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv1->ctl_points,
		     coords, coords, 0, k_index, crv->pt_type);

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv2->ctl_points,
		     coords, coords, k_index, new_kv.k_size - crv2->order,
		     crv2->pt_type);

    rt_nurb_free_oslo(oslo, (struct resource *)NULL);

    bu_free((char *) new_kv.knots, "rt_nurb_c_xsplit: new_kv.knots");

    BU_LIST_APPEND(&crv1->l, &crv2->l);
    return crv1;
}
/**
 * Create a place holder for a nurb surface.
 */
struct face_g_snurb *
rt_nurb_new_snurb(int u_order, int v_order, int n_u, int n_v, int n_rows, int n_cols, int pt_type, struct resource *res)
{
    register struct face_g_snurb * srf;
    int pnum;

    if (res) RT_CK_RESOURCE(res);

    GET_SNURB(srf);
    srf->order[0] = u_order;
    srf->order[1] = v_order;
    srf->dir = RT_NURB_SPLIT_ROW;

    srf->u.k_size = n_u;
    srf->v.k_size = n_v;
    srf->s_size[0] = n_rows;
    srf->s_size[1] = n_cols;
    srf->pt_type = pt_type;

    pnum = sizeof (fastf_t) * n_rows * n_cols * RT_NURB_EXTRACT_COORDS(pt_type);

    srf->u.knots = (fastf_t *) bu_malloc (
	n_u * sizeof (fastf_t), "rt_nurb_new_snurb: u kv knot values");
    srf->v.knots = (fastf_t *) bu_malloc (
	n_v * sizeof (fastf_t), "rt_nurb_new_snurb: v kv knot values");
    srf->ctl_points = (fastf_t *) bu_malloc(
	pnum, "rt_nurb_new_snurb: control mesh points");

    return srf;
}
示例#6
0
文件: nurb_ray.c 项目: kanzure/brlcad
void
rt_nurb_pbound(struct face_g_snurb *srf, fastf_t *vmin, fastf_t *vmax)
{
    register fastf_t * ptr;
    register int coords;
    int i;

    vmin[0] = vmin[1] = vmin[2] = INFINITY;
    vmax[0] = vmax[1] = vmax[2] = -INFINITY;

    ptr = srf->ctl_points;

    coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);

    for (i = (srf->s_size[RT_NURB_SPLIT_ROW] *
	      srf->s_size[RT_NURB_SPLIT_COL]); i > 0; i--) {
	V_MIN((vmin[0]), (ptr[0]));
	V_MAX((vmax[0]), (ptr[0]));

	V_MIN((vmin[1]), (ptr[1]));
	V_MAX((vmax[1]), (ptr[1]));

	ptr += coords;
    }
}
示例#7
0
struct face_g_snurb *
rt_nurb_scopy(const struct face_g_snurb *srf, struct resource *res)
{
    register struct face_g_snurb * n;
    int i;

    NMG_CK_SNURB(srf);

    n = (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],
						  srf->pt_type, res);

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

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

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

	n->ctl_points[i] = srf->ctl_points[i];
    }

    return (struct face_g_snurb *) n;
}
示例#8
0
struct edge_g_cnurb *
rt_nurb_c_refine(const struct edge_g_cnurb *crv, struct knot_vector *kv)
{
    struct oslo_mat * oslo;
    struct edge_g_cnurb * new_crv;
    int i, coords;

    NMG_CK_CNURB(crv);

    coords = RT_NURB_EXTRACT_COORDS(crv->pt_type);

    new_crv = (struct edge_g_cnurb *) rt_nurb_new_cnurb(
	crv->order, kv->k_size, kv->k_size - crv->order,
	crv->pt_type);

    oslo = (struct oslo_mat *) rt_nurb_calc_oslo(
	crv->order, &crv->k, kv, (struct resource *)NULL);

    rt_nurb_map_oslo(oslo, crv->ctl_points,
		     new_crv->ctl_points,
		     coords, coords, 0,
		     kv->k_size - new_crv->order,
		     new_crv->pt_type);

    new_crv->k.k_size = kv->k_size;

    for (i = 0; i < kv->k_size; i++)
	new_crv->k.knots[i] = kv->knots[i];

    rt_nurb_free_oslo(oslo, (struct resource *)NULL);

    return new_crv;
}
示例#9
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;
}
/**
 * Calculate the maximum edge length (in parameter space) that will
 * keep the curve approximation within epsilon of the true curve
 *
 * This is a temporary guess until legitimate code can be found
 *
 * returns:
 * -1.0 if the curve is a straight line
 * maximum parameter increment otherwise
 */
fastf_t
rt_cnurb_par_edge(const struct edge_g_cnurb *crv, fastf_t epsilon)
{
    struct edge_g_cnurb *d1, *d2;
    fastf_t der2[5], t, *pt;
    fastf_t num_coord_factor, final_t;
    int num_coords;
    int i, j;

    if (crv->order < 3)
	return -1.0;

    num_coords = RT_NURB_EXTRACT_COORDS(crv->pt_type);
    if (num_coords > 5) {
	bu_log("ERROR: rt_cnurb_par_edge() cannot handle curves with more than 5 coordinates (curve has %d)\n",
	       num_coords);
	bu_bomb("ERROR: rt_cnurb_par_edge() cannot handle curves with more than 5 coordinates\n");
    }

    for (i=0; i<num_coords; i++) {
	der2[i] = 0.0;
    }

    final_t = MAX_FASTF;
    num_coord_factor = sqrt((double)num_coords);

    d1 = rt_nurb_c_diff(crv);
    d2 = rt_nurb_c_diff(d1);

    pt = d2->ctl_points;
    for (i=0; i<d2->c_size; i++) {
	for (j=0; j<num_coords; j++) {
	    fastf_t abs_val;

	    abs_val = *pt > 0.0 ? *pt : -(*pt);
	    if (abs_val > der2[j])
		der2[j] = abs_val;
	    pt++;
	}
    }

    rt_nurb_free_cnurb(d1);
    rt_nurb_free_cnurb(d2);

    for (j=0; j<num_coords; j++) {
	if (ZERO(der2[j]))
	    continue;

	t = sqrt(2.0 * epsilon / (num_coord_factor * der2[j]));
	if (t < final_t)
	    final_t = t;
    }

    if (ZERO(final_t - MAX_FASTF))
	return -1.0;
    else
	return final_t/2.0;
}
示例#11
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;

}
示例#12
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_pr_mesh(const struct face_g_snurb *m)
{
    int i, j, k;
    fastf_t * m_ptr = m->ctl_points;
    int evp = RT_NURB_EXTRACT_COORDS(m->pt_type);

    NMG_CK_SNURB(m);

    bu_log("\t[%d] [%d]\n", m->s_size[0], m->s_size[1]);

    for (i = 0; i < m->s_size[0]; i++) {
	for (j =0; j < m->s_size[1]; j++) {
	    bu_log("\t");

	    for (k = 0; k < evp; k++)
		bu_log("%f    ", m_ptr[k]);

	    bu_log("\n");
	    m_ptr += RT_NURB_EXTRACT_COORDS(m->pt_type);
	}
	bu_log("\n");
    }
}
示例#14
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 */
}
示例#15
0
文件: nmg_copy.c 项目: kanzure/brlcad
static struct face_g_snurb *
nmg_construct_face_g_snurb(const struct face_g_snurb *original, void **structArray)
{
    struct face_g_snurb *ret;

    NMG_GETSTRUCT(ret, face_g_snurb);

    ret->l.magic = NMG_FACE_G_SNURB_MAGIC;

    BU_LIST_INIT(&ret->f_hd);

    ret->order[0] = original->order[0];
    ret->order[1] = original->order[1];

    ret->u.magic  = NMG_KNOT_VECTOR_MAGIC;
    ret->u.k_size = original->u.k_size;
    ret->u.knots = (fastf_t *)bu_malloc(ret->u.k_size * sizeof(fastf_t),
					"nmg_construct_face_g_snurb(): u.knots");
    memcpy(ret->u.knots, original->u.knots, ret->u.k_size * sizeof(fastf_t));
    ret->v.magic  = NMG_KNOT_VECTOR_MAGIC;
    ret->v.k_size = original->v.k_size;
    ret->v.knots = (fastf_t *)bu_malloc(ret->v.k_size * sizeof(fastf_t),
					"nmg_construct_face_g_snurb(): v.knots");
    memcpy(ret->v.knots, original->v.knots, ret->v.k_size * sizeof(fastf_t));

    ret->s_size[0]  = original->s_size[0];
    ret->s_size[1]  = original->s_size[1];
    ret->pt_type    = original->pt_type;
    ret->ctl_points
	= (fastf_t *)bu_malloc(original->s_size[0] * original->s_size[1] * RT_NURB_EXTRACT_COORDS(ret->pt_type) * sizeof(fastf_t),
			       "nmg_construct_face_g_snurb(): ctl_points");
    memcpy(ret->ctl_points, original->ctl_points, original->s_size[0] * original->s_size[1] * RT_NURB_EXTRACT_COORDS(ret->pt_type) * sizeof(fastf_t));

    ret->dir = original->dir;
    VMOVE(ret->min_pt, original->min_pt);
    VMOVE(ret->max_pt, original->max_pt);

    ret->index              = original->index;
    structArray[ret->index] = ret;

    return ret;
}
示例#16
0
struct edge_g_cnurb *
rt_nurb_crv_copy(const struct edge_g_cnurb *crv)
{
    register struct edge_g_cnurb * n;
    int i;

    NMG_CK_CNURB(crv);

    n = (struct edge_g_cnurb *) rt_nurb_new_cnurb(crv->order,
						  crv->k.k_size, crv->c_size, crv->pt_type);

    for (i = 0; i < crv->k.k_size; i++)
	n->k.knots[i] = crv->k.knots[i];

    for (i = 0; i < crv->c_size *
	     RT_NURB_EXTRACT_COORDS(crv->pt_type); i++)
	n->ctl_points[i] = crv->ctl_points[i];

    return (struct edge_g_cnurb *) n;
}
示例#17
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 */
}
void
rt_nurb_mesh_diff(int order, const fastf_t *o_pts, fastf_t *n_pts, const fastf_t *knots, int o_stride, int n_stride, int o_size, int pt_type)
{
    int i, k;
    int coords;
    fastf_t denom;

    coords = RT_NURB_EXTRACT_COORDS(pt_type);

    for (i = 1; i < o_size; i++) {
	denom = knots[ i + order - 1] - knots[i];
	for (k = 0; k < coords; k++) {
	    if (ZERO(denom))
		n_pts[k] = 0.0;
	    else
		n_pts[k] = (order - 1) *
		    (o_pts[k+o_stride] - o_pts[k]) /
		    denom;
	}
	n_pts += n_stride;
	o_pts += o_stride;
    }
}
/**
 * Create a place holder for a new nurb curve.
 */
struct edge_g_cnurb *
rt_nurb_new_cnurb(int order, int n_knots, int n_pts, int pt_type)
{
    register struct edge_g_cnurb * crv;

    GET_CNURB(crv);
    crv->order = order;

    crv->k.k_size = n_knots;
    crv->k.knots = (fastf_t *)
	bu_malloc(n_knots * sizeof(fastf_t),
		  "rt_nurb_new_cnurb: knot values");

    crv->c_size = n_pts;
    crv->pt_type = pt_type;

    crv->ctl_points = (fastf_t *)
	bu_malloc(sizeof(fastf_t) * RT_NURB_EXTRACT_COORDS(pt_type) *
		  n_pts,
		  "rt_nurb_new_cnurb: mesh point values");

    return crv;
}
示例#20
0
/**
 * Algorithm
 *
 * Given a parametric direction (u or v) look at the direction knot
 * vector and insert a multiple knot of parametric direction surface
 * order. This is somewhat different than rt_nurb_split in that the
 * surface is give a parametric value at which to split the surface.
 * rt_nurb_kvmult does the right thing in inserting a multiple knot
 * with the correct amount. Separate the surface and return the two
 * resulting surface.
 */
struct face_g_snurb *
rt_nurb_s_xsplit(struct face_g_snurb *srf, fastf_t param, int dir)
{
    struct knot_vector new_kv;
    struct oslo_mat * oslo;
    int i;
    int k_index;
    struct face_g_snurb * srf1, * srf2;

    NMG_CK_SNURB(srf);

    if (dir == RT_NURB_SPLIT_ROW) {
	rt_nurb_kvmult(&new_kv, &srf->u, srf->order[0], param, (struct resource *)NULL);

	k_index = srf->order[0];

	oslo = (struct oslo_mat *)
	    rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_ROW], &srf->u, &new_kv, (struct resource *)NULL);

	GET_SNURB(srf1);
	srf1->order[0]  = srf->order[0];
	srf1->order[1]  = srf->order[1];
	srf1->dir = RT_NURB_SPLIT_ROW;
	rt_nurb_kvextract(&srf1->u, &new_kv, 0, k_index + srf1->order[0], (struct resource *)NULL);
	rt_nurb_kvcopy(&srf1->v, &srf->v, (struct resource *)NULL);

	srf1->pt_type = srf->pt_type;
	srf1->s_size[0] = srf1->v.k_size -
	    srf1->order[1];
	srf1->s_size[1] = srf1->u.k_size -
	    srf1->order[0];

	srf1->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
		      srf1->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf1->pt_type),
		      "rt_nurb_s_xsplit: srf1 row mesh control points");

	GET_SNURB(srf2);
	srf2->order[0]  = srf->order[0];
	srf2->order[1]  = srf->order[1];
	srf2->dir = RT_NURB_SPLIT_ROW;
	rt_nurb_kvextract(&srf2->u, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
	rt_nurb_kvcopy(&srf2->v, &srf->v, (struct resource *)NULL);

	srf2->pt_type = srf->pt_type;
	srf2->s_size[0] = srf2->v.k_size -
	    srf2->order[1];
	srf2->s_size[1] = srf2->u.k_size -
	    srf2->order[0];

	srf2->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
		      srf2->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf2->pt_type),
		      "rt_nurb_s_xsplit: srf2 row mesh control points");

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

	    old_mesh_ptr = &srf->ctl_points[
		i * srf->s_size[1] *
		RT_NURB_EXTRACT_COORDS(srf->pt_type)];
	    new_mesh_ptr = &srf1->ctl_points[
		i * srf1->s_size[1] *
		RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
			     0, k_index, srf1->pt_type);
	    new_mesh_ptr = &srf2->ctl_points[
		i * srf2->s_size[1] *
		RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
			     k_index, new_kv.k_size - srf2->order[0],
			     srf2->pt_type);
	}
    } else {
	rt_nurb_kvmult(&new_kv, &srf->v, srf->order[RT_NURB_SPLIT_COL], param, (struct resource *)NULL);

	k_index = srf->order[1];

	oslo = (struct oslo_mat *)
	    rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_COL], &srf->v, &new_kv, (struct resource *)NULL);

	GET_SNURB(srf1);
	srf1->order[0]  = srf->order[0];
	srf1->order[1]  = srf->order[1];
	srf1->dir = RT_NURB_SPLIT_COL;
	rt_nurb_kvextract(&srf1->v, &new_kv, 0, k_index + srf1->order[RT_NURB_SPLIT_COL], (struct resource *)NULL);
	rt_nurb_kvcopy(&srf1->u, &srf->u, (struct resource *)NULL);

	srf1->pt_type = srf->pt_type;
	srf1->s_size[0] = srf1->v.k_size -
	    srf1->order[1];
	srf1->s_size[1] = srf1->u.k_size -
	    srf1->order[0];

	srf1->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
		      srf1->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf1->pt_type),
		      "rt_nurb_split: srf1 row mesh control points");

	GET_SNURB(srf2);
	srf2->order[0]  = srf->order[0];
	srf2->order[1]  = srf->order[1];
	srf2->dir = RT_NURB_SPLIT_COL;
	rt_nurb_kvextract(&srf2->v, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
	rt_nurb_kvcopy(&srf2->u, &srf->u, (struct resource *)NULL);

	srf2->pt_type = srf->pt_type;
	srf2->s_size[0] = srf2->v.k_size -
	    srf2->order[1];
	srf2->s_size[1] = srf2->u.k_size -
	    srf2->order[0];

	srf2->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
		      srf2->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf2->pt_type),
		      "rt_nurb_s_xsplit: srf2 row mesh control points");

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

	    old_mesh_ptr = &srf->ctl_points[
		i * RT_NURB_EXTRACT_COORDS(srf->pt_type)];
	    new_mesh_ptr = &srf1->ctl_points[
		i * RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     srf->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     srf1->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
			     0, k_index, srf1->pt_type);
	    new_mesh_ptr = &srf2->ctl_points[
		i * RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     srf->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     srf2->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
			     k_index, new_kv.k_size - srf2->order[1],
			     srf2->pt_type);
	}
    }

    BU_LIST_APPEND(&srf1->l, &srf2->l);

    bu_free((char *) new_kv.knots, "rt_nurb_s_xsplit: new_kv.knots");

    rt_nurb_free_oslo(oslo, (struct resource *)NULL);

    return srf1;
}
示例#21
0
/**
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_nurb_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_nurb_internal *nurb;

    mat_t mirmat;
    mat_t rmat;
    mat_t temp;
    vect_t nvec;
    vect_t xvec;
    vect_t mirror_dir;
    point_t mirror_pt;
    fastf_t ang;

    int i;
    int j;

    static point_t origin = {0.0, 0.0, 0.0};

    RT_CK_DB_INTERNAL(ip);

    nurb = (struct rt_nurb_internal *)ip->idb_ptr;
    RT_PG_CK_MAGIC(nurb);

    MAT_IDN(mirmat);

    VMOVE(mirror_dir, plane);
    VSCALE(mirror_pt, plane, plane[W]);

    /* Build mirror transform matrix, for those who need it. */
    /* First, perform a mirror down the X axis */
    mirmat[0] = -1.0;

    /* Create the rotation matrix */
    VSET(xvec, 1, 0, 0);
    VCROSS(nvec, xvec, mirror_dir);
    VUNITIZE(nvec);
    ang = -acos(VDOT(xvec, mirror_dir));
    bn_mat_arb_rot(rmat, origin, nvec, ang*2.0);

    /* Add the rotation to mirmat */
    MAT_COPY(temp, mirmat);
    bn_mat_mul(mirmat, temp, rmat);

    /* Add the translation to mirmat */
    mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X];
    mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y];
    mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z];

    for (i=0; i<nurb->nsrf; i++) {
	fastf_t *ptr;
	int tmp;
	int orig_size[2];
	int ncoords;
	int m;
	int l;

	/* swap knot vectors between u and v */
	ptr = nurb->srfs[i]->u.knots;
	tmp = nurb->srfs[i]->u.k_size;

	nurb->srfs[i]->u.knots = nurb->srfs[i]->v.knots;
	nurb->srfs[i]->u.k_size = nurb->srfs[i]->v.k_size;
	nurb->srfs[i]->v.knots = ptr;
	nurb->srfs[i]->v.k_size = tmp;

	/* swap order */
	tmp = nurb->srfs[i]->order[0];
	nurb->srfs[i]->order[0] = nurb->srfs[i]->order[1];
	nurb->srfs[i]->order[1] = tmp;

	/* swap mesh size */
	orig_size[0] = nurb->srfs[i]->s_size[0];
	orig_size[1] = nurb->srfs[i]->s_size[1];

	nurb->srfs[i]->s_size[0] = orig_size[1];
	nurb->srfs[i]->s_size[1] = orig_size[0];

	/* allocate memory for a new control mesh */
	ncoords = RT_NURB_EXTRACT_COORDS(nurb->srfs[i]->pt_type);
	ptr = (fastf_t *)bu_calloc(orig_size[0]*orig_size[1]*ncoords, sizeof(fastf_t), "rt_mirror: ctl mesh ptr");

	/* mirror each control point */
	for (j=0; j<orig_size[0]*orig_size[1]; j++) {
	    point_t pt;

	    VMOVE(pt, &nurb->srfs[i]->ctl_points[j*ncoords]);
	    MAT4X3PNT(&nurb->srfs[i]->ctl_points[j*ncoords], mirmat, pt);
	}

	/* copy mirrored control points into new mesh
	 * while swapping u and v */
	m = 0;
	for (j=0; j<orig_size[0]; j++) {
	    for (l=0; l<orig_size[1]; l++) {
		VMOVEN(&ptr[(l*orig_size[0]+j)*ncoords], &nurb->srfs[i]->ctl_points[m*ncoords], ncoords);
		m++;
	    }
	}

	/* free old mesh */
	bu_free((char *)nurb->srfs[i]->ctl_points, "rt_mirror: ctl points");

	/* put new mesh in place */
	nurb->srfs[i]->ctl_points = ptr;
    }

    return 0;
}
示例#22
0
/**
 * Algorithm
 *
 * Given a parametric direction (u or v) look at the direction knot
 * vector and insert a multiple knot of parametric direction surface
 * order.  If internal knot values exist than pick the one closest to
 * the middle and add additional knots to split at that value,
 * otherwise add multiple knots at the mid point of the knot
 * vector. Use the new knot vector to pass to the oslo refinement
 * process and split the surface.  Separate the surface and return the
 * two resulting surface.
 *
 * The original surface is undisturbed by this operation.
 */
void
rt_nurb_s_split(struct bu_list *split_hd, const struct face_g_snurb *srf, int dir, struct resource *res)
{
    struct knot_vector new_kv;
    fastf_t value;
    struct oslo_mat * oslo;
    int i;
    int k_index = 0;
    struct face_g_snurb * srf1, * srf2;

    NMG_CK_SNURB(srf);

    if (dir == RT_NURB_SPLIT_ROW) {
        value = srf->u.knots[(srf->u.k_size -1)/2];

        for (i = 0; i < srf->u.k_size; i++)
            if (ZERO(value - srf->u.knots[i])) {
                k_index = i;
                break;
            }
        if (k_index == 0) {
            value = (value +
                     srf->u.knots[ srf->u.k_size -1])
                    /2.0;
            k_index = srf->order[0];
        }

        rt_nurb_kvmult(&new_kv, &srf->u, srf->order[0], value, res);

        oslo = (struct oslo_mat *)
               rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_ROW], &srf->u, &new_kv, res);

        GET_SNURB(srf1);
        srf1->order[0]  = srf->order[0];
        srf1->order[1]  = srf->order[1];
        srf1->dir = RT_NURB_SPLIT_ROW;
        rt_nurb_kvextract(&srf1->u, &new_kv, 0, k_index + srf1->order[0], res);
        rt_nurb_kvcopy(&srf1->v, &srf->v, res);

        srf1->pt_type = srf->pt_type;
        srf1->s_size[0] = srf1->v.k_size -
                          srf1->order[1];
        srf1->s_size[1] = srf1->u.k_size -
                          srf1->order[0];

        srf1->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
                                     srf1->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                                     "rt_nurb_s_split: srf1 row mesh control points");

        GET_SNURB(srf2);
        srf2->order[0]  = srf->order[0];
        srf2->order[1]  = srf->order[1];
        srf2->dir = RT_NURB_SPLIT_ROW;
        rt_nurb_kvextract(&srf2->u, &new_kv, k_index, new_kv.k_size, res);
        rt_nurb_kvcopy(&srf2->v, &srf->v, res);

        srf2->pt_type = srf->pt_type;
        srf2->s_size[0] = srf2->v.k_size -
                          srf2->order[1];
        srf2->s_size[1] = srf2->u.k_size -
                          srf2->order[0];

        srf2->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
                                     srf2->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                                     "rt_nurb_s_split: srf2 row mesh control points");

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

            old_mesh_ptr = &srf->ctl_points[
                               i * srf->s_size[1] *
                               RT_NURB_EXTRACT_COORDS(srf->pt_type)];
            new_mesh_ptr = &srf1->ctl_points[
                               i * srf1->s_size[1] *
                               RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                             0, k_index, srf1->pt_type);
            new_mesh_ptr = &srf2->ctl_points[
                               i * srf2->s_size[1] *
                               RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                             k_index, new_kv.k_size - srf2->order[0],
                             srf2->pt_type);
        }
    } else {
        value = srf->v.knots[(srf->v.k_size -1)/2];

        for (i = 0; i < srf->v.k_size; i++)
            if (ZERO(value - srf->v.knots[i])) {
                k_index = i;
                break;
            }
        if (k_index == 0) {
            value = (value +
                     srf->v.knots[ srf->v.k_size -1])
                    /2.0;
            k_index = srf->order[1];
        }

        rt_nurb_kvmult(&new_kv, &srf->v, srf->order[RT_NURB_SPLIT_COL], value, res);

        oslo = (struct oslo_mat *)
               rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_COL], &srf->v, &new_kv, res);

        GET_SNURB(srf1);
        srf1->order[0]  = srf->order[0];
        srf1->order[1]  = srf->order[1];
        srf1->dir = RT_NURB_SPLIT_COL;
        rt_nurb_kvextract(&srf1->v, &new_kv, 0, k_index + srf1->order[RT_NURB_SPLIT_COL], res);
        rt_nurb_kvcopy(&srf1->u, &srf->u, res);

        srf1->pt_type = srf->pt_type;
        srf1->s_size[0] = srf1->v.k_size -
                          srf1->order[1];
        srf1->s_size[1] = srf1->u.k_size -
                          srf1->order[0];

        srf1->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
                                     srf1->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                                     "rt_nurb_s_split: srf1 col mesh control points");

        GET_SNURB(srf2);
        srf2->order[0]  = srf->order[0];
        srf2->order[1]  = srf->order[1];
        srf2->dir = RT_NURB_SPLIT_COL;
        rt_nurb_kvextract(&srf2->v, &new_kv, k_index, new_kv.k_size, res);
        rt_nurb_kvcopy(&srf2->u, &srf->u, res);

        srf2->pt_type = srf->pt_type;
        srf2->s_size[0] = srf2->v.k_size -
                          srf2->order[1];
        srf2->s_size[1] = srf2->u.k_size -
                          srf2->order[0];

        srf2->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
                                     srf2->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                                     "rt_nurb_s_split: srf2 col mesh control points");

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

            old_mesh_ptr = &srf->ctl_points[
                               i * RT_NURB_EXTRACT_COORDS(srf->pt_type)];
            new_mesh_ptr = &srf1->ctl_points[
                               i * RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             srf->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             srf1->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                             0, k_index, srf1->pt_type);
            new_mesh_ptr = &srf2->ctl_points[
                               i * RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             srf->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             srf2->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                             k_index, new_kv.k_size - srf2->order[1],
                             srf2->pt_type);
        }
    }

    /* Arrangement will be:  head, srf1, srf2 */
    BU_LIST_APPEND(split_hd, &srf2->l);
    BU_LIST_APPEND(split_hd, &srf1->l);

    rt_nurb_free_oslo(oslo, res);
    bu_free((char *)new_kv.knots, "rt_nurb_s_split: new kv knots");

}
示例#23
0
/**
 * Split a NURB curve by inserting a multiple knot and return the
 * result of the two curves.
 *
 * Algorithm
 *
 * Insert a multiple knot of the curve order.  If internal knot values
 * exist than pick the one closest to the middle and add additional
 * knots to split at that value, otherwise add multiple knots at the
 * mid point of the knot vector. Use the new knot vector to pass to
 * the oslo refinement process and split the curve.  Separate the
 * curve and return the two resulting curves.
 *
 * The original curve is undisturbed by this operation.
 */
void
rt_nurb_c_split(struct bu_list *split_hd, const struct edge_g_cnurb *crv)
{
    struct knot_vector new_kv;
    fastf_t value;
    struct oslo_mat * oslo;
    int i;
    int k_index = 0;
    struct edge_g_cnurb * crv1, * crv2;
    int coords;

    NMG_CK_CNURB(crv);

    coords = RT_NURB_EXTRACT_COORDS(crv->pt_type),

    value = crv->k.knots[(crv->k.k_size -1)/2];

    for (i = 0; i < crv->k.k_size; i++)
        if (ZERO(value - crv->k.knots[i])) {
            k_index = i;
            break;
        }
    if (k_index == 0) {
        value = (value +
                 crv->k.knots[ crv->k.k_size -1])
                /2.0;
        k_index = crv->order;
    }

    rt_nurb_kvmult(&new_kv, &crv->k, crv->order, value, (struct resource *)NULL);

    oslo = (struct oslo_mat *)
           rt_nurb_calc_oslo(crv->order, &crv->k, &new_kv, (struct resource *)NULL);

    GET_CNURB(crv1);
    crv1->order  = crv->order;
    rt_nurb_kvextract(&crv1->k, &new_kv, 0, k_index + crv->order, (struct resource *)NULL);
    crv1->pt_type = crv->pt_type;
    crv1->c_size = crv1->k.k_size - crv1->order;
    crv1->ctl_points = (fastf_t *)
                       bu_malloc(sizeof(fastf_t) * crv1->c_size *
                                 RT_NURB_EXTRACT_COORDS(crv1->pt_type),
                                 "rt_nurb_c_split: crv1 control points");

    GET_CNURB(crv2);
    crv2->order  = crv->order;
    rt_nurb_kvextract(&crv2->k, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
    crv2->pt_type = crv->pt_type;
    crv2->c_size = crv2->k.k_size - crv2->order;
    crv2->ctl_points = (fastf_t *)
                       bu_malloc(sizeof(fastf_t) * crv2->c_size *
                                 RT_NURB_EXTRACT_COORDS(crv2->pt_type),
                                 "rt_nurb_s_split: crv2 mesh control points");

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv1->ctl_points,
                     coords, coords, 0, k_index, crv->pt_type);

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv2->ctl_points,
                     coords, coords, k_index, new_kv.k_size - crv2->order,
                     crv2->pt_type);

    rt_nurb_free_oslo(oslo, (struct resource *)NULL);

    bu_free((char *) new_kv.knots, "rt_nurb_c_split; new_kv.knots");

    /* Arrangement will be:  head, crv1, crv2 */
    BU_LIST_APPEND(split_hd, &crv2->l);
    BU_LIST_APPEND(split_hd, &crv1->l);
}
示例#24
0
文件: nurb_ray.c 项目: kanzure/brlcad
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;
}
struct face_g_snurb *
rt_nurb_s_diff(const struct face_g_snurb *srf, int dir)
{
    struct face_g_snurb *nsrf;
    int i;

    NMG_CK_SNURB(srf);

    if (dir == RT_NURB_SPLIT_ROW) {
	nsrf = (struct face_g_snurb *)
	    rt_nurb_new_snurb(srf->order[0] - 1, srf->order[1],
			      srf->u.k_size - 2, srf->v.k_size,
			      srf->s_size[0], srf->s_size[1] - 1,
			      srf->pt_type, (struct resource *)NULL);

	for (i = 0; i < srf->s_size[0]; i++) {
	    fastf_t * old_points, *new_points;

	    old_points = srf->ctl_points +
		i * RT_NURB_EXTRACT_COORDS(srf->pt_type)
		*srf->s_size[1];

	    new_points = nsrf->ctl_points +
		i * RT_NURB_EXTRACT_COORDS(nsrf->pt_type)
		*nsrf->s_size[1];

	    rt_nurb_mesh_diff(srf->order[0],
			      old_points, new_points, srf->u.knots,
			      RT_NURB_EXTRACT_COORDS(srf->pt_type),
			      RT_NURB_EXTRACT_COORDS(nsrf->pt_type),
			      srf->s_size[1], srf->pt_type);
	}

	for (i = 1; i < srf->u.k_size - 1; i++)
	    nsrf->u.knots[i - 1] = srf->u.knots[i];

	for (i = 0; i < srf->v.k_size; i++)
	    nsrf->v.knots[i] = srf->v.knots[i];
    } else {
	nsrf = (struct face_g_snurb *) rt_nurb_new_snurb(
	    srf->order[0], srf->order[1] - 1,
	    srf->u.k_size, srf->v.k_size - 2,
	    srf->s_size[0] - 1, srf->s_size[1],
	    srf->pt_type, (struct resource *)NULL);

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

	    old_points = srf->ctl_points +
		i * RT_NURB_EXTRACT_COORDS(srf->pt_type);

	    new_points = nsrf->ctl_points +
		i * RT_NURB_EXTRACT_COORDS(nsrf->pt_type);

	    rt_nurb_mesh_diff(srf->order[1],
			      old_points, new_points, srf->v.knots,
			      RT_NURB_EXTRACT_COORDS(srf->pt_type) *
			      srf->s_size[1],
			      RT_NURB_EXTRACT_COORDS(nsrf->pt_type) *
			      nsrf->s_size[1],
			      srf->s_size[0], srf->pt_type);
	}

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

	for (i = 1; i < srf->v.k_size - 1; i++)
	    nsrf->v.knots[i-1] = srf->v.knots[i];
    }
    return nsrf;
}
示例#26
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;
}
示例#27
0
文件: nurb_ray.c 项目: kanzure/brlcad
void
rt_nurb_clip_srf(const struct face_g_snurb *srf, int dir, fastf_t *min, fastf_t *max)
{
    struct internal_convex_hull ch[20]; /* max order is 10 */
    register fastf_t * mp1;
    fastf_t * p1, *p2, *p3, *p4;	/* corner points of the mesh */
    fastf_t v1[2], v2[2], v3[2];	/* vectors from corners */
    struct internal_line l1;
    fastf_t norm;
    fastf_t value;
    int i;
    register int j;
    int k;
    int coords;
    int col_size, row_size;

    col_size = srf->s_size[1];
    row_size = srf->s_size[0];

    coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);

    p1 = srf->ctl_points;
    p2 = srf->ctl_points + coords * (col_size - 1);
    p3 = srf->ctl_points + (coords * col_size *
			    (row_size - 1));
    p4 = srf->ctl_points + (coords * col_size *
			    (row_size - 1)) +
	((col_size - 1) * coords);

    if (dir == RT_NURB_SPLIT_ROW) {
	v1[0] = p1[0] - p3[0];
	v1[1] = p1[1] - p3[1];

	v2[0] = p2[0] - p4[0];
	v2[1] = p2[1] - p4[1];
    } else {
	v1[0] = p1[0] - p2[0];
	v1[1] = p1[1] - p2[1];

	v2[0] = p3[0] - p4[0];
	v2[1] = p3[1] - p4[1];
    }

    v3[0] = v1[0] + v2[0];
    v3[1] = v1[1] + v1[1];

    norm = sqrt(v3[1] * v3[1] + v3[0] * v3[0]);
    l1.a = v3[1] / norm;
    l1.b = -v3[0] / norm;

    *min = 1.0e8;
    *max = -1.0e8;

    if (dir == RT_NURB_SPLIT_ROW) {
	for (i = 0; i < col_size; i++) {
	    ch[i].param = (fastf_t) i / (col_size - 1.0);
	    ch[i].min = 1.0e8;
	    ch[i].max = -1.0e8;
	}

	mp1 = srf->ctl_points;

	for (i = 0; i < row_size; i++) {
	    for (j = 0; j < col_size; j++) {
		value = - (mp1[0] * l1.a + mp1[1] * l1.b);
		if (value <= ch[j].min)
		    ch[j].min = value;
		if (value >= ch[j].max)
		    ch[j].max = value;
		mp1 += coords;
	    }
	}

	for (k = 0; k < col_size - 1; k++)
	    for (j = k+1; j < col_size; j++) {
		fastf_t d;
		fastf_t param1, param2;

		param1 = ch[k].param;
		param2 = ch[j].param;

		d = FINDZERO(param1, param2, ch[k].max, ch[j].max);
		if (d <= *min) *min = d * .99;
		if (d >= *max) *max = d * .99 + .01;

		d = FINDZERO(param1, param2, ch[k].min, ch[j].min);
		if (d <= *min) *min = d * .99;
		if (d >= *max) *max = d * .99 + .01;
	    }

	if (*min <= 0.0)
	    *min = 0.0;
	if (*max >= 1.0)
	    *max = 1.0;
	if (SIGN(ch[0].min) != SIGN(ch[0].max))
	    *min = 0.0;
	i = SIGN(ch[col_size -1].min);
	j = SIGN(ch[col_size -1].max);
	if (i != j)
	    *max = 1.0;
    } else {
	for (i = 0; i < row_size; i++) {
	    ch[i].param = (fastf_t) i / (row_size - 1.0);
	    ch[i].min = 1.0e8;
	    ch[i].max = -1.0e8;
	}


	for (i = 0; i < col_size; i++) {
	    int stride;

	    stride = coords * col_size;

	    mp1 = srf->ctl_points + i * coords;
	    for (j = 0; j < row_size; j++) {
		value = - (mp1[0] * l1.a + mp1[1] * l1.b);
		if (value <= ch[j].min)
		    ch[j].min = value;
		if (value >= ch[j].max)
		    ch[j].max = value;
		mp1 += stride;
	    }
	}

	for (k = 0; k < row_size - 1; k++)
	    for (j = k+1; j < row_size; j++) {
		fastf_t d;
		fastf_t param1, param2;

		param1 = ch[k].param;
		param2 = ch[j].param;

		d = FINDZERO(param1, param2, ch[k].max, ch[j].max);
		if (d <= *min) *min = d * .99;
		if (d >= *max) *max = d * .99 + .01;

		d = FINDZERO(param1, param2, ch[k].min, ch[j].min);
		if (d <= *min) *min = d * .99;
		if (d >= *max) *max = d * .99 + .01;
	    }
	if (*min <= 0.0)
	    *min = 0.0;
	if (*max >= 1.0)
	    *max = 1.0;
	if (SIGN(ch[0].min) != SIGN(ch[0].max))
	    *min = 0.0;
	i = SIGN(ch[row_size-1 ].min);
	j = SIGN(ch[row_size -1].max);
	if (i != j)
	    *max = 1.0;	}
}
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)));
}
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;
}
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 */

}