/** * 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; }
/** * 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; }
/** * 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"); }
/** * 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; }