/* * 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 */ }
HIDDEN struct bu_cmdhist_obj * cho_open(ClientData UNUSED(clientData), Tcl_Interp *interp, const char *name) { struct bu_cmdhist_obj *chop; /* check to see if command history object exists */ for (BU_LIST_FOR(chop, bu_cmdhist_obj, &HeadCmdHistObj.l)) { if (BU_STR_EQUAL(name, bu_vls_addr(&chop->cho_name))) { Tcl_AppendResult(interp, "ch_open: ", name, " exists.\n", (char *)NULL); return BU_CMDHIST_OBJ_NULL; } } BU_GET(chop, struct bu_cmdhist_obj); bu_vls_init(&chop->cho_name); bu_vls_strcpy(&chop->cho_name, name); BU_LIST_INIT(&chop->cho_head.l); bu_vls_init(&chop->cho_head.h_command); chop->cho_head.h_start.tv_sec = chop->cho_head.h_start.tv_usec = chop->cho_head.h_finish.tv_sec = chop->cho_head.h_finish.tv_usec = 0L; chop->cho_head.h_status = TCL_OK; chop->cho_curr = &chop->cho_head; BU_LIST_APPEND(&HeadCmdHistObj.l, &chop->l); return chop; }
void new_image(const struct bu_structparse *UNUSED(sdp), const char *UNUSED(name), void *base, const char *UNUSED(value), void *UNUSED(data)) { struct bbd_specific *bbd_sp = (struct bbd_specific *)base; struct bbd_img *bbdi; /* XXX - looks like we don't release this memory */ BU_ALLOC(bbdi, struct bbd_img); bbdi->img_mf = bu_open_mapped_file_with_path( bbd_sp->rtip->rti_dbip->dbi_filepath, bu_vls_addr(&bbd_sp->img_filename), NULL); if (!bbdi->img_mf) { bu_log("error opening image %s\n", bu_vls_addr(&bbd_sp->img_filename)); bu_bomb(""); } BU_CK_MAPPED_FILE(bbdi->img_mf); bbdi->img_width = bbd_sp->img_width; bbdi->img_width = bbd_sp->img_height; BU_LIST_APPEND(&bbd_sp->imgs, &(bbdi->l)); bbd_sp->img_count++; }
void nurb_c_to_bezier(struct bu_list *clist, struct edge_g_cnurb *crv) { fastf_t knot_min, knot_max; int i; struct edge_g_cnurb *crv1, *crv_copy; int done; /* make a copy of original curve */ crv_copy = rt_nurb_crv_copy( crv ); /* split curve at each knot value */ done = 0; while ( !done ) { fastf_t split; knot_min = crv_copy->k.knots[0]; knot_max = crv_copy->k.knots[crv_copy->k.k_size-1]; split = MAX_FASTF; for ( i=1; i<crv_copy->k.k_size-1; i++ ) { if ( crv_copy->k.knots[i] != knot_min && crv_copy->k.knots[i] != knot_max ) { split = crv_copy->k.knots[i]; break; } } if ( split == MAX_FASTF ) { done = 1; BU_LIST_APPEND( clist, &crv_copy->l ); break; } crv1 = rt_nurb_c_xsplit( crv_copy, split ); rt_nurb_free_cnurb( crv_copy ); crv_copy = BU_LIST_PNEXT( edge_g_cnurb, &crv1->l ); BU_LIST_DEQUEUE( &crv_copy->l ); BU_LIST_APPEND( clist, &crv1->l ); } }
int rt_gen_conic(struct xrays *rays, const struct xray *center_ray, fastf_t theta, vect_t up_vector, int rays_per_radius) { int count = 0; point_t start; vect_t orig_dir; fastf_t x, y; /* Setting radius to tan(theta) works because, as shown in the * following diagram, the ray that starts at the given point and * passes through orig_dir + (radius in any orthogonal direction) * has an angle of theta with the original ray; when the * resulting vector is normalized, the angle is preserved. */ fastf_t radius = tan(theta); fastf_t rsq = radius * radius; /* radius-squared, for use in the loop */ fastf_t gridsize = 2 * radius / (rays_per_radius - 1); vect_t a_dir, b_dir; register struct xrays *xrayp; VMOVE(start, center_ray->r_pt); VMOVE(orig_dir, center_ray->r_dir); /* Create vectors a_dir, b_dir that are orthogonal to orig_dir. */ VMOVE(b_dir, up_vector); VUNITIZE(b_dir); VCROSS(a_dir, orig_dir, up_vector); VUNITIZE(a_dir); for (y = -radius; y <= radius; y += gridsize) { vect_t tmp; printf("y:%f\n", y); VSCALE(tmp, b_dir, y); printf("y_partofit: %f,%f,%f\n", V3ARGS(tmp)); for (x = -radius; x <= radius; x += gridsize) { if (((x*x)/rsq + (y*y)/rsq) <= 1) { BU_ALLOC(xrayp, struct xrays); VMOVE(xrayp->ray.r_pt, start); VJOIN2(xrayp->ray.r_dir, orig_dir, x, a_dir, y, b_dir); VUNITIZE(xrayp->ray.r_dir); xrayp->ray.index = count++; xrayp->ray.magic = RT_RAY_MAGIC; BU_LIST_APPEND(&rays->l, &xrayp->l); } } } return count; }
void bu_add_hook(struct bu_hook_list *hlp, bu_hook_t func, genptr_t clientdata) { struct bu_hook_list *new_hook; BU_GETSTRUCT(new_hook, bu_hook_list); new_hook->hookfunc = func; new_hook->clientdata = clientdata; new_hook->l.magic = BU_HOOK_LIST_MAGIC; BU_LIST_APPEND(&hlp->l, &new_hook->l); }
/** * 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; }
/** * Classify a point vs a vertex (touching/missed) */ static int nmg_class_pt_vu(struct fpi *fpi, struct vertexuse *vu) { vect_t delta; struct ve_dist *ved; NMG_CK_VERTEXUSE(vu); /* see if we've classified this vertex WRT the point already */ for (BU_LIST_FOR(ved, ve_dist, &fpi->ve_dh)) { NMG_CK_VED(ved); if (ved->magic_p == &vu->v_p->magic) { goto found; } } /* if we get here, we didn't find the vertex in the list of * previously classified geometry. Create an entry in the * face's list of processed geometry. */ VSUB2(delta, vu->v_p->vg_p->coord, fpi->pt); BU_ALLOC(ved, struct ve_dist); ved->magic_p = &vu->v_p->magic; ved->dist = MAGNITUDE(delta); if (ved->dist < fpi->tol->dist_sq) { ved->status = NMG_FPI_TOUCHED; if (fpi->hits == NMG_FPI_PERGEOM) { /* need to cast vu_func pointer for actual use as a function */ void (*cfp)(struct vertexuse *, point_t, const char*); cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func; cfp(vu, fpi->pt, fpi->priv); } } else ved->status = NMG_FPI_MISSED; ved->v1 = ved->v2 = vu->v_p; BU_LIST_MAGIC_SET(&ved->l, NMG_VE_DIST_MAGIC); BU_LIST_APPEND(&fpi->ve_dh, &ved->l); found: if (fpi->vu_func && ved->status == NMG_FPI_TOUCHED && fpi->hits == NMG_FPI_PERUSE) { /* need to cast vu_func pointer for actual use as a function */ void (*cfp)(struct vertexuse *, point_t, const char*); cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func; cfp(vu, fpi->pt, fpi->priv); } return ved->status; }
int rt_gen_frustum(struct xrays *rays, const struct xray *center_ray, const vect_t a_vec, const vect_t b_vec, const fastf_t a_theta, const fastf_t b_theta, const fastf_t a_num, const fastf_t UNUSED(b_num)) { int count = 0; point_t start; vect_t orig_dir; fastf_t x, y; fastf_t a_length = tan(a_theta); fastf_t b_length = tan(b_theta); fastf_t a_inc = 2 * a_length / (a_num - 1); vect_t a_dir, b_dir; register struct xrays *xrayp; VMOVE(start, center_ray->r_pt); VMOVE(orig_dir, center_ray->r_dir); VMOVE(a_dir, a_vec); VUNITIZE(a_dir); VMOVE(b_dir, b_vec); VUNITIZE(b_dir); /* This adds BN_TOL_DIST to the *_length variables in the * condition because in some cases, floating-point problems can * make extremely close numbers compare incorrectly. */ for (y = -b_length; y <= b_length + BN_TOL_DIST;) { for (x = -a_length; x <= a_length + BN_TOL_DIST; x += a_inc) { BU_ALLOC(xrayp, struct xrays); VMOVE(xrayp->ray.r_pt, start); VJOIN2(xrayp->ray.r_dir, orig_dir, x, a_dir, y, b_dir); VUNITIZE(xrayp->ray.r_dir); xrayp->ray.index = count++; xrayp->ray.magic = RT_RAY_MAGIC; BU_LIST_APPEND(&rays->l, &xrayp->l); } } return count; }
int rt_gen_elliptical_grid(struct xrays *rays, const struct xray *center_ray, const fastf_t *avec, const fastf_t *bvec, fastf_t gridsize) { register struct xrays *xrayp; int count = 0; point_t C; vect_t dir; vect_t a_dir; vect_t b_dir; fastf_t a = MAGNITUDE(avec); fastf_t b = MAGNITUDE(bvec); fastf_t x, y; int acpr = a / gridsize; int bcpr = b / gridsize; VMOVE(a_dir, avec); VUNITIZE(a_dir); VMOVE(b_dir, bvec); VUNITIZE(b_dir); VMOVE(C, center_ray->r_pt); VMOVE(dir, center_ray->r_dir); /* make sure avec perpendicular to bvec perpendicular to ray direction */ BU_ASSERT(NEAR_ZERO(VDOT(avec, bvec), VUNITIZE_TOL)); BU_ASSERT(NEAR_ZERO(VDOT(avec, dir), VUNITIZE_TOL)); for (y=gridsize * (-bcpr); y <= b; y=y+gridsize) { for (x= gridsize * (-acpr); x <= a; x=x+gridsize) { if (((x*x)/(a*a) + (y*y)/(b*b)) < 1) { BU_ALLOC(xrayp, struct xrays); VJOIN2(xrayp->ray.r_pt, C, x, a_dir, y, b_dir); VMOVE(xrayp->ray.r_dir, dir); xrayp->ray.index = count++; xrayp->ray.magic = RT_RAY_MAGIC; BU_LIST_APPEND(&rays->l, &xrayp->l); } } } return count; }
void bu_log_add_hook(bu_hook_t func, genptr_t clientdata) { #if 0 struct bu_hook_list *toadd; /* Grab a hunk of memory for a new node, and put it at the head of the list */ BU_GETSTRUCT(toadd, bu_hook_list); toadd->hookfunc = func; toadd->clientdata = clientdata; toadd->l.magic = BU_HOOK_LIST_MAGIC; BU_LIST_APPEND( &(bu_log_hook_list.l), &(toadd->l) ); #else bu_add_hook(&bu_log_hook_list, func, clientdata); #endif }
int rt_gen_rect(struct xrays *rays, const struct xray *center_ray, const vect_t a_vec, const vect_t b_vec, const fastf_t da, const fastf_t db) { int count = 0; point_t orig_start; vect_t dir; fastf_t x, y; fastf_t a_length = MAGNITUDE(a_vec); fastf_t b_length = MAGNITUDE(b_vec); vect_t a_dir; vect_t b_dir; register struct xrays *xrayp; VMOVE(orig_start, center_ray->r_pt); VMOVE(dir, center_ray->r_dir); VMOVE(a_dir, a_vec); VUNITIZE(a_dir); VMOVE(b_dir, b_vec); VUNITIZE(b_dir); for (y = -b_length; y <= b_length; y += db) { for (x = -a_length; x <= a_length; x += da) { BU_ALLOC(xrayp, struct xrays); VJOIN2(xrayp->ray.r_pt, orig_start, x, a_dir, y, b_dir); VMOVE(xrayp->ray.r_dir, dir); xrayp->ray.index = count++; xrayp->ray.magic = RT_RAY_MAGIC; BU_LIST_APPEND(&rays->l, &xrayp->l); } } return count; }
/* * We try and clip a curve so that it can be either Case A, or Case C. * Sometimes one of the curves is still case C though, but it is much * small than the original, and further clipping will either show that * it is on the curve or provide all Case B or Case A curves. * We try and pick the best axis to clip against, but this may not always * work. One extra step that was included, that is not in the paper for * curves but is for surfaces, is the fact that sometimes the curve is * not clipped enough, if the maximum clip is less than .2 than we sub * divide the curve in three equal parts, at .3 and .6, * Subdivision is done using the Oslo Algorithm, rather than the other * methods which were prossed. */ void rt_clip_cnurb(struct bu_list *plist, struct edge_g_cnurb *crv, fastf_t u, fastf_t v) { fastf_t ds1, dt1; struct _interior_line s_line, t_line; int axis, i; fastf_t umin, umax; int coords; struct edge_g_cnurb * c1, *c2, *tmp; fastf_t m1, m2; int zero_changed; fastf_t *ptr; fastf_t dist[10]; coords = RT_NURB_EXTRACT_COORDS( crv->pt_type); s_line.axis = 0; s_line.o_dist = v; t_line.axis = 1; t_line.o_dist = u; ds1 = 0.0; dt1 = 0.0; ptr = crv->ctl_points; /* determine what axis to clip against */ for ( i = 0; i < crv->c_size; i++, ptr += coords) { ds1 += fabs( rt_trim_line_pt_dist( &s_line, ptr, crv->pt_type) ); dt1 += fabs( rt_trim_line_pt_dist( &t_line, ptr, crv->pt_type) ); } if ( ds1 >= dt1 ) axis = 0; else axis = 1; ptr = crv->ctl_points; for ( i = 0; i < crv->c_size; i++) { if ( axis == 1) dist[i] = rt_trim_line_pt_dist(&t_line, ptr, crv->pt_type); else dist[i] = rt_trim_line_pt_dist(&s_line, ptr, crv->pt_type); ptr += coords; } /* Find the convex hull of the distances and determine the * minimum and maximum distance to clip against. See the * paper for details about this step */ umin = 10e40; umax = -10e40; zero_changed = 0; for ( i = 0; i < crv->c_size; i++) { fastf_t d1, d2; fastf_t x0, x1, zero; if ( i == (crv->c_size -1 ) ) { d1 = dist[i]; d2 = dist[0]; x0 = (fastf_t) i / (fastf_t) (crv->c_size - 1); x1 = 0.0; } else { d1 = dist[i]; d2 = dist[i+1]; x0 = (fastf_t) i / (fastf_t) (crv->c_size - 1 ); x1 = (i+1.0) / (crv->c_size - 1); } if ( _SIGN(d1) != _SIGN(d2) ) { zero = x0 - d1 * (x1 - x0)/ (d2-d1); if ( zero <= umin) umin = zero * .99; if ( zero >= umax) umax = zero * .99 + .01; zero_changed = 1; } } if ( !zero_changed) return; /* Clip is not large enough, split in thiords and try again */ if ( umax - umin < .2) { umin = .3; umax = .6; } /* Translate the 0.0-->1.09 clipping against the real knots */ m1 = (crv->k.knots[0] * (1 - umin)) + crv->k.knots[crv->k.k_size -1] * umin; m2 = (crv->k.knots[0] * (1-umax)) + crv->k.knots[crv->k.k_size -1] * umax; /* subdivide the curve */ c1 = (struct edge_g_cnurb *) rt_nurb_c_xsplit(crv, m1); c2 = rt_nurb_c_xsplit((struct edge_g_cnurb *) c1->l.forw, m2); tmp = (struct edge_g_cnurb *) c1->l.forw; BU_LIST_DEQUEUE( &tmp->l); rt_nurb_free_cnurb( tmp ); BU_LIST_INIT( plist ); BU_LIST_INSERT( &c2->l, plist); BU_LIST_APPEND( plist, &c1->l); }
/** * Make a list of all edgeuses which are at the same distance as the * first element on the list. Toss out opposing pairs of edgeuses of the * same edge. * */ HIDDEN void make_near_list(struct edge_info *edge_list, struct bu_list *near1, const struct bn_tol *tol) { struct edge_info *ei; struct edge_info *ei_p; struct edge_info *tmp; fastf_t dist; BU_CK_LIST_HEAD(&edge_list->l); BU_CK_LIST_HEAD(near1); /* toss opposing pairs of uses of the same edge from the list */ ei = BU_LIST_FIRST(edge_info, &edge_list->l); while (BU_LIST_NOT_HEAD(&ei->l, &edge_list->l)) { NMG_CK_EI(ei); ei_p = BU_LIST_FIRST(edge_info, &edge_list->l); while (BU_LIST_NOT_HEAD(&ei_p->l, &edge_list->l)) { NMG_CK_EI(ei_p); NMG_CK_VED(ei_p->ved_p); /* if we've found an opposing use of the same * edge toss the pair of them */ if (ei_p->ved_p->magic_p == ei->ved_p->magic_p && ei_p->eu_p->eumate_p->vu_p->v_p == ei->eu_p->vu_p->v_p && ei_p->eu_p->vu_p->v_p == ei->eu_p->eumate_p->vu_p->v_p) { if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) { bu_log("tossing edgeuse pair:\n"); bu_log("(%g %g %g) -> (%g %g %g)\n", V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord), V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord)); bu_log("(%g %g %g) -> (%g %g %g)\n", V3ARGS(ei_p->eu_p->vu_p->v_p->vg_p->coord), V3ARGS(ei_p->eu_p->eumate_p->vu_p->v_p->vg_p->coord)); } tmp = ei_p; ei_p = BU_LIST_PLAST(edge_info, &ei_p->l); BU_LIST_DEQUEUE(&tmp->l); bu_free((char *)tmp, "edge info struct"); tmp = ei; ei = BU_LIST_PLAST(edge_info, &ei->l); BU_LIST_DEQUEUE(&tmp->l); bu_free((char *)tmp, "edge info struct"); break; } ei_p = BU_LIST_PNEXT(edge_info, &ei_p->l); } ei = BU_LIST_PNEXT(edge_info, &ei->l); } if (BU_LIST_IS_EMPTY(&edge_list->l)) return; ei = BU_LIST_FIRST(edge_info, &edge_list->l); NMG_CK_EI(ei); NMG_CK_VED(ei->ved_p); dist = ei->ved_p->dist; /* create "near" list with all ei's at this dist */ for (BU_LIST_FOR(ei, edge_info, &edge_list->l)) { NMG_CK_EI(ei); NMG_CK_VED(ei->ved_p); if (NEAR_EQUAL(ei->ved_p->dist, dist, tol->dist_sq)) { ei_p = BU_LIST_PLAST(edge_info, &ei->l); BU_LIST_DEQUEUE(&ei->l); BU_LIST_APPEND(near1, &ei->l); ei = ei_p; } } if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) { bu_log("dist %g near list\n", dist); for (BU_LIST_FOR(ei, edge_info, near1)) { bu_log("\t(%g %g %g) -> (%g %g %g)\n", V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord), V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord)); bu_log("\tdist:%g class:%s status:%d\n\t\tv1(%g %g %g) v2(%g %g %g)\n", ei->ved_p->dist, nmg_class_name(ei->nmg_class), ei->ved_p->status, V3ARGS(ei->ved_p->v1->vg_p->coord), V3ARGS(ei->ved_p->v2->vg_p->coord)); bu_log("\tei->ved_p->magic_p=%p, ei->eu_p->vu_p=%p, ei->eu_p->eumate_p->vu_p=%p\n", (void *)ei->ved_p->magic_p, (void *)ei->eu_p->vu_p, (void *)ei->eu_p->eumate_p->vu_p); } }
/** * If there is no ve_dist structure for this edge, compute one and * add it to the list. * * Sort an edge_info structure into the loops list of edgeuse status */ static struct edge_info * nmg_class_pt_eu(struct fpi *fpi, struct edgeuse *eu, struct edge_info *edge_list, const int in_or_out_only) { struct bn_tol tmp_tol; struct edgeuse *next_eu; struct ve_dist *ved, *ed; struct edge_info *ei_p; struct edge_info *ei; pointp_t eu_pt; vect_t left; vect_t v_to_pt; int found_data = 0; NMG_CK_FPI(fpi); BN_CK_TOL(fpi->tol); if (RTG.NMG_debug & DEBUG_PT_FU) { bu_log("pt (%g %g %g) vs_edge (%g %g %g) (%g %g %g) (eu=%p)\n", V3ARGS(fpi->pt), V3ARGS(eu->vu_p->v_p->vg_p->coord), V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord), (void *)eu); } /* we didn't find a ve_dist structure for this edge, so we'll * have to do the calculations. */ tmp_tol = (*fpi->tol); if (in_or_out_only) { tmp_tol.dist = 0.0; tmp_tol.dist_sq = 0.0; } BU_ALLOC(ved, struct ve_dist); ved->magic_p = &eu->e_p->magic; ved->status = bn_distsq_pt3_lseg3(&ved->dist, eu->vu_p->v_p->vg_p->coord, eu->eumate_p->vu_p->v_p->vg_p->coord, fpi->pt, &tmp_tol); ved->v1 = eu->vu_p->v_p; ved->v2 = eu->eumate_p->vu_p->v_p; BU_LIST_MAGIC_SET(&ved->l, NMG_VE_DIST_MAGIC); BU_LIST_APPEND(&fpi->ve_dh, &ved->l); eu_pt = ved->v1->vg_p->coord; if (RTG.NMG_debug & DEBUG_PT_FU) { bu_log("nmg_class_pt_eu: status for eu %p (%g %g %g)<->(%g %g %g) vs pt (%g %g %g) is %d\n", (void *)eu, V3ARGS(eu->vu_p->v_p->vg_p->coord), V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord), V3ARGS(fpi->pt), ved->status); bu_log("\tdist = %g\n", ved->dist); } /* Add a struct for this edgeuse to the loop's list of dist-sorted * edgeuses. */ BU_ALLOC(ei, struct edge_info); ei->ved_p = ved; ei->eu_p = eu; BU_LIST_MAGIC_SET(&ei->l, NMG_EDGE_INFO_MAGIC); /* compute the status (ei->status) of the point WRT this edge */ switch (ved->status) { case 0: /* pt is on the edge(use) */ ei->nmg_class = NMG_CLASS_AonBshared; if (fpi->eu_func && (fpi->hits == NMG_FPI_PERUSE || (fpi->hits == NMG_FPI_PERGEOM && !found_data))) { /* need to cast eu_func pointer for actual use as a function */ void (*cfp)(struct edgeuse *, point_t, const char*); cfp = (void (*)(struct edgeuse *, point_t, const char *))fpi->eu_func; cfp(eu, fpi->pt, fpi->priv); } break; case 1: /* within tolerance of endpoint at ved->v1 */ ei->nmg_class = NMG_CLASS_AonBshared; /* add an entry for the vertex in the edge list so that * other uses of this vertex will claim the point is within * tolerance without re-computing */ BU_ALLOC(ed, struct ve_dist); ed->magic_p = &ved->v1->magic; ed->status = ved->status; ed->v1 = ed->v2 = ved->v1; BU_LIST_MAGIC_SET(&ed->l, NMG_VE_DIST_MAGIC); BU_LIST_APPEND(&fpi->ve_dh, &ed->l); if (fpi->vu_func && (fpi->hits == NMG_FPI_PERUSE || (fpi->hits == NMG_FPI_PERGEOM && !found_data))) { /* need to cast vu_func pointer for actual use as a function */ void (*cfp)(struct vertexuse *, point_t, const char*); cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func; cfp(eu->vu_p, fpi->pt, fpi->priv); } break; case 2: /* within tolerance of endpoint at ved->v2 */ ei->nmg_class = NMG_CLASS_AonBshared; /* add an entry for the vertex in the edge list so that * other uses of this vertex will claim the point is within * tolerance without re-computing */ BU_ALLOC(ed, struct ve_dist); ed->magic_p = &ved->v2->magic; ed->status = ved->status; ed->v1 = ed->v2 = ved->v2; BU_LIST_MAGIC_SET(&ed->l, NMG_VE_DIST_MAGIC); BU_LIST_APPEND(&fpi->ve_dh, &ed->l); if (fpi->vu_func && (fpi->hits == NMG_FPI_PERUSE || (fpi->hits == NMG_FPI_PERGEOM && !found_data))) { /* need to cast vu_func pointer for actual use as a function */ void (*cfp)(struct vertexuse *, point_t, const char*); cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func; cfp(eu->eumate_p->vu_p, fpi->pt, fpi->priv); } break; case 3: /* PCA of pt on line is within tolerance of ved->v1 of segment */ ei->nmg_class = nmg_class_pt_euvu(fpi->pt, eu, fpi->tol); if (ei->nmg_class == NMG_CLASS_Unknown) ei->ved_p->dist = MAX_FASTF; break; case 4: /* PCA of pt on line is within tolerance of ved->v2 of segment */ next_eu = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l); ei->nmg_class = nmg_class_pt_euvu(fpi->pt, next_eu, fpi->tol); if (ei->nmg_class == NMG_CLASS_Unknown) ei->ved_p->dist = MAX_FASTF; break; case 5: /* PCA is along length of edge, but point is NOT on edge. */ if (nmg_find_eu_left_non_unit(left, eu)) bu_bomb("can't find left vector\n"); /* take dot product of v->pt vector with left to determine * if pt is inside/left of edge */ VSUB2(v_to_pt, fpi->pt, eu_pt); if (VDOT(v_to_pt, left) > -SMALL_FASTF) ei->nmg_class = NMG_CLASS_AinB; else ei->nmg_class = NMG_CLASS_AoutB; break; default: bu_log("%s:%d status = %d\n", __FILE__, __LINE__, ved->status); bu_bomb("Why did this happen?"); break; } if (RTG.NMG_debug & DEBUG_PT_FU) { bu_log("pt @ dist %g from edge classed %s vs edge\n", ei->ved_p->dist, nmg_class_name(ei->nmg_class)); /* pl_pt_e(fpi, ei); */ } /* now that it's complete, add ei to the edge list */ for (BU_LIST_FOR(ei_p, edge_info, &edge_list->l)) { /* if the distance to this edge is smaller, or * if the distance is the same & the edge is the same * Insert edge_info struct here in list */ if (ved->dist < ei_p->ved_p->dist || (ZERO(ved->dist - ei_p->ved_p->dist) && ei_p->ved_p->magic_p == ved->magic_p)) { break; } } BU_LIST_INSERT(&ei_p->l, &ei->l); return ei; }
/* * Open/create a framebuffer object. * * Usage: * fb_open [name device [args]] */ HIDDEN int fbo_open_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { struct fb_obj *fbop; FBIO *ifp; int width = 512; int height = 512; register int c; struct bu_vls vls; if (argc == 1) { /* get list of framebuffer objects */ for (BU_LIST_FOR(fbop, fb_obj, &HeadFBObj.l)) Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), " ", (char *)NULL); return TCL_OK; } if (argc < 3) { bu_vls_init(&vls); bu_vls_printf(&vls, "helplib fb_open"); Tcl_Eval(interp, bu_vls_addr(&vls)); bu_vls_free(&vls); return TCL_ERROR; } /* process args */ bu_optind = 3; bu_opterr = 0; while ((c = bu_getopt(argc, argv, "w:W:s:S:n:N:")) != EOF) { switch (c) { case 'W': case 'w': width = atoi(bu_optarg); break; case 'N': case 'n': height = atoi(bu_optarg); break; case 'S': case 's': width = atoi(bu_optarg); height = width; break; case '?': default: Tcl_AppendResult(interp, "fb_open: bad option - ", bu_optarg, (char *)NULL); return TCL_ERROR; } } if ((ifp = fb_open(argv[2], width, height)) == FBIO_NULL) { Tcl_AppendResult(interp, "fb_open: bad device - ", argv[2], (char *)NULL); } if (fb_ioinit(ifp) != 0) { Tcl_AppendResult(interp, "fb_open: fb_ioinit() failed.", (char *) NULL); return TCL_ERROR; } BU_GETSTRUCT(fbop, fb_obj); bu_vls_init(&fbop->fbo_name); bu_vls_strcpy(&fbop->fbo_name, argv[1]); fbop->fbo_fbs.fbs_fbp = ifp; fbop->fbo_fbs.fbs_listener.fbsl_fbsp = &fbop->fbo_fbs; fbop->fbo_fbs.fbs_listener.fbsl_fd = -1; fbop->fbo_fbs.fbs_listener.fbsl_port = -1; /* append to list of fb_obj's */ BU_LIST_APPEND(&HeadFBObj.l, &fbop->l); (void)Tcl_CreateCommand(interp, bu_vls_addr(&fbop->fbo_name), (Tcl_CmdProc *)fbo_cmd, (ClientData)fbop, fbo_deleteProc); /* Return new function name as result */ Tcl_ResetResult(interp); Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), (char *)NULL); return TCL_OK; }
int ged_shells(struct ged *gedp, int argc, const char *argv[]) { struct directory *old_dp, *new_dp; struct rt_db_internal old_intern, new_intern; struct model *m_tmp, *m; struct nmgregion *r_tmp, *r; struct shell *s_tmp, *s; int shell_count=0; struct bu_vls shell_name = BU_VLS_INIT_ZERO; long **trans_tbl; static const char *usage = "nmg_model"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc != 2) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } if ((old_dp = db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_NOISY)) == RT_DIR_NULL) return GED_ERROR; if (rt_db_get_internal(&old_intern, old_dp, gedp->ged_wdbp->dbip, bn_mat_identity, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "rt_db_get_internal() error\n"); return GED_ERROR; } if (old_intern.idb_type != ID_NMG) { bu_vls_printf(gedp->ged_result_str, "Object is not an NMG!!!\n"); return GED_ERROR; } m = (struct model *)old_intern.idb_ptr; NMG_CK_MODEL(m); for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) { for (BU_LIST_FOR(s, shell, &r->s_hd)) { s_tmp = nmg_dup_shell(s, &trans_tbl, &gedp->ged_wdbp->wdb_tol); bu_free((void *)trans_tbl, "trans_tbl"); m_tmp = nmg_mmr(); r_tmp = BU_LIST_FIRST(nmgregion, &m_tmp->r_hd); BU_LIST_DEQUEUE(&s_tmp->l); BU_LIST_APPEND(&r_tmp->s_hd, &s_tmp->l); s_tmp->r_p = r_tmp; nmg_m_reindex(m_tmp, 0); nmg_m_reindex(m, 0); bu_vls_printf(&shell_name, "shell.%d", shell_count); while (db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), 0) != RT_DIR_NULL) { bu_vls_trunc(&shell_name, 0); shell_count++; bu_vls_printf(&shell_name, "shell.%d", shell_count); } /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&new_intern); new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; new_intern.idb_type = ID_NMG; new_intern.idb_meth = &OBJ[ID_NMG]; new_intern.idb_ptr = (void *)m_tmp; new_dp=db_diradd(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&new_intern.idb_type); if (new_dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "An error has occurred while adding a new object to the database.\n"); return GED_ERROR; } /* make sure the geometry/bounding boxes are up to date */ nmg_rebound(m_tmp, &gedp->ged_wdbp->wdb_tol); if (rt_db_put_internal(new_dp, gedp->ged_wdbp->dbip, &new_intern, &rt_uniresource) < 0) { /* Free memory */ nmg_km(m_tmp); bu_vls_printf(gedp->ged_result_str, "rt_db_put_internal() failure\n"); return GED_ERROR; } /* Internal representation has been freed by rt_db_put_internal */ new_intern.idb_ptr = (void *)NULL; } } bu_vls_free(&shell_name); return GED_OK; }
void Do_subfigs() { int i, j; int entity_type; struct wmember head1; struct wmember *wmem; if (RT_G_DEBUG & DEBUG_MEM_FULL) bu_mem_barriercheck(); BU_LIST_INIT(&head1.l); for (i = 0; i < totentities; i++) { int subfigdef_de; int subfigdef_index; int no_of_members; int *members; char *name = NULL; struct wmember head2; double mat_scale[3]; int non_unit; if (dir[i]->type != 408) continue; if (RT_G_DEBUG & DEBUG_MEM_FULL) bu_mem_barriercheck(); if (dir[i]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[i]->direct, dir[i]->name); continue; } Readrec(dir[i]->param); Readint(&entity_type, ""); if (entity_type != 408) { bu_log("Expected Singular Subfigure Instance Entity, found %s\n", iges_type(entity_type)); continue; } Readint(&subfigdef_de, ""); subfigdef_index = (subfigdef_de - 1)/2; if (subfigdef_index >= totentities) { bu_log("Singular Subfigure Instance Entity gives Subfigure Definition"); bu_log("\tEntity DE of %d, largest DE in file is %d\n", subfigdef_de, (totentities * 2) - 1); continue; } if (dir[subfigdef_index]->type != 308) { bu_log("Expected Subfigure Definition Entity, found %s\n", iges_type(dir[subfigdef_index]->type)); continue; } if (dir[subfigdef_index]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[subfigdef_index]->direct, dir[subfigdef_index]->name); continue; } Readrec(dir[subfigdef_index]->param); Readint(&entity_type, ""); if (entity_type != 308) { bu_log("Expected Subfigure Definition Entity, found %s\n", iges_type(entity_type)); continue; } Readint(&j, ""); /* ignore depth */ Readstrg(""); /* ignore subfigure name */ wmem = mk_addmember(dir[subfigdef_index]->name, &head1.l, NULL, WMOP_UNION); non_unit = 0; for (j = 0; j < 3; j++) { double mag_sq; mat_scale[j] = 1.0; mag_sq = MAGSQ(&(*dir[i]->rot)[j*4]); /* FIXME: arbitrary undefined tolerance */ if (!NEAR_EQUAL(mag_sq, 1.0, 100.0*SQRT_SMALL_FASTF)) { mat_scale[j] = 1.0/sqrt(mag_sq); non_unit = 1; } } if (non_unit) { bu_log("Illegal transformation matrix in %s for member %s\n", curr_file->obj_name, wmem->wm_name); bu_log(" row vector magnitudes are %g, %g, and %g\n", 1.0/mat_scale[0], 1.0/mat_scale[1], 1.0/mat_scale[2]); bn_mat_print("", *dir[i]->rot); for (j = 0; j < 11; j++) { if ((j+1)%4 == 0) continue; (*dir[i]->rot)[j] *= mat_scale[0]; } bn_mat_print("After scaling:", *dir[i]->rot); } memcpy(wmem->wm_mat, *dir[i]->rot, sizeof(mat_t)); Readint(&no_of_members, ""); /* get number of members */ members = (int *)bu_calloc(no_of_members, sizeof(int), "Do_subfigs: members"); for (j = 0; j < no_of_members; j++) Readint(&members[j], ""); BU_LIST_INIT(&head2.l); for (j = 0; j < no_of_members; j++) { int idx; idx = (members[j] - 1)/2; if (idx >= totentities) { bu_log("Subfigure Definition Entity gives Member Entity"); bu_log("\tDE of %d, largest DE in file is %d\n", members[j], (totentities * 2) - 1); continue; } if (dir[idx]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[idx]->direct, dir[idx]->name); continue; } if (dir[idx]->type == 416) { struct file_list *list_ptr; char *file_name; int found = 0; /* external reference */ Readrec(dir[idx]->param); Readint(&entity_type, ""); if (entity_type != 416) { bu_log("Expected External reference Entity, found %s\n", iges_type(entity_type)); continue; } if (dir[idx]->form != 1) { bu_log("External Reference Entity of form #%d found\n", dir[idx]->form); bu_log("\tOnly form #1 is currently handled\n"); continue; } Readname(&file_name, ""); /* Check if this external reference is already on the list */ for (BU_LIST_FOR(list_ptr, file_list, &iges_list.l)) { if (BU_STR_EQUAL(file_name, list_ptr->file_name)) { found = 1; name = list_ptr->obj_name; break; } } if (!found) { /* Need to add this one to the list */ BU_ALLOC(list_ptr, struct file_list); list_ptr->file_name = file_name; if (no_of_members == 1) bu_strlcpy(list_ptr->obj_name, dir[subfigdef_index]->name, NAMESIZE+1); else { bu_strlcpy(list_ptr->obj_name, "subfig", NAMESIZE+1); (void) Make_unique_brl_name(list_ptr->obj_name); } BU_LIST_APPEND(&curr_file->l, &list_ptr->l); name = list_ptr->obj_name; } else bu_free((char *)file_name, "Do_subfigs: file_name"); } else name = dir[idx]->name; if (no_of_members > 1) { wmem = mk_addmember(name, &head2.l, NULL, WMOP_UNION); memcpy(wmem->wm_mat, dir[idx]->rot, sizeof(mat_t)); } } if (no_of_members > 1) (void)mk_lcomb(fdout, dir[subfigdef_index]->name, &head2, 0, (char *)NULL, (char *)NULL, (unsigned char *)NULL, 0); }
struct rt_nurb_uv_hit * rt_nurb_intersect(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, double uv_tol, struct resource *res, struct bu_list *plist) { struct rt_nurb_uv_hit * h; struct face_g_snurb * psrf, * osrf; int dir, sub; point_t vmin, vmax; fastf_t u[2], v[2]; struct bu_list rni_plist; NMG_CK_SNURB(srf); h = (struct rt_nurb_uv_hit *) 0; if (plist == NULL) { plist = &rni_plist; BU_LIST_INIT(plist); } /* project the surface to a 2 dimensional problem */ /* NOTE that this gives a single snurb back, NOT a list */ psrf = rt_nurb_project_srf(srf, plane2, plane1, res); psrf->dir = 1; BU_LIST_APPEND(plist, &psrf->l); if (RT_G_DEBUG & DEBUG_SPLINE) rt_nurb_s_print("srf", psrf); /* This list starts out with only a single snurb, but more may be * added on as work progresses. */ while (BU_LIST_WHILE(psrf, face_g_snurb, plist)) { int flat; BU_LIST_DEQUEUE(&psrf->l); NMG_CK_SNURB(psrf); sub = 0; flat = 0; dir = psrf->dir; while (!flat) { fastf_t smin = 0.0, smax = 0.0; sub++; dir = (dir == 0)?1:0; /* change direction */ if (RT_G_DEBUG & DEBUG_SPLINE) rt_nurb_s_print("psrf", psrf); rt_nurb_pbound(psrf, vmin, vmax); /* Check for origin to be included in the bounding box */ if (!(vmin[0] <= 0.0 && vmin[1] <= 0.0 && vmax[0] >= 0.0 && vmax[1] >= 0.0)) { if (RT_G_DEBUG & DEBUG_SPLINE) bu_log("this srf doesn't include the origin\n"); flat = 1; rt_nurb_free_snurb(psrf, res); continue; } rt_nurb_clip_srf(psrf, dir, &smin, &smax); if ((smax - smin) > .8) { struct rt_nurb_uv_hit *hp; /* Split surf, requeue both sub-surfs at head */ /* New surfs will have same dir as arg, here */ if (RT_G_DEBUG & DEBUG_SPLINE) bu_log("splitting this surface\n"); rt_nurb_s_split(plist, psrf, dir, res); rt_nurb_free_snurb(psrf, res); hp = rt_nurb_intersect(srf, plane1, plane2, uv_tol, res, plist); return hp; } if (smin > 1.0 || smax < 0.0) { if (RT_G_DEBUG & DEBUG_SPLINE) bu_log("eliminating this surface (smin=%g, smax=%g)\n", smin, smax); flat = 1; rt_nurb_free_snurb(psrf, res); continue; } if (dir == RT_NURB_SPLIT_ROW) { smin = (1.0 - smin) * psrf->u.knots[0] + smin * psrf->u.knots[ psrf->u.k_size -1]; smax = (1.0 - smax) * psrf->u.knots[0] + smax * psrf->u.knots[ psrf->u.k_size -1]; } else { smin = (1.0 - smin) * psrf->v.knots[0] + smin * psrf->v.knots[ psrf->v.k_size -1]; smax = (1.0 - smax) * psrf->v.knots[0] + smax * psrf->v.knots[ psrf->v.k_size -1]; } osrf = psrf; psrf = (struct face_g_snurb *) rt_nurb_region_from_srf( osrf, dir, smin, smax, res); psrf->dir = dir; rt_nurb_free_snurb(osrf, res); if (RT_G_DEBUG & DEBUG_SPLINE) { bu_log("After call to rt_nurb_region_from_srf() (smin=%g, smax=%g)\n", smin, smax); rt_nurb_s_print("psrf", psrf); } u[0] = psrf->u.knots[0]; u[1] = psrf->u.knots[psrf->u.k_size -1]; v[0] = psrf->v.knots[0]; v[1] = psrf->v.knots[psrf->v.k_size -1]; if ((u[1] - u[0]) < uv_tol && (v[1] - v[0]) < uv_tol) { struct rt_nurb_uv_hit * hit; if (RT_G_DEBUG & DEBUG_SPLINE) { fastf_t p1[4], p2[4]; int coords; vect_t diff; coords = RT_NURB_EXTRACT_COORDS(srf->pt_type); rt_nurb_s_eval(srf, u[0], v[0], p1); rt_nurb_s_eval(srf, u[1], v[1], p2); if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) { fastf_t inv_w; inv_w = 1.0 / p1[coords-1]; VSCALE(p1, p1, inv_w); inv_w = 1.0 / p2[coords-1]; VSCALE(p2, p2, inv_w); } VSUB2(diff, p1, p2); bu_log("Precision of hit point = %g (%f %f %f) <-> (%f %f %f)\n", MAGNITUDE(diff), V3ARGS(p1), V3ARGS(p2)); } hit = (struct rt_nurb_uv_hit *) bu_malloc( sizeof(struct rt_nurb_uv_hit), "hit"); hit->next = (struct rt_nurb_uv_hit *)0; hit->sub = sub; hit->u = (u[0] + u[1])/2.0; hit->v = (v[0] + v[1])/2.0; if (h == (struct rt_nurb_uv_hit *)0) h = hit; else { hit->next = h; h = hit; } flat = 1; rt_nurb_free_snurb(psrf, res); } if ((u[1] - u[0]) > (v[1] - v[0])) dir = 1; else dir = 0; } } return (struct rt_nurb_uv_hit *)h; }
/** * 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; }
struct bu_mapped_file * bu_open_mapped_file(const char *name, const char *appl) /* file name */ /* non-null only when app. will use 'apbuf' */ { struct bu_mapped_file *mp = (struct bu_mapped_file *)NULL; char *real_path = bu_realpath(name, NULL); #ifdef HAVE_SYS_STAT_H struct stat sb; int fd = -1; /* unix file descriptor */ int readval; ssize_t bytes_to_go, nbytes; #else FILE *fp = (FILE *)NULL; /* stdio file pointer */ #endif int ret; if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE)) bu_log("bu_open_mapped_file(%s(canonical path - %s), %s)\n", name, real_path, appl?appl:"(NIL)"); /* See if file has already been mapped, and can be shared */ bu_semaphore_acquire(BU_SEM_MAPPEDFILE); if (!BU_LIST_IS_INITIALIZED(&bu_mapped_file_list)) { BU_LIST_INIT(&bu_mapped_file_list); } for (BU_LIST_FOR(mp, bu_mapped_file, &bu_mapped_file_list)) { BU_CK_MAPPED_FILE(mp); /* find a match */ if (!BU_STR_EQUAL(real_path, mp->name)) continue; if (appl && !BU_STR_EQUAL(appl, mp->appl)) continue; /* found a match */ /* if mapped file still exists, verify size and modtime */ if (!mp->dont_restat) { bu_semaphore_acquire(BU_SEM_SYSCALL); fd = open(real_path, O_RDONLY | O_BINARY); bu_semaphore_release(BU_SEM_SYSCALL); /* If file didn't vanish from disk, make sure it's the same file */ if (fd >= 0) { #ifdef HAVE_SYS_STAT_H bu_semaphore_acquire(BU_SEM_SYSCALL); ret = fstat(fd, &sb); bu_semaphore_release(BU_SEM_SYSCALL); if (ret < 0) { /* odd, open worked but fstat failed. assume it * vanished from disk and the mapped copy is still * OK. */ bu_semaphore_acquire(BU_SEM_SYSCALL); (void)close(fd); bu_semaphore_release(BU_SEM_SYSCALL); fd = -1; } if ((size_t)sb.st_size != mp->buflen) { bu_log("bu_open_mapped_file(%s) WARNING: File size changed from %ld to %ld, opening new version.\n", real_path, mp->buflen, sb.st_size); /* mp doesn't reflect the file any longer. Invalidate. */ mp->appl = bu_strdup("__STALE__"); /* Can't invalidate old copy, it may still be in use. */ break; } if (sb.st_mtime != mp->modtime) { bu_log("bu_open_mapped_file(%s) WARNING: File modified since last mapped, opening new version.\n", real_path); /* mp doesn't reflect the file any longer. Invalidate. */ mp->appl = bu_strdup("__STALE__"); /* Can't invalidate old copy, it may still be in use. */ break; } /* To be completely safe, should check st_dev and st_inum */ #endif } /* It is safe to reuse mp */ mp->uses++; bu_semaphore_release(BU_SEM_MAPPEDFILE); if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE)) bu_pr_mapped_file("open_reused", mp); return mp; } /* It is safe to reuse mp */ mp->uses++; return mp; } /* done iterating over mapped file list */ bu_semaphore_release(BU_SEM_MAPPEDFILE); /* necessary in case we take a 'fail' path before BU_ALLOC() */ mp = NULL; /* File is not yet mapped or has changed, open file read only if * we didn't find it earlier. */ #ifdef HAVE_SYS_STAT_H if (fd < 0) { bu_semaphore_acquire(BU_SEM_SYSCALL); fd = open(real_path, O_RDONLY | O_BINARY); bu_semaphore_release(BU_SEM_SYSCALL); } if (UNLIKELY(fd < 0)) { if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE)) perror(real_path); goto fail; } bu_semaphore_acquire(BU_SEM_SYSCALL); ret = fstat(fd, &sb); bu_semaphore_release(BU_SEM_SYSCALL); if (UNLIKELY(ret < 0)) { perror(real_path); goto fail; } if (UNLIKELY(sb.st_size == 0)) { bu_log("bu_open_mapped_file(%s) 0-length file\n", real_path); goto fail; } #endif /* HAVE_SYS_STAT_H */ /* Optimistically assume that things will proceed OK */ BU_ALLOC(mp, struct bu_mapped_file); mp->name = bu_strdup(real_path); if (appl) mp->appl = bu_strdup(appl); #ifdef HAVE_SYS_STAT_H mp->buflen = sb.st_size; mp->modtime = sb.st_mtime; # ifdef HAVE_SYS_MMAN_H /* Attempt to access as memory-mapped file */ bu_semaphore_acquire(BU_SEM_SYSCALL); mp->buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); bu_semaphore_release(BU_SEM_SYSCALL); if (UNLIKELY(mp->buf == MAP_FAILED)) perror(real_path); if (mp->buf != MAP_FAILED) { /* OK, its memory mapped in! */ mp->is_mapped = 1; /* It's safe to close the fd now, the manuals say */ } else # endif /* HAVE_SYS_MMAN_H */ { /* Allocate a local zero'd buffer, and slurp it in always * leaving space for a trailing zero. */ mp->buf = bu_calloc(1, sb.st_size+1, real_path); nbytes = 0; bytes_to_go = sb.st_size; bu_semaphore_acquire(BU_SEM_SYSCALL); while (nbytes < sb.st_size) { readval = read(fd, ((char *)(mp->buf)) + nbytes, ((bytes_to_go > INT_MAX) ? (INT_MAX) : (bytes_to_go))); if (UNLIKELY(readval < 0)) { bu_semaphore_release(BU_SEM_SYSCALL); perror(real_path); bu_free(mp->buf, real_path); goto fail; } else { nbytes += readval; bytes_to_go -= readval; } } bu_semaphore_release(BU_SEM_SYSCALL); if (UNLIKELY(nbytes != sb.st_size)) { perror(real_path); bu_free(mp->buf, real_path); goto fail; } } #else /* !HAVE_SYS_STAT_H */ /* Read it in with stdio, with no clue how big it is */ bu_semaphore_acquire(BU_SEM_SYSCALL); fp = fopen(real_path, "rb"); bu_semaphore_release(BU_SEM_SYSCALL); if (UNLIKELY(fp == NULL)) { perror(real_path); goto fail; } /* Read it once to see how large it is */ { char buf[32768] = {0}; int got; mp->buflen = 0; bu_semaphore_acquire(BU_SEM_SYSCALL); while ((got = fread(buf, 1, sizeof(buf), fp)) > 0) mp->buflen += got; rewind(fp); bu_semaphore_release(BU_SEM_SYSCALL); } /* Allocate the necessary buffer */ mp->buf = bu_calloc(1, mp->buflen+1, real_path); /* Read it again into the buffer */ bu_semaphore_acquire(BU_SEM_SYSCALL); ret = fread(mp->buf, mp->buflen, 1, fp); bu_semaphore_release(BU_SEM_SYSCALL); if (UNLIKELY(ret != 1)) { bu_semaphore_acquire(BU_SEM_SYSCALL); perror("fread"); fclose(fp); bu_semaphore_release(BU_SEM_SYSCALL); bu_log("bu_open_mapped_file() 2nd fread failed? len=%d\n", mp->buflen); bu_free(mp->buf, "non-unix fread buf"); goto fail; } bu_semaphore_acquire(BU_SEM_SYSCALL); fclose(fp); bu_semaphore_release(BU_SEM_SYSCALL); #endif if (fd >= 0) { bu_semaphore_acquire(BU_SEM_SYSCALL); (void)close(fd); bu_semaphore_release(BU_SEM_SYSCALL); } mp->uses = 1; mp->l.magic = BU_MAPPED_FILE_MAGIC; bu_semaphore_acquire(BU_SEM_MAPPEDFILE); BU_LIST_APPEND(&bu_mapped_file_list, &mp->l); bu_semaphore_release(BU_SEM_MAPPEDFILE); if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE)) { bu_pr_mapped_file("1st_open", mp); } if (real_path) { bu_free(real_path, "real_path alloc from bu_realpath"); } return mp; fail: if (fd >= 0) { bu_semaphore_acquire(BU_SEM_SYSCALL); (void)close(fd); bu_semaphore_release(BU_SEM_SYSCALL); } if (mp) { bu_free(mp->name, "mp->name"); if (mp->appl) bu_free(mp->appl, "mp->appl"); /* Don't free mp->buf here, it might not be bu_malloced but mmaped */ bu_free(mp, "mp from bu_open_mapped_file fail"); } if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE)) bu_log("bu_open_mapped_file(%s, %s) can't open file\n", real_path, appl ? appl: "(NIL)"); if (real_path) { bu_free(real_path, "real_path alloc from bu_realpath"); } return (struct bu_mapped_file *)NULL; }
int _ged_run_rtwizard(struct ged *gedp) { int i; FILE *fp_in; #ifndef _WIN32 int pipe_in[2]; int pipe_err[2]; #else HANDLE pipe_in[2], pipe_inDup; HANDLE pipe_err[2], pipe_errDup; STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; SECURITY_ATTRIBUTES sa = {0}; struct bu_vls line = BU_VLS_INIT_ZERO; #endif struct ged_run_rt *run_rtp; struct _ged_rt_client_data *drcdp; #ifndef _WIN32 int pid; int ret; ret = pipe(pipe_in); if (ret < 0) perror("pipe"); ret = pipe(pipe_err); if (ret < 0) perror("pipe"); if ((pid = fork()) == 0) { /* make this a process group leader */ setpgid(0, 0); /* Redirect stdin and stderr */ (void)close(0); ret = dup(pipe_in[0]); if (ret < 0) perror("dup"); (void)close(2); ret = dup(pipe_err[1]); if (ret < 0) perror("dup"); /* close pipes */ (void)close(pipe_in[0]); (void)close(pipe_in[1]); (void)close(pipe_err[0]); (void)close(pipe_err[1]); for (i = 3; i < 20; i++) (void)close(i); (void)execvp(gedp->ged_gdp->gd_rt_cmd[0], gedp->ged_gdp->gd_rt_cmd); perror(gedp->ged_gdp->gd_rt_cmd[0]); exit(16); } /* As parent, send view information down pipe */ (void)close(pipe_in[0]); fp_in = fdopen(pipe_in[1], "w"); (void)close(pipe_err[1]); (void)fclose(fp_in); /* must be BU_GET() to match release in _ged_rt_output_handler */ BU_GET(run_rtp, struct ged_run_rt); BU_LIST_INIT(&run_rtp->l); BU_LIST_APPEND(&gedp->ged_gdp->gd_headRunRt.l, &run_rtp->l); run_rtp->fd = pipe_err[0]; run_rtp->pid = pid; /* must be BU_GET() to match release in _ged_rt_output_handler */ BU_GET(drcdp, struct _ged_rt_client_data); drcdp->gedp = gedp; drcdp->rrtp = run_rtp; Tcl_CreateFileHandler(run_rtp->fd, TCL_READABLE, _ged_rt_output_handler, (ClientData)drcdp); return 0; #else sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* Create a pipe for the child process's STDOUT. */ CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0); /* Create noninheritable read handle and close the inheritable read handle. */ DuplicateHandle(GetCurrentProcess(), pipe_err[0], GetCurrentProcess(), &pipe_errDup , 0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(pipe_err[0]); /* Create a pipe for the child process's STDIN. */ CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0); /* Duplicate the write handle to the pipe so it is not inherited. */ DuplicateHandle(GetCurrentProcess(), pipe_in[1], GetCurrentProcess(), &pipe_inDup, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); CloseHandle(pipe_in[1]); si.cb = sizeof(STARTUPINFO); si.lpReserved = NULL; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.lpDesktop = NULL; si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = pipe_in[0]; si.hStdOutput = pipe_err[1]; si.hStdError = pipe_err[1]; for (i = 0; i < gedp->ged_gdp->gd_rt_cmd_len; i++) { bu_vls_printf(&line, "\"%s\" ", gedp->ged_gdp->gd_rt_cmd[i]); } CreateProcess(NULL, bu_vls_addr(&line), NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi); bu_vls_free(&line); CloseHandle(pipe_in[0]); CloseHandle(pipe_err[1]); /* As parent, send view information down pipe */ fp_in = _fdopen(_open_osfhandle((intptr_t)pipe_inDup, _O_TEXT), "wb"); (void)fclose(fp_in); /* must be BU_GET() to match release in _ged_rt_output_handler */ BU_GET(run_rtp, struct ged_run_rt); BU_LIST_INIT(&run_rtp->l); BU_LIST_APPEND(&gedp->ged_gdp->gd_headRunRt.l, &run_rtp->l); run_rtp->fd = pipe_errDup; run_rtp->hProcess = pi.hProcess; run_rtp->pid = pi.dwProcessId; run_rtp->aborted=0; run_rtp->chan = Tcl_MakeFileChannel(run_rtp->fd, TCL_READABLE); /* must be BU_GET() to match release in _ged_rt_output_handler */ BU_GET(drcdp, struct _ged_rt_client_data); drcdp->gedp = gedp; drcdp->rrtp = run_rtp; Tcl_CreateChannelHandler(run_rtp->chan, TCL_READABLE, _ged_rt_output_handler, (ClientData)drcdp); return 0; #endif }
/* * F _ N I R T * * Invoke nirt with the current view & stuff */ int dgo_nirt_cmd(struct dg_obj *dgop, struct view_obj *vop, int argc, const char **argv) { const char **vp; FILE *fp_in; FILE *fp_out, *fp_err; #ifndef _WIN32 int ret; size_t sret; int pid, rpid; int retcode; int pipe_in[2]; int pipe_out[2]; int pipe_err[2]; #else HANDLE pipe_in[2], pipe_inDup; HANDLE pipe_out[2], pipe_outDup; HANDLE pipe_err[2], pipe_errDup; STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; char name[1024]; char line1[2048]; int rem = 2048; #endif int use_input_orig = 0; vect_t center_model; vect_t dir; vect_t cml; int i; struct solid *sp; char line[RT_MAXLINE]; char *val; struct bu_vls vls = BU_VLS_INIT_ZERO; struct bu_vls o_vls = BU_VLS_INIT_ZERO; struct bu_vls p_vls = BU_VLS_INIT_ZERO; struct bu_vls t_vls = BU_VLS_INIT_ZERO; struct bn_vlblock *vbp; struct dg_qray_dataList *ndlp; struct dg_qray_dataList HeadQRayData; int args; args = argc + 20 + 2 + dgo_count_tops((struct solid *)&dgop->dgo_headSolid); dgop->dgo_rt_cmd = (char **)bu_calloc(args, sizeof(char *), "alloc dgo_rt_cmd"); vp = (const char **)&dgop->dgo_rt_cmd[0]; *vp++ = "nirt"; /* swipe x, y, z off the end if present */ if (argc > 3) { double scan[3]; if (sscanf(argv[argc-3], "%lf", &scan[X]) == 1 && sscanf(argv[argc-2], "%lf", &scan[Y]) == 1 && sscanf(argv[argc-1], "%lf", &scan[Z]) == 1) { VMOVE(center_model, scan); use_input_orig = 1; argc -= 3; VSCALE(center_model, center_model, dgop->dgo_wdbp->dbip->dbi_local2base); } } /* Calculate point from which to fire ray */ if (!use_input_orig) { VSET(center_model, -vop->vo_center[MDX], -vop->vo_center[MDY], -vop->vo_center[MDZ]); } VSCALE(cml, center_model, dgop->dgo_wdbp->dbip->dbi_base2local); VMOVEN(dir, vop->vo_rotation + 8, 3); VSCALE(dir, dir, -1.0); bu_vls_printf(&p_vls, "xyz %lf %lf %lf;", cml[X], cml[Y], cml[Z]); bu_vls_printf(&p_vls, "dir %lf %lf %lf; s", dir[X], dir[Y], dir[Z]); i = 0; if (DG_QRAY_GRAPHICS(dgop)) { *vp++ = "-e"; *vp++ = DG_QRAY_FORMAT_NULL; /* first ray ---- returns partitions */ *vp++ = "-e"; *vp++ = DG_QRAY_FORMAT_P; /* ray start, direction, and 's' command */ *vp++ = "-e"; *vp++ = bu_vls_addr(&p_vls); /* second ray ---- returns overlaps */ *vp++ = "-e"; *vp++ = DG_QRAY_FORMAT_O; /* ray start, direction, and 's' command */ *vp++ = "-e"; *vp++ = bu_vls_addr(&p_vls); if (DG_QRAY_TEXT(dgop)) { char *cp; int count = 0; /* get 'r' format now; prepend its' format string with a newline */ val = bu_vls_addr(&dgop->dgo_qray_fmts[0].fmt); /* find first '"' */ while (*val != '"' && *val != '\0') ++val; if (*val == '\0') goto done; else ++val; /* skip first '"' */ /* find last '"' */ cp = (char *)strrchr(val, '"'); if (cp != (char *)NULL) /* found it */ count = cp - val; done: if (*val == '\0') bu_vls_printf(&o_vls, " fmt r \"\\n\" "); else { struct bu_vls tmp = BU_VLS_INIT_ZERO; bu_vls_strncpy(&tmp, val, count); bu_vls_printf(&o_vls, " fmt r \"\\n%V\" ", &tmp); bu_vls_free(&tmp); if (count) val += count + 1; bu_vls_printf(&o_vls, "%s", val); } i = 1; *vp++ = "-e"; *vp++ = bu_vls_addr(&o_vls); } } if (DG_QRAY_TEXT(dgop)) { /* load vp with formats for printing */ for (; dgop->dgo_qray_fmts[i].type != (char)0; ++i) bu_vls_printf(&t_vls, "fmt %c %s; ", dgop->dgo_qray_fmts[i].type, bu_vls_addr(&dgop->dgo_qray_fmts[i].fmt)); *vp++ = "-e"; *vp++ = bu_vls_addr(&t_vls); /* nirt does not like the trailing ';' */ bu_vls_trunc(&t_vls, -2); } /* include nirt script string */ if (bu_vls_strlen(&dgop->dgo_qray_script)) { *vp++ = "-e"; *vp++ = bu_vls_addr(&dgop->dgo_qray_script); } *vp++ = "-e"; *vp++ = bu_vls_addr(&p_vls); for (i = 1; i < argc; i++) *vp++ = argv[i]; *vp++ = dgop->dgo_wdbp->dbip->dbi_filename; dgop->dgo_rt_cmd_len = (char **)vp - (char **)dgop->dgo_rt_cmd; /* Note - dgo_build_tops sets the last vp to (char *)0 */ dgop->dgo_rt_cmd_len += dgo_build_tops((struct solid *)&dgop->dgo_headSolid, vp, (const char **)&dgop->dgo_rt_cmd[args]); if (dgop->dgo_qray_cmd_echo) { /* Print out the command we are about to run */ vp = (const char **)&dgop->dgo_rt_cmd[0]; while (*vp) Tcl_AppendResult(dgop->interp, *vp++, " ", (char *)NULL); Tcl_AppendResult(dgop->interp, "\n", (char *)NULL); } if (use_input_orig) { bu_vls_printf(&vls, "\nFiring from (%lf, %lf, %lf)...\n", center_model[X], center_model[Y], center_model[Z]); Tcl_AppendResult(dgop->interp, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); } else Tcl_AppendResult(dgop->interp, "\nFiring from view center...\n", (char *)NULL); #ifndef _WIN32 ret = pipe(pipe_in); if (ret < 0) perror("pipe"); ret = pipe(pipe_out); if (ret < 0) perror("pipe"); ret = pipe(pipe_err); if (ret < 0) perror("pipe"); (void)signal(SIGINT, SIG_IGN); if ((pid = fork()) == 0) { /* Redirect stdin, stdout, stderr */ (void)close(0); ret = dup(pipe_in[0]); if (ret < 0) perror("dup"); (void)close(1); ret = dup(pipe_out[1]); if (ret < 0) perror("dup"); (void)close(2); ret = dup(pipe_err[1]); if (ret < 0) perror("dup"); /* close pipes */ (void)close(pipe_in[0]); (void)close(pipe_in[1]); (void)close(pipe_out[0]); (void)close(pipe_out[1]); (void)close(pipe_err[0]); (void)close(pipe_err[1]); for (i = 3; i < 20; i++) (void)close(i); (void)signal(SIGINT, SIG_DFL); (void)execvp(dgop->dgo_rt_cmd[0], dgop->dgo_rt_cmd); perror (dgop->dgo_rt_cmd[0]); exit(16); } /* use fp_in to feed view info to nirt */ (void)close(pipe_in[0]); fp_in = fdopen(pipe_in[1], "w"); /* use fp_out to read back the result */ (void)close(pipe_out[1]); fp_out = fdopen(pipe_out[0], "r"); /* use fp_err to read any error messages */ (void)close(pipe_err[1]); fp_err = fdopen(pipe_err[0], "r"); /* send quit command to nirt */ sret = fwrite("q\n", 1, 2, fp_in); if (sret != 2) bu_log("fwrite failure\n"); (void)fclose(fp_in); #else memset((void *)&si, 0, sizeof(STARTUPINFO)); memset((void *)&pi, 0, sizeof(PROCESS_INFORMATION)); memset((void *)&sa, 0, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* Create a pipe for the child process's STDOUT. */ CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0); /* Create noninheritable read handle and close the inheritable read handle. */ DuplicateHandle(GetCurrentProcess(), pipe_out[0], GetCurrentProcess(), &pipe_outDup , 0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(pipe_out[0]); /* Create a pipe for the child process's STDERR. */ CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0); /* Create noninheritable read handle and close the inheritable read handle. */ DuplicateHandle(GetCurrentProcess(), pipe_err[0], GetCurrentProcess(), &pipe_errDup , 0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(pipe_err[0]); /* The steps for redirecting child process's STDIN: * 1. Save current STDIN, to be restored later. * 2. Create anonymous pipe to be STDIN for child process. * 3. Set STDIN of the parent to be the read handle to the * pipe, so it is inherited by the child process. * 4. Create a noninheritable duplicate of the write handle, * and close the inheritable write handle. */ /* Create a pipe for the child process's STDIN. */ CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0); /* Duplicate the write handle to the pipe so it is not inherited. */ DuplicateHandle(GetCurrentProcess(), pipe_in[1], GetCurrentProcess(), &pipe_inDup, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); CloseHandle(pipe_in[1]); si.cb = sizeof(STARTUPINFO); si.lpReserved = NULL; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.lpDesktop = NULL; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdInput = pipe_in[0]; si.hStdOutput = pipe_out[1]; si.hStdError = pipe_err[1]; si.wShowWindow = SW_HIDE; snprintf(line1, rem, "%s ", dgop->dgo_rt_cmd[0]); rem -= (int)strlen(line1) - 1; for (i = 1; i < dgop->dgo_rt_cmd_len; i++) { /* skip commands */ if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL) ++i; else { /* append other arguments (i.e. options, file and obj(s)) */ snprintf(name, 1024, "\"%s\" ", dgop->dgo_rt_cmd[i]); if (rem - strlen(name) < 1) { bu_log("Ran out of buffer space!"); bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd"); dgop->dgo_rt_cmd = NULL; return TCL_ERROR; } bu_strlcat(line1, name, sizeof(line1)); rem -= (int)strlen(name); } } CreateProcess(NULL, line1, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi); /* use fp_in to feed view info to nirt */ CloseHandle(pipe_in[0]); fp_in = _fdopen(_open_osfhandle((intptr_t)pipe_inDup, _O_TEXT), "wb"); setmode(fileno(fp_in), O_BINARY); /* send commands down the pipe */ for (i = 1; i < dgop->dgo_rt_cmd_len-2; i++) if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL) fprintf(fp_in, "%s\n", dgop->dgo_rt_cmd[++i]); /* use fp_out to read back the result */ CloseHandle(pipe_out[1]); fp_out = _fdopen(_open_osfhandle((intptr_t)pipe_outDup, _O_TEXT), "rb"); setmode(fileno(fp_out), O_BINARY); /* use fp_err to read any error messages */ CloseHandle(pipe_err[1]); fp_err = _fdopen(_open_osfhandle((intptr_t)pipe_errDup, _O_TEXT), "rb"); setmode(fileno(fp_err), O_BINARY); /* send quit command to nirt */ fwrite("q\n", 1, 2, fp_in); (void)fclose(fp_in); #endif bu_vls_free(&p_vls); /* use to form "partition" part of nirt command above */ if (DG_QRAY_GRAPHICS(dgop)) { double scan[4]; if (DG_QRAY_TEXT(dgop)) bu_vls_free(&o_vls); /* used to form "overlap" part of nirt command above */ BU_LIST_INIT(&HeadQRayData.l); /* handle partitions */ while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) { if (line[0] == '\n') { Tcl_AppendResult(dgop->interp, line+1, (char *)NULL); break; } BU_ALLOC(ndlp, struct dg_qray_dataList); BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l); if (sscanf(line, "%le %le %le %le", &scan[0], &scan[1], &scan[2], &scan[3]) != 4) break; ndlp->x_in = scan[0]; ndlp->y_in = scan[1]; ndlp->z_in = scan[2]; ndlp->los = scan[3]; } vbp = rt_vlblock_init(); dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 0); bu_list_free(&HeadQRayData.l); dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0); rt_vlblock_free(vbp); /* handle overlaps */ while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) { if (line[0] == '\n') { Tcl_AppendResult(dgop->interp, line+1, (char *)NULL); break; } BU_ALLOC(ndlp, struct dg_qray_dataList); BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l); if (sscanf(line, "%le %le %le %le", &scan[0], &scan[1], &scan[2], &scan[3]) != 4) break; ndlp->x_in = scan[0]; ndlp->y_in = scan[1]; ndlp->z_in = scan[2]; ndlp->los = scan[3]; } vbp = rt_vlblock_init(); dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 1); bu_list_free(&HeadQRayData.l); dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0); rt_vlblock_free(vbp); } /* * Notify observers, if any, before generating textual output since * such an act (observer notification) wipes out whatever gets stuffed * into the result. */ dgo_notify(dgop); if (DG_QRAY_TEXT(dgop)) { bu_vls_free(&t_vls); while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) Tcl_AppendResult(dgop->interp, line, (char *)NULL); } (void)fclose(fp_out); while (bu_fgets(line, RT_MAXLINE, fp_err) != (char *)NULL) Tcl_AppendResult(dgop->interp, line, (char *)NULL); (void)fclose(fp_err); #ifndef _WIN32 /* Wait for program to finish */ while ((rpid = wait(&retcode)) != pid && rpid != -1) ; /* NULL */ if (retcode != 0) pr_wait_status(dgop->interp, retcode); #else /* Wait for program to finish */ WaitForSingleObject(pi.hProcess, INFINITE); #endif FOR_ALL_SOLIDS(sp, &dgop->dgo_headSolid) sp->s_wflag = DOWN; bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd"); dgop->dgo_rt_cmd = NULL; return TCL_OK; }
static void tree_solids(union tree *tp, struct tree_bark *tb, int op, struct resource *resp) { RT_CK_TREE(tp); switch (tp->tr_op) { case OP_NOP: return; case OP_SOLID: { struct reg_db_internals *dbint; matp_t mp; long sol_id = 0; struct rt_ell_internal *ell_p; vect_t v; int ret; BU_ALLOC(dbint, struct reg_db_internals); BU_LIST_INIT_MAGIC(&(dbint->l), DBINT_MAGIC); if (tp->tr_a.tu_stp->st_matp) mp = tp->tr_a.tu_stp->st_matp; else mp = (matp_t)bn_mat_identity; /* Get the internal form of this solid & add it to the list */ ret = rt_db_get_internal(&dbint->ip, tp->tr_a.tu_stp->st_dp, tb->dbip, mp, resp); if (ret < 0) { bu_log("Failure reading %s object from database.\n", OBJ[sol_id].ft_name); return; } RT_CK_DB_INTERNAL(&dbint->ip); dbint->st_p = tp->tr_a.tu_stp; sol_id = dbint->ip.idb_type; if (sol_id < 0) { bu_log("Primitive ID %ld out of bounds\n", sol_id); bu_bomb(""); } if (sol_id != ID_ELL) { if (op == OP_UNION) bu_log("Non-ellipse \"union\" primitive of \"%s\" being ignored\n", tb->name); if (rdebug&RDEBUG_SHADE) bu_log(" got a primitive type %ld \"%s\". This primitive ain't no ellipse bucko!\n", sol_id, OBJ[sol_id].ft_name); break; } ell_p = (struct rt_ell_internal *)dbint->ip.idb_ptr; if (rdebug&RDEBUG_SHADE) bu_log(" got a primitive type %ld \"%s\"\n", sol_id, OBJ[sol_id].ft_name); RT_ELL_CK_MAGIC(ell_p); if (rdebug&RDEBUG_SHADE) { VPRINT("point", ell_p->v); VPRINT("a", ell_p->a); VPRINT("b", ell_p->b); VPRINT("c", ell_p->c); } /* create the matrix that maps the coordinate system defined * by the ellipse into model space, and get inverse for use * in the _render() proc */ MAT_IDN(mp); VMOVE(v, ell_p->a); VUNITIZE(v); mp[0] = v[0]; mp[4] = v[1]; mp[8] = v[2]; VMOVE(v, ell_p->b); VUNITIZE(v); mp[1] = v[0]; mp[5] = v[1]; mp[9] = v[2]; VMOVE(v, ell_p->c); VUNITIZE(v); mp[2] = v[0]; mp[6] = v[1]; mp[10] = v[2]; MAT_DELTAS_VEC(mp, ell_p->v); MAT_COPY(dbint->ell2model, mp); bn_mat_inv(dbint->model2ell, mp); /* find scaling of gaussian puff in ellipsoid space */ VSET(dbint->one_sigma, MAGNITUDE(ell_p->a) / tb->gs->gauss_sigma, MAGNITUDE(ell_p->b) / tb->gs->gauss_sigma, MAGNITUDE(ell_p->c) / tb->gs->gauss_sigma); if (rdebug&RDEBUG_SHADE) { VPRINT("sigma", dbint->one_sigma); } BU_LIST_APPEND(tb->l, &(dbint->l)); break; } case OP_UNION: tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp); tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp); break; case OP_NOT: bu_log("Warning: 'Not' region operator in %s\n", tb->name); tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp); break; case OP_GUARD:bu_log("Warning: 'Guard' region operator in %s\n", tb->name); tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp); break; case OP_XNOP:bu_log("Warning: 'XNOP' region operator in %s\n", tb->name); tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp); break; case OP_INTERSECT: case OP_SUBTRACT: case OP_XOR: /* XXX this can get us in trouble if 1 solid is subtracted * from less than all the "union" solids of the region. */ tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp); tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp); return; default: bu_bomb("rt_tree_region_assign: bad op\n"); } }
/** * 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); }
/** * 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"); }