/* * Convert an ascii nmg description into a BRL-CAD data base. */ static int ascii_to_brlcad(FILE *fpin, struct rt_wdb *fpout, char *reg_name, char *grp_name) { struct model *m; struct nmgregion *r; struct bn_tol tol; struct shell *s; vect_t Ext; struct faceuse *fu; plane_t pl; VSETALL(Ext, 0.); m = nmg_mm(); /* Make nmg model. */ r = nmg_mrsv(m); /* Make region, empty shell, vertex */ s = BU_LIST_FIRST(shell, &r->s_hd); descr_to_nmg(s, fpin, Ext); /* Convert ascii description to nmg. */ /* Copied from proc-db/nmgmodel.c */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.01; tol.dist_sq = tol.dist * tol.dist; tol.perp = 0.001; tol.para = 0.999; /* Associate the face geometry. */ fu = BU_LIST_FIRST( faceuse, &s->fu_hd ); if (nmg_loop_plane_area(BU_LIST_FIRST(loopuse, &fu->lu_hd), pl) < 0.0) return -1; else nmg_face_g( fu, pl ); if (!NEAR_ZERO(MAGNITUDE(Ext), 0.001)) nmg_extrude_face(BU_LIST_FIRST(faceuse, &s->fu_hd), Ext, &tol); nmg_region_a(r, &tol); /* Calculate geometry for region and shell. */ nmg_fix_normals( s, &tol ); /* insure that faces have outward pointing normals */ create_brlcad_db(fpout, m, reg_name, grp_name); return 0; }
/** * Read a polygon file and convert it to an NMG shell * * A polygon file consists of the following: * * The first line consists of two integer numbers: the number of * points (vertices) in the file, followed by the number of polygons * in the file. This line is followed by lines for each of the * vertices. Each vertex is listed on its own line, as the 3tuple "X * Y Z". After the list of vertices comes the list of polygons. * each polygon is represented by a line containing 1) the number of * vertices in the polygon, followed by 2) the indices of the * vertices that make up the polygon. * * Implicitly returns r->s_p which is a new shell containing all the * faces from the polygon file. * * XXX This is a horrible way to do this. Lee violates his own rules * about not creating fundamental structures on his own... :-) * Retired in favor of more modern tessellation strategies. */ struct shell * nmg_polytonmg(FILE *fp, struct nmgregion *r, const struct bn_tol *tol) { int i, j, num_pts, num_facets, pts_this_face, facet; int vl_len; struct vertex **v; /* list of all vertices */ struct vertex **vl; /* list of vertices for this polygon*/ point_t p; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; plane_t plane; struct model *m; s = nmg_msv(r); m = s->r_p->m_p; nmg_kvu(s->vu_p); /* get number of points & number of facets in file */ if (fscanf(fp, "%d %d", &num_pts, &num_facets) != 2) bu_bomb("polytonmg() Error in first line of poly file\n"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("points: %d facets: %d\n", num_pts, num_facets); v = (struct vertex **) bu_calloc(num_pts, sizeof (struct vertex *), "vertices"); /* build the vertices */ for (i = 0; i < num_pts; ++i) { GET_VERTEX(v[i], m); v[i]->magic = NMG_VERTEX_MAGIC; } /* read in the coordinates of the vertices */ for (i=0; i < num_pts; ++i) { if (fscanf(fp, "%lg %lg %lg", &p[0], &p[1], &p[2]) != 3) bu_bomb("polytonmg() Error reading point"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("read vertex #%d (%g %g %g)\n", i, p[0], p[1], p[2]); nmg_vertex_gv(v[i], p); } vl = (struct vertex **)bu_calloc(vl_len=8, sizeof (struct vertex *), "vertex parameter list"); for (facet = 0; facet < num_facets; ++facet) { if (fscanf(fp, "%d", &pts_this_face) != 1) bu_bomb("polytonmg() error getting pt count for this face"); if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("facet %d pts in face %d\n", facet, pts_this_face); if (pts_this_face > vl_len) { while (vl_len < pts_this_face) vl_len *= 2; vl = (struct vertex **)bu_realloc((char *)vl, vl_len*sizeof(struct vertex *), "vertex parameter list (realloc)"); } for (i=0; i < pts_this_face; ++i) { if (fscanf(fp, "%d", &j) != 1) bu_bomb("polytonmg() error getting point index for v in f"); vl[i] = v[j-1]; } fu = nmg_cface(s, vl, pts_this_face); lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); /* XXX should check for vertex-loop */ eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); if (bn_mk_plane_3pts(plane, eu->vu_p->v_p->vg_p->coord, BU_LIST_PNEXT(edgeuse, eu)->vu_p->v_p->vg_p->coord, BU_LIST_PLAST(edgeuse, eu)->vu_p->v_p->vg_p->coord, tol)) { bu_log("At %d in %s\n", __LINE__, __FILE__); bu_bomb("polytonmg() cannot make plane equation\n"); } else nmg_face_g(fu, plane); } for (i=0; i < num_pts; ++i) { if (BU_LIST_IS_EMPTY(&v[i]->vu_hd)) continue; FREE_VERTEX(v[i]); } bu_free((char *)v, "vertex array"); return s; }
int psurf_to_nmg(struct model *m, FILE *fp, char *jfile) /* Input/output, nmg model. */ /* Input, pointer to psurf data file. */ /* Name of Jack data base file. */ { int face, fail, i, lst[MAX_NUM_PTS], nf, nv; struct faceuse *outfaceuses[MAX_NUM_PTS]; struct nmgregion *r; struct shell *s; struct vertex *vertlist[MAX_NUM_PTS]; struct vlist vert; /* Copied from proc-db/nmgmodel.c */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.01; tol.dist_sq = tol.dist * tol.dist; tol.perp = 0.001; tol.para = 0.999; face = 0; r = nmg_mrsv(m); /* Make region, empty shell, vertex. */ s = BU_LIST_FIRST(shell, &r->s_hd); while ((nv = read_psurf_vertices(fp, &vert)) != 0) { size_t ret; while ((nf = read_psurf_face(fp, lst)) != 0) { /* Make face out of vertices in lst (ccw ordered). */ for (i = 0; i < nf; i++) vertlist[i] = vert.vt[lst[i]-1]; outfaceuses[face] = nmg_cface(s, vertlist, nf); face++; /* Save (possibly) newly created vertex structs. */ for (i = 0; i < nf; i++) vert.vt[lst[i]-1] = vertlist[i]; } ret = fscanf(fp, ";;"); if (ret > 0) bu_log("unknown parsing error\n"); /* Associate the vertex geometry, ccw. */ for (i = 0; i < nv; i++) if (vert.vt[i]) nmg_vertex_gv(vert.vt[i], &vert.pt[3*i]); else fprintf(stderr, "%s, vertex %d is unused\n", jfile, i+1); } nmg_vertex_fuse(&m->magic, &tol); /* Associate the face geometry. */ for (i = 0, fail = 0; i < face; i++) { struct loopuse *lu; plane_t pl; lu = BU_LIST_FIRST(loopuse, &outfaceuses[i]->lu_hd); if (nmg_loop_plane_area(lu, pl) < 0.0) { fail = 1; nmg_kfu(outfaceuses[i]); } else nmg_face_g(outfaceuses[i], pl); } if (fail) return -1; if (face) { int empty_model; empty_model = nmg_kill_zero_length_edgeuses(m); if (!empty_model) { /* Compute "geometry" for region and shell */ nmg_region_a(r, &tol); nmg_break_e_on_v(&m->magic, &tol); empty_model = nmg_kill_zero_length_edgeuses(m); /* Glue edges of outward pointing face uses together. */ if (!empty_model) nmg_edge_fuse(&m->magic, &tol); } } return 0; }
int read_faces(struct model *m, FILE *fgeom) { int nverts, nfaces, nedges; int i, j, fail=0; fastf_t *pts; struct vertex **verts; struct faceuse **outfaceuses; struct nmgregion *r; struct shell *s; size_t ret; /* Get numbers of vertices and faces, and grab the appropriate amount of memory */ if (fscanf(fgeom, "%d %d %d", &nverts, &nfaces, &nedges) != 3) bu_exit(1, "Cannot read number of vertices, faces, edges.\n"); pts = (fastf_t *) bu_malloc(sizeof(fastf_t) * 3 * nverts, "points list"); verts = (struct vertex **) bu_malloc(sizeof(struct vertex *) * nverts, "vertices"); outfaceuses = (struct faceuse **) bu_malloc(sizeof(struct faceuse *) * nfaces, "faceuses"); /* Read in vertex geometry, store in geometry list */ for (i = 0; i < nverts; i++) { double scan[3]; if (fscanf(fgeom, "%lf %lf %lf", &scan[0], &scan[1], &scan[2]) != 3) { bu_exit(1, "Not enough data points in geometry file.\n"); } pts[3*i] = scan[0]; pts[3*i+1] = scan[1]; pts[3*i+2] = scan[2]; verts[i] = (struct vertex *) 0; ret = fscanf(fgeom, "%*[^\n]"); if (ret > 0) bu_log("unknown parsing error\n"); } r = nmg_mrsv(m); /* Make region, empty shell, vertex. */ s = BU_LIST_FIRST(shell, &r->s_hd); for (i = 0; i < nfaces; i++) { /* Read in each of the faces */ struct vertex **vlist; int *pinds; if (fscanf(fgeom, "%d", &nedges) != 1) { bu_exit(1, "Not enough faces in geometry file.\n"); } /* Grab memory for list for this face. */ vlist = (struct vertex **) bu_malloc(sizeof(struct vertex *) * nedges, "vertex list"); pinds = (int *) bu_malloc(sizeof(int) * nedges, "point indices"); for (j = 0; j < nedges; j++) { /* Read list of point indices. */ if (fscanf(fgeom, "%d", &pinds[j]) != 1) { bu_exit(1, "Not enough points on face.\n"); } vlist[j] = verts[pinds[j]-1]; } outfaceuses[i] = nmg_cface(s, vlist, nedges); /* Create face. */ NMG_CK_FACEUSE(outfaceuses[i]); for (j = 0; j < nedges; j++) /* Save (possibly) newly created vertex structs. */ verts[pinds[j]-1] = vlist[j]; ret = fscanf(fgeom, "%*[^\n]"); if (ret > 0) bu_log("unknown parsing error\n"); bu_free((char *)vlist, "vertext list"); bu_free((char *)pinds, "point indices"); } for (i = 0; i < nverts; i++) if (verts[i] != 0) nmg_vertex_gv(verts[i], &pts[3*i]); else fprintf(stderr, "Warning: vertex %d unused.\n", i+1); for (i = 0; i < nfaces; i++) { plane_t pl; fprintf(stderr, "planeeqning face %d.\n", i); if ( nmg_loop_plane_area( BU_LIST_FIRST( loopuse, &outfaceuses[i]->lu_hd ), pl ) < 0.0 ) fail = 1; else nmg_face_g( outfaceuses[i], pl ); } if (fail) return -1; nmg_gluefaces(outfaceuses, nfaces, &tol); nmg_region_a(r, &tol); bu_free((char *)pts, "points list"); return 0; }
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; }
void make_3manifold_bits(struct bn_tol *tol) { plane_t plane; struct faceuse *fu_end; memset((char *)vertl, 0, sizeof(vertl)); memset((char *)f_vertl, 0, sizeof(f_vertl)); /* front right */ f_vertl[0] = &vertl[0]; f_vertl[1] = &vertl[1]; f_vertl[2] = &vertl[2]; f_vertl[3] = &vertl[3]; fr_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[0], 100.0, 100.0, 100.0); nmg_vertex_g(vertl[1], 50.0, 100.0, 100.0); nmg_vertex_g(vertl[2], 50.0, 0.0, 100.0); nmg_vertex_g(vertl[3], 100.0, 0.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); /* make top right */ f_vertl[0] = &vertl[0]; f_vertl[1] = &vertl[4]; f_vertl[2] = &vertl[5]; f_vertl[3] = &vertl[1]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[4], 100.0, 100.0, 0.0); nmg_vertex_g(vertl[5], 50.0, 100.0, 0.0); (void)nmg_fu_planeeqn(fu, tol); /* back right */ f_vertl[0] = &vertl[5]; f_vertl[1] = &vertl[4]; f_vertl[2] = &vertl[6]; f_vertl[3] = &vertl[7]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[6], 100.0, 0.0, 0.0); nmg_vertex_g(vertl[7], 50.0, 0.0, 0.0); (void)nmg_fu_planeeqn(fu, tol); /* bottom right */ f_vertl[0] = &vertl[7]; f_vertl[1] = &vertl[6]; f_vertl[2] = &vertl[3]; f_vertl[3] = &vertl[2]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* right end */ f_vertl[0] = &vertl[3]; f_vertl[1] = &vertl[6]; f_vertl[2] = &vertl[4]; f_vertl[3] = &vertl[0]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make split top */ f_vertl[0] = &vertl[1]; f_vertl[1] = &vertl[5]; f_vertl[2] = &vertl[8]; f_vertl[3] = &vertl[9]; tc_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[8], 25.0, 100.0, 0.0); nmg_vertex_g(vertl[9], 25.0, 100.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[9]; f_vertl[1] = &vertl[8]; f_vertl[2] = &vertl[12]; f_vertl[3] = &vertl[13]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[12], 0.0, 100.0, 0.0); nmg_vertex_g(vertl[13], 0.0, 100.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); /* make split & funky front side * we make the convex face first, make the second (non-convex) portion * after the face normal has been computed. */ f_vertl[0] = &vertl[14]; f_vertl[1] = &vertl[18]; f_vertl[2] = &vertl[15]; f_vertl[3] = &vertl[16]; fl_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[14], 0.0, 25.0, 100.0); nmg_vertex_g(vertl[15], 25.0, 0.0, 100.0); nmg_vertex_g(vertl[16], 25.0, 25.0, 100.0); nmg_vertex_g(vertl[18], 0.0, 0.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[1]; f_vertl[1] = &vertl[9]; f_vertl[2] = &vertl[10]; f_vertl[3] = &vertl[9]; f_vertl[4] = &vertl[13]; f_vertl[5] = &vertl[14]; f_vertl[6] = &vertl[16]; f_vertl[7] = &vertl[15]; f_vertl[8] = &vertl[2]; nmg_jf(fu, nmg_cmface(s, f_vertl, 9)); nmg_vertex_g(vertl[10], 25.0, 75.0, 100.0); /* make split back side */ f_vertl[0] = &vertl[5]; f_vertl[1] = &vertl[7]; f_vertl[2] = &vertl[17]; f_vertl[3] = &vertl[12]; f_vertl[4] = &vertl[8]; f_vertl[5] = &vertl[11]; f_vertl[6] = &vertl[8]; bl_fu = fu = nmg_cmface(s, f_vertl, 7); nmg_vertex_g(vertl[11], 25.0, 75.0, 0.0); nmg_vertex_g(vertl[17], 0.0, 0.0, 0.0); /* this face isn't strictly convex, so we have to make the plane * equation the old-fashioned way. */ bn_mk_plane_3pts(plane, vertl[7]->vg_p->coord, vertl[17]->vg_p->coord, vertl[12]->vg_p->coord, tol); nmg_face_g(fu, plane); /* make funky end */ f_vertl[0] = &vertl[14]; f_vertl[1] = &vertl[20]; f_vertl[2] = &vertl[19]; f_vertl[3] = &vertl[18]; fu_end = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[19], 0.0, 0.0, 75.0); nmg_vertex_g(vertl[20], 0.0, 25.0, 75.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[12]; f_vertl[1] = &vertl[17]; f_vertl[2] = &vertl[19]; f_vertl[3] = &vertl[20]; f_vertl[4] = &vertl[14]; f_vertl[5] = &vertl[13]; nmg_jf(fu, nmg_cmface(s, f_vertl, 6)); /* make funky bottom */ f_vertl[0] = &vertl[15]; f_vertl[1] = &vertl[18]; f_vertl[2] = &vertl[19]; f_vertl[3] = &vertl[21]; ul_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[21], 25.0, 0.0, 75.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[7]; f_vertl[1] = &vertl[2]; f_vertl[2] = &vertl[15]; f_vertl[3] = &vertl[21]; f_vertl[4] = &vertl[19]; f_vertl[5] = &vertl[17]; nmg_jf(fu, nmg_cmface(s, f_vertl, 6)); /* now create the (3manifold) hole through the object */ /* make the holes in the end face */ f_vertl[0] = &vertl[29]; f_vertl[1] = &vertl[28]; f_vertl[2] = &vertl[27]; f_vertl[3] = &vertl[26]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[26], 0.0, 60.0, 10.0); nmg_vertex_g(vertl[27], 0.0, 60.0, 25.0); nmg_vertex_g(vertl[28], 0.0, 40.0, 25.0); nmg_vertex_g(vertl[29], 0.0, 40.0, 10.0); /* GROSS HACK XXX * we reverse the orientation of the faceuses and loopuses * so that we can make the hole as a face, and transfer the hole * to an existing face */ lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); lu->orientation = OT_OPPOSITE; lu->lumate_p->orientation = OT_OPPOSITE; fu->orientation = OT_OPPOSITE; fu->fumate_p->orientation = OT_SAME; nmg_jf(fu_end, fu->fumate_p); f_vertl[0] = &vertl[22]; f_vertl[1] = &vertl[23]; f_vertl[2] = &vertl[24]; f_vertl[3] = &vertl[25]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[22], 10.0, 60.0, 0.0); nmg_vertex_g(vertl[23], 25.0, 60.0, 0.0); nmg_vertex_g(vertl[24], 25.0, 40.0, 0.0); nmg_vertex_g(vertl[25], 10.0, 40.0, 0.0); /* GROSS HACK XXX * we reverse the orientation of the faceuses and loopuses * so that we can make the hole as a face, and transfer the hole * to an existing face. */ lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); lu->orientation = OT_OPPOSITE; lu->lumate_p->orientation = OT_OPPOSITE; fu->orientation = OT_OPPOSITE; fu->fumate_p->orientation = OT_SAME; nmg_jf(bl_fu, fu->fumate_p); /* make the top of the hole */ f_vertl[0] = &vertl[22]; f_vertl[1] = &vertl[23]; f_vertl[2] = &vertl[27]; f_vertl[3] = &vertl[26]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make the bottom of the hole */ f_vertl[0] = &vertl[24]; f_vertl[1] = &vertl[25]; f_vertl[2] = &vertl[29]; f_vertl[3] = &vertl[28]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make origin-ward side of the hole */ f_vertl[0] = &vertl[22]; f_vertl[1] = &vertl[26]; f_vertl[2] = &vertl[29]; f_vertl[3] = &vertl[25]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make last side of hole */ f_vertl[0] = &vertl[23]; f_vertl[1] = &vertl[24]; f_vertl[2] = &vertl[28]; f_vertl[3] = &vertl[27]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* now make the void in the center of the solid */ /* void bottom */ f_vertl[0] = &vertl[41]; f_vertl[1] = &vertl[40]; f_vertl[2] = &vertl[39]; f_vertl[3] = &vertl[38]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[38], 85.0, 40.0, 60.0); nmg_vertex_g(vertl[39], 65.0, 40.0, 60.0); nmg_vertex_g(vertl[40], 65.0, 40.0, 40.0); nmg_vertex_g(vertl[41], 85.0, 40.0, 40.0); (void)nmg_fu_planeeqn(fu, tol); /* void top */ f_vertl[0] = &vertl[42]; f_vertl[1] = &vertl[43]; f_vertl[2] = &vertl[44]; f_vertl[3] = &vertl[45]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[42], 85.0, 60.0, 40.0); nmg_vertex_g(vertl[43], 85.0, 60.0, 60.0); nmg_vertex_g(vertl[44], 65.0, 60.0, 60.0); nmg_vertex_g(vertl[45], 65.0, 60.0, 40.0); (void)nmg_fu_planeeqn(fu, tol); /* void front */ f_vertl[0] = &vertl[44]; f_vertl[1] = &vertl[43]; f_vertl[2] = &vertl[38]; f_vertl[3] = &vertl[39]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* void back */ f_vertl[0] = &vertl[42]; f_vertl[1] = &vertl[45]; f_vertl[2] = &vertl[40]; f_vertl[3] = &vertl[41]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* void left */ f_vertl[0] = &vertl[45]; f_vertl[1] = &vertl[44]; f_vertl[2] = &vertl[39]; f_vertl[3] = &vertl[40]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* void right */ f_vertl[0] = &vertl[42]; f_vertl[1] = &vertl[41]; f_vertl[2] = &vertl[38]; f_vertl[3] = &vertl[43]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); }