/* IEEE patch number of the Bi-Cubic Bezier patch and convert it * to a B-Spline surface (Bezier surfaces are a subset of B-spline surfaces * and output it to a BRL-CAD binary format. */ void dump_patch(int (*patch)[4]) { struct vertex *verts[4]; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; int i, j, pt_type; fastf_t *mesh=NULL; fastf_t *ukv=NULL; fastf_t *vkv=NULL; /* U and V parametric Direction Spline parameters * Cubic = order 4, * knot size is Control point + order = 8 * control point size is 4 * point size is 3 */ for ( i=0; i<4; i++ ) verts[i] = (struct vertex *)NULL; fu = nmg_cface( s, verts, 4 ); NMG_CK_FACEUSE( fu ); for ( i=0; i<4; i++ ) { struct vertexuse *vu; vect_t uvw; point_t pnt; int k, j; switch ( i ) { default: case 0: VSET( uvw, 0.0, 0.0, 0.0 ); k = 0; j = 0; break; case 1: VSET( uvw, 1.0, 0.0, 0.0 ); k = 0; j = 3; break; case 2: VSET( uvw, 1.0, 1.0, 0.0 ); k = 3; j = 3; break; case 3: VSET( uvw, 0.0, 1.0, 0.0 ); k = 3; j = 0; break; } VSET( pnt , ducks[patch[k][j]-1].x * 1000 , ducks[patch[k][j]-1].y * 1000 , ducks[patch[k][j]-1].z * 1000 ); nmg_vertex_gv( verts[i], pnt ); for ( BU_LIST_FOR( vu, vertexuse, &verts[i]->vu_hd ) ) nmg_vertexuse_a_cnurb( vu, uvw ); } pt_type = RT_NURB_MAKE_PT_TYPE(3, RT_NURB_PT_XYZ, 0); /* see nurb.h for details */ nmg_face_g_snurb( fu, 4, 4, 8, 8, ukv, vkv, 4, 4, pt_type, mesh ); NMG_CK_FACE( fu->f_p ); NMG_CK_FACE_G_SNURB( fu->f_p->g.snurb_p ); mesh = fu->f_p->g.snurb_p->ctl_points; /* Copy the control points */ for ( i = 0; i< 4; i++) for ( j = 0; j < 4; j++) { *mesh = ducks[patch[i][j]-1].x * 1000; *(mesh+1) = ducks[patch[i][j]-1].y * 1000; *(mesh+2) = ducks[patch[i][j]-1].z * 1000; mesh += 3; } /* Both u and v knot vectors are [ 0 0 0 0 1 1 1 1] */ ukv = fu->f_p->g.snurb_p->u.knots; vkv = fu->f_p->g.snurb_p->v.knots; /* set the knot vectors */ for ( i=0; i<4; i++ ) { *(ukv+i) = 0.0; *(vkv+i) = 0.0; } for ( i=0; i<4; i++ ) { *(ukv+4+i) = 1.0; *(vkv+4+i) = 1.0; } /* set eu geometry */ pt_type = RT_NURB_MAKE_PT_TYPE(2, RT_NURB_PT_UV, 0); /* see nurb.h for details */ lu = BU_LIST_FIRST( loopuse, &fu->lu_hd ); NMG_CK_LOOPUSE( lu ); for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { #if 0 nmg_edge_g_cnurb( eu, 2, 0, (fastf_t *)NULL, 2 , pt_type, (fastf_t *)NULL ); #else nmg_edge_g_cnurb_plinear( eu ); #endif } nmg_face_bb( fu->f_p, &tol ); }
struct faceuse * Make_planar_face(struct shell *s, int entityno, int face_orient) { int sol_num; /* IGES solid type number */ int no_of_edges; /* edge count for this loop */ int no_of_param_curves; int vert_count = 0; /* Actual number of vertices used to make face */ struct iges_edge_use *edge_list; /* list of edgeuses from iges loop entity */ struct faceuse *fu = NULL; /* NMG face use */ struct loopuse *lu; /* NMG loop use */ struct vertex ***verts; /* list of vertices */ struct iges_vertex_list *v_list; int done; int i, j, k; /* Acquiring Data */ if (dir[entityno]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[entityno]->direct, dir[entityno]->name); return 0; } Readrec(dir[entityno]->param); Readint(&sol_num, ""); if (sol_num != 508) { bu_exit(1, "ERROR: Entity #%d is not a loop (it's a %s)\n", entityno, iges_type(sol_num)); } Readint(&no_of_edges, ""); edge_list = (struct iges_edge_use *)bu_calloc(no_of_edges, sizeof(struct iges_edge_use) , "Make_face (edge_list)"); for (i = 0; i < no_of_edges; i++) { Readint(&edge_list[i].edge_is_vertex, ""); Readint(&edge_list[i].edge_de, ""); Readint(&edge_list[i].index, ""); Readint(&edge_list[i].orient, ""); if (!face_orient) { /* need opposite orientation of edge */ if (edge_list[i].orient) edge_list[i].orient = 0; else edge_list[i].orient = 1; } edge_list[i].root = (struct iges_param_curve *)NULL; Readint(&no_of_param_curves, ""); for (j = 0; j < no_of_param_curves; j++) { struct iges_param_curve *new_crv; struct iges_param_curve *crv; Readint(&k, ""); /* ignore iso-parametric flag */ BU_ALLOC(new_crv, struct iges_param_curve); if (edge_list[i].root == (struct iges_param_curve *)NULL) edge_list[i].root = new_crv; else { crv = edge_list[i].root; while (crv->next != (struct iges_param_curve *)NULL) crv = crv->next; crv->next = new_crv; } Readint(&new_crv->curve_de, ""); new_crv->next = (struct iges_param_curve *)NULL; } } verts = (struct vertex ***)bu_calloc(no_of_edges, sizeof(struct vertex **) , "Make_face: vertex_list **"); for (i = 0; i < no_of_edges; i++) { if (face_orient) verts[i] = Get_vertex(&edge_list[i]); else verts[no_of_edges-1-i] = Get_vertex(&edge_list[i]); } /* eliminate zero length edges */ vert_count = no_of_edges; done = 0; while (!done) { done = 1; for (i = 0; i < vert_count; i++) { k = i + 1; if (k == vert_count) k = 0; if (verts[i] == verts[k]) { bu_log("Ignoring zero length edge\n"); done = 0; vert_count--; for (j = i; j < vert_count; j++) verts[j] = verts[j+1]; } } } if (vert_count) { plane_t pl; /* Plane equation for face */ fastf_t area; /* area of loop */ fastf_t dist; vect_t min2max; point_t outside_pt; fu = nmg_cmface(s, verts, vert_count); /* associate geometry */ v_list = vertex_root; while (v_list != NULL) { for (i = 0; i < v_list->no_of_verts; i++) { if (v_list->i_verts[i].v != NULL && v_list->i_verts[i].v->vg_p == NULL) { NMG_CK_VERTEX(v_list->i_verts[i].v); nmg_vertex_gv(v_list->i_verts[i].v , v_list->i_verts[i].pt); } } v_list = v_list->next; } lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); NMG_CK_LOOPUSE(lu); area = nmg_loop_plane_area(lu, pl); if (area < 0.0) { bu_log("Could not calculate area for face (entityno = %d)\n", entityno); nmg_pr_fu_briefly(fu, ""); nmg_kfu(fu); fu = (struct faceuse *)NULL; goto err; } nmg_face_g(fu, pl); nmg_face_bb(fu->f_p, &tol); /* find a point that is surely outside the loop */ VSUB2(min2max, fu->f_p->max_pt, fu->f_p->min_pt); VADD2(outside_pt, fu->f_p->max_pt, min2max); /* move it to the plane of the face */ dist = DIST_PT_PLANE(outside_pt, pl); VJOIN1(outside_pt, outside_pt, -dist, pl); if (nmg_class_pt_lu_except(outside_pt, lu, (struct edge *)NULL, &tol) != NMG_CLASS_AoutB) { nmg_reverse_face(fu); if (fu->orientation != OT_SAME) { fu = fu->fumate_p; if (fu->orientation != OT_SAME) bu_exit(1, "ERROR: no OT_SAME use for a face!\n"); } } } else bu_log("No edges left!\n"); err: bu_free((char *)edge_list, "Make_face (edge_list)"); bu_free((char *)verts, "Make_face (vertexlist)"); return fu; }