/** * R T _ P G _ T E S S */ int rt_pg_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol) { size_t i; struct shell *s; struct vertex **verts; /* dynamic array of pointers */ struct vertex ***vertp;/* dynamic array of ptrs to pointers */ struct faceuse *fu; size_t p; /* current polygon number */ struct rt_pg_internal *pgp; RT_CK_DB_INTERNAL(ip); pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); *r = nmg_mrsv(m); /* Make region, empty shell, vertex */ s = BU_LIST_FIRST(shell, &(*r)->s_hd); verts = (struct vertex **)bu_malloc( pgp->max_npts * sizeof(struct vertex *), "pg_tess verts[]"); vertp = (struct vertex ***)bu_malloc( pgp->max_npts * sizeof(struct vertex **), "pg_tess vertp[]"); for (i=0; i < pgp->max_npts; i++) vertp[i] = &verts[i]; for (p = 0; p < pgp->npoly; p++) { struct rt_pg_face_internal *pp; pp = &pgp->poly[p]; /* Locate these points, if previously mentioned */ for (i=0; i < pp->npts; i++) { verts[i] = nmg_find_pt_in_shell(s, &pp->verts[3*i], tol); } /* Construct the face. Verts should be in CCW order */ if ((fu = nmg_cmface(s, vertp, pp->npts)) == (struct faceuse *)0) { bu_log("rt_pg_tess() nmg_cmface failed, skipping face %zu\n", p); } /* Associate vertex geometry, where none existed before */ for (i=0; i < pp->npts; i++) { if (verts[i]->vg_p) continue; nmg_vertex_gv(verts[i], &pp->verts[3*i]); } /* Associate face geometry */ if (nmg_calc_face_g(fu)) { nmg_pr_fu_briefly(fu, ""); bu_free((char *)verts, "pg_tess verts[]"); bu_free((char *)vertp, "pg_tess vertp[]"); return -1; /* FAIL */ } } /* Compute "geometry" for region and shell */ nmg_region_a(*r, tol); /* Polysolids are often built with incorrect face normals. * Don't depend on them here. */ nmg_fix_normals(s, tol); bu_free((char *)verts, "pg_tess verts[]"); bu_free((char *)vertp, "pg_tess vertp[]"); return 0; /* OK */ }
HIDDEN void get_ctria3(void) { int pid; int g1, g2, g3; int gin1, gin2, gin3; point_t pt1, pt2, pt3; struct vertex **v[3]; struct faceuse *fu; struct shell *s; struct pshell *psh; int pid_index=0; pid = atoi(curr_rec[2]); pid_index = get_pid_index(pid); g1 = atoi(curr_rec[3]); g2 = atoi(curr_rec[4]); g3 = atoi(curr_rec[5]); gin1 = get_gridi(g1); gin2 = get_gridi(g2); gin3 = get_gridi(g3); v[0] = &g_pts[gin1].v[pid_index]; v[1] = &g_pts[gin2].v[pid_index]; v[2] = &g_pts[gin3].v[pid_index]; VSCALE(pt1, g_pts[gin1].pt, conv[units]); VSCALE(pt2, g_pts[gin2].pt, conv[units]); VSCALE(pt3, g_pts[gin3].pt, conv[units]); if (!nmg_model && !pid) { struct nmgregion *r; nmg_model = nmg_mm(); r = nmg_mrsv(nmg_model); nmg_shell = BU_LIST_FIRST(shell, &r->s_hd); } if (!pid) s = nmg_shell; else { int found=0; /* find pshell entry for this pid */ for (BU_LIST_FOR(psh, pshell, &pshell_head.l)) { if (psh->pid == pid) { found = 1; break; } } if (!found) { bu_log("Cannot find PSHELL entry for a CTRIA3 element (ignoring)!\n"); write_fields(); return; } if (psh->s) s = psh->s; else { struct model *m; struct nmgregion *r; m = nmg_mm(); r = nmg_mrsv(m); s = BU_LIST_FIRST(shell, &r->s_hd); psh->s = s; } } fu = nmg_cmface(s, v, 3); if (!g_pts[gin1].v[pid_index]->vg_p) nmg_vertex_gv(g_pts[gin1].v[pid_index], pt1); if (!g_pts[gin2].v[pid_index]->vg_p) nmg_vertex_gv(g_pts[gin2].v[pid_index], pt2); if (!g_pts[gin3].v[pid_index]->vg_p) nmg_vertex_gv(g_pts[gin3].v[pid_index], pt3); nmg_calc_face_g(fu); }
/** * "Tessellate" an ARB into an NMG data structure. * Purely a mechanical transformation of one faceted object * into another. * * Returns - * -1 failure * 0 OK. *r points to nmgregion that holds this tessellation. */ int rt_arbn_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol) { struct rt_arbn_internal *aip; struct shell *s; struct faceuse **fu; /* array of faceuses */ size_t nverts; /* maximum possible number of vertices = neqn!/(3!(neqn-3)! */ size_t point_count = 0; /* actual number of vertices */ size_t face_count = 0; /* actual number of faces built */ size_t i, j, k, l, n; struct arbn_pts *pts; struct arbn_edges *edges; /* A list of edges for each plane eqn (each face) */ size_t *edge_count; /* number of edges for each face */ size_t max_edge_count; /* maximum number of edges for any face */ struct vertex **verts; /* Array of pointers to vertex structs */ struct vertex ***loop_verts; /* Array of pointers to vertex structs to pass to nmg_cmface */ RT_CK_DB_INTERNAL(ip); aip = (struct rt_arbn_internal *)ip->idb_ptr; RT_ARBN_CK_MAGIC(aip); /* Allocate memory for the vertices */ nverts = aip->neqn * (aip->neqn-1) * (aip->neqn-2) / 6; pts = (struct arbn_pts *)bu_calloc(nverts, sizeof(struct arbn_pts), "rt_arbn_tess: pts"); /* Allocate memory for arbn_edges */ edges = (struct arbn_edges *)bu_calloc(aip->neqn*aip->neqn, sizeof(struct arbn_edges) , "rt_arbn_tess: edges"); edge_count = (size_t *)bu_calloc(aip->neqn, sizeof(size_t), "rt_arbn_tess: edge_count"); /* Allocate memory for faceuses */ fu = (struct faceuse **)bu_calloc(aip->neqn, sizeof(struct faceuse *), "rt_arbn_tess: fu"); /* Calculate all vertices */ for (i = 0; i < aip->neqn; i++) { for (j = i + 1; j < aip->neqn; j++) { for (k = j + 1; k < aip->neqn; k++) { int keep_point = 1; if (bn_mkpoint_3planes(pts[point_count].pt, aip->eqn[i], aip->eqn[j], aip->eqn[k])) continue; for (l = 0; l < aip->neqn; l++) { if (l == i || l == j || l == k) continue; if (DIST_PT_PLANE(pts[point_count].pt, aip->eqn[l]) > tol->dist) { keep_point = 0; break; } } if (keep_point) { pts[point_count].plane_no[0] = i; pts[point_count].plane_no[1] = j; pts[point_count].plane_no[2] = k; point_count++; } } } } /* Allocate memory for the NMG vertex pointers */ verts = (struct vertex **)bu_calloc(point_count, sizeof(struct vertex *) , "rt_arbn_tess: verts"); /* Associate points with vertices */ for (i = 0; i < point_count; i++) pts[i].vp = &verts[i]; /* Check for duplicate points */ for (i = 0; i < point_count; i++) { for (j = i + 1; j < point_count; j++) { if (DIST_PT_PT_SQ(pts[i].pt, pts[j].pt) < tol->dist_sq) { /* These two points should point to the same vertex */ pts[j].vp = pts[i].vp; } } } /* Make list of edges for each face */ for (i = 0; i < aip->neqn; i++) { /* look for a point that lies in this face */ for (j = 0; j < point_count; j++) { if (pts[j].plane_no[0] != (int)i && pts[j].plane_no[1] != (int)i && pts[j].plane_no[2] != (int)i) continue; /* look for another point that shares plane "i" and another with this one */ for (k = j + 1; k < point_count; k++) { size_t match = (size_t)-1; size_t pt1, pt2; int duplicate = 0; /* skip points not on plane "i" */ if (pts[k].plane_no[0] != (int)i && pts[k].plane_no[1] != (int)i && pts[k].plane_no[2] != (int)i) continue; for (l = 0; l < 3; l++) { for (n = 0; n < 3; n++) { if (pts[j].plane_no[l] == pts[k].plane_no[n] && pts[j].plane_no[l] != (int)i) { match = pts[j].plane_no[l]; break; } } if (match != (size_t)-1) break; } if (match == (size_t)-1) continue; /* convert equivalent points to lowest point number */ pt1 = j; pt2 = k; for (l = 0; l < pt1; l++) { if (pts[pt1].vp == pts[l].vp) { pt1 = l; break; } } for (l = 0; l < pt2; l++) { if (pts[pt2].vp == pts[l].vp) { pt2 = l; break; } } /* skip null edges */ if (pt1 == pt2) continue; /* check for duplicate edge */ for (l = 0; l < edge_count[i]; l++) { if ((edges[LOC(i, l)].v1_no == (int)pt1 && edges[LOC(i, l)].v2_no == (int)pt2) || (edges[LOC(i, l)].v2_no == (int)pt1 && edges[LOC(i, l)].v1_no == (int)pt2)) { duplicate = 1; break; } } if (duplicate) continue; /* found an edge belonging to faces "i" and "match" */ if (edge_count[i] == aip->neqn) { bu_log("Too many edges found for one face\n"); goto fail; } edges[LOC(i, edge_count[i])].v1_no = pt1; edges[LOC(i, edge_count[i])].v2_no = pt2; edge_count[i]++; } } } /* for each face, sort the list of edges into a loop */ Sort_edges(edges, edge_count, aip); /* Get max number of edges for any face */ max_edge_count = 0; for (i = 0; i < aip->neqn; i++) if (edge_count[i] > max_edge_count) max_edge_count = edge_count[i]; /* Allocate memory for array to pass to nmg_cmface */ loop_verts = (struct vertex ***) bu_calloc(max_edge_count, sizeof(struct vertex **) , "rt_arbn_tess: loop_verts"); *r = nmg_mrsv(m); /* Make region, empty shell, vertex */ s = BU_LIST_FIRST(shell, &(*r)->s_hd); /* Make the faces */ for (i = 0; i < aip->neqn; i++) { int loop_length = 0; for (j = 0; j < edge_count[i]; j++) { /* skip zero length edges */ if (pts[edges[LOC(i, j)].v1_no].vp == pts[edges[LOC(i, j)].v2_no].vp) continue; /* put vertex pointers into loop_verts array */ loop_verts[loop_length] = pts[edges[LOC(i, j)].v2_no].vp; loop_length++; } /* Make the face if there is are least 3 vertices */ if (loop_length > 2) fu[face_count++] = nmg_cmface(s, loop_verts, loop_length); } /* Associate vertex geometry */ for (i = 0; i < point_count; i++) { if (!(*pts[i].vp)) continue; if ((*pts[i].vp)->vg_p) continue; nmg_vertex_gv(*pts[i].vp, pts[i].pt); } bu_free((char *)pts, "rt_arbn_tess: pts"); bu_free((char *)edges, "rt_arbn_tess: edges"); bu_free((char *)edge_count, "rt_arbn_tess: edge_count"); bu_free((char *)verts, "rt_arbn_tess: verts"); bu_free((char *)loop_verts, "rt_arbn_tess: loop_verts"); /* Associate face geometry */ for (i = 0; i < face_count; i++) { if (nmg_fu_planeeqn(fu[i], tol)) { bu_log("Failed to calculate face plane equation\n"); bu_free((char *)fu, "rt_arbn_tess: fu"); nmg_kr(*r); *r = (struct nmgregion *)NULL; return -1; } } bu_free((char *)fu, "rt_arbn_tess: fu"); nmg_fix_normals(s, tol); (void)nmg_mark_edges_real(&s->l.magic); /* Compute "geometry" for region and shell */ nmg_region_a(*r, tol); return 0; fail: bu_free((char *)pts, "rt_arbn_tess: pts"); bu_free((char *)edges, "rt_arbn_tess: edges"); bu_free((char *)edge_count, "rt_arbn_tess: edge_count"); bu_free((char *)verts, "rt_arbn_tess: verts"); return -1; }
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); }