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; }
/* * 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 */ }
extern "C" void rt_nurb_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *) { int i, j, k; struct rt_nurb_internal *nip; RT_CK_DB_INTERNAL(ip); nip = (struct rt_nurb_internal *)ip->idb_ptr; RT_NURB_CK_MAGIC(nip); ON_TextLog log(stderr); for (i = 0; i < nip->nsrf; i++) { struct face_g_snurb *surface = nip->srfs[i]; NMG_CK_SNURB(surface); ON_NurbsSurface *nurb = ON_NurbsSurface::New(3, true, surface->order[0], surface->order[1], surface->s_size[0], surface->s_size[1]); /* set 'u' knots */ /* skip first and last (duplicates?) */ for (j = 1; j < surface->u.k_size - 1; j++) { nurb->SetKnot(0, j-1, surface->u.knots[j]); /* bu_log("u knot %d is %f\n", j-1, surface->u.knots[j]); */ } /* set 'v' knots */ /* skip first and last (duplicates?) */ for (j = 1; j < surface->v.k_size - 1; j++) { nurb->SetKnot(1, j-1, surface->v.knots[j]); /* bu_log("v knot %d is %f\n", j-1, surface->u.knots[j]); */ } /* set control points */ for (j = 0; j < surface->s_size[0]; j++) { for (k = 0; k < surface->s_size[1]; k++) { ON_3dPoint point = &RT_NURB_GET_CONTROL_POINT(surface, j, k); nurb->SetCV(k, j, point); } } /* nurb->Dump(log); */ bu_log("NURBS surface %d %s valid\n", i, nurb->IsValid(&log) ? "is" : "is not"); (*b)->m_S.Append(nurb); int sindex = (*b)->m_S.Count(); (*b)->NewFace(sindex - 1); int findex = (*b)->m_F.Count(); (*b)->NewOuterLoop(findex - 1); } bu_log("BREP object %s a single surface\n", (*b)->IsSurface() ? "is" : "is not"); bu_log("BREP object %s valid\n", (*b)->IsValid(&log) ? "is" : "is not"); bu_log("BREP object %s valid topology\n", (*b)->IsValidTopology(&log) ? "is" : "is not"); bu_log("BREP object %s valid geometry\n", (*b)->IsValidGeometry(&log) ? "is" : "is not"); bu_log("BREP object %s solid\n", (*b)->IsSolid() ? "is" : "is not"); bu_log("BREP object %s manifold\n", (*b)->IsManifold() ? "is" : "is not"); }
int rt_bez_check(const struct face_g_snurb *srf) { NMG_CK_SNURB(srf); if ( srf->u.k_size > (2.0 * srf->order[0])) return 0; if ( srf->v.k_size > (2.0 * srf->order[1])) return 1; return -1; }
void rt_nurb_free_snurb(struct face_g_snurb *srf, struct resource *res) { NMG_CK_SNURB(srf); if (res) RT_CK_RESOURCE(res); /* assume that links to other surface and curves are already * deleted. */ bu_free((char *)srf->u.knots, "rt_nurb_free_snurb: u kv knots"); bu_free((char *)srf->v.knots, "rt_nurb_free_snurb: v kv knots"); bu_free((char *)srf->ctl_points, "rt_nurb_free_snurb: mesh points"); srf->l.magic = 0; bu_free((char *)srf, "rt_nurb_free_snurb: snurb struct"); }
/** * Clean up the storage use of an snurb, but don't release the * pointer. Often used by routines that allocate an array of nurb * pointers, or use automatic variables to hold one. */ void rt_nurb_clean_snurb(struct face_g_snurb *srf, struct resource *res) { NMG_CK_SNURB(srf); if (res) RT_CK_RESOURCE(res); bu_free((char *)srf->u.knots, "rt_nurb_clean_snurb() u.knots"); bu_free((char *)srf->v.knots, "rt_nurb_free_snurb() v.knots"); bu_free((char *)srf->ctl_points, "rt_nurb_free_snurb() ctl_points"); /* Invalidate the structure */ srf->u.knots = (fastf_t *)NULL; srf->v.knots = (fastf_t *)NULL; srf->ctl_points = (fastf_t *)NULL; srf->order[0] = srf->order[1] = -1; srf->l.magic = 0; }
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"); } }
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; }
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; }
/** * 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"); }
/** * 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; }
/** * Returns a refined surface. The original surface is unmodified. */ struct face_g_snurb * rt_nurb_s_refine(const struct face_g_snurb *srf, int dir, struct knot_vector *kv, struct resource *res) /* Old surface to be refined */ /* Direction to refine */ /* Row = 0, Col = 1 */ /* New knot vector */ { register struct face_g_snurb * nurb_srf; struct oslo_mat *oslo; /* oslo refinement matrix */ int i; NMG_CK_SNURB(srf); if (dir == RT_NURB_SPLIT_ROW) { /* Row (u) direction */ GET_SNURB(nurb_srf); nurb_srf->order[0] = srf->order[0]; nurb_srf->order[1] = srf->order[1]; rt_nurb_kvcopy(&nurb_srf->u, kv, res); rt_nurb_kvcopy(&nurb_srf->v, &srf->v, res); nurb_srf->s_size[0] = srf->s_size[0]; nurb_srf->s_size[1] = kv->k_size - srf->order[0]; nurb_srf->pt_type = srf->pt_type; nurb_srf->ctl_points = (fastf_t *) bu_malloc(sizeof (fastf_t) * nurb_srf->s_size[0] * nurb_srf->s_size[1] * RT_NURB_EXTRACT_COORDS(nurb_srf->pt_type), "rt_nurb_s_refine: row mesh control points"); oslo = (struct oslo_mat *) rt_nurb_calc_oslo (srf -> order[RT_NURB_SPLIT_ROW], &srf->u, kv, res); for (i = 0; i < nurb_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 = &nurb_srf->ctl_points[ i * nurb_srf->s_size[1] * RT_NURB_EXTRACT_COORDS(nurb_srf->pt_type)]; rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr, RT_NURB_EXTRACT_COORDS(srf->pt_type), RT_NURB_EXTRACT_COORDS(nurb_srf->pt_type), 0, kv->k_size - nurb_srf->order[0], nurb_srf->pt_type); } rt_nurb_free_oslo(oslo, res); } else { /* Col (v) direction */ GET_SNURB(nurb_srf); nurb_srf->order[0] = srf->order[0]; nurb_srf->order[1] = srf->order[1]; rt_nurb_kvcopy(&nurb_srf->u, &srf->u, res); rt_nurb_kvcopy(&nurb_srf->v, kv, res); nurb_srf->s_size[0] = kv->k_size - srf->order[1]; nurb_srf->s_size[1] = srf->s_size[1]; nurb_srf->pt_type = srf->pt_type; nurb_srf->ctl_points = (fastf_t *) bu_malloc(sizeof (fastf_t) * nurb_srf->s_size[0] * nurb_srf->s_size[1] * RT_NURB_EXTRACT_COORDS(nurb_srf->pt_type), "rt_nurb_s_refine: row mesh control points"); oslo = (struct oslo_mat *) rt_nurb_calc_oslo (srf->order[RT_NURB_SPLIT_COL], &srf->v, kv, res); for (i = 0; i < nurb_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 = &nurb_srf->ctl_points[ i * RT_NURB_EXTRACT_COORDS(nurb_srf->pt_type)]; rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr, srf->s_size[1] * RT_NURB_EXTRACT_COORDS(srf->pt_type), nurb_srf->s_size[1] * RT_NURB_EXTRACT_COORDS(nurb_srf->pt_type), 0, kv->k_size - nurb_srf->order[1], nurb_srf->pt_type); } rt_nurb_free_oslo(oslo, res); } return nurb_srf; }