void make_2manifold_bits(struct bn_tol *tol) { struct vertex *f2_vertl[8]; /* make a non-dangling internal face */ f2_vertl[0] = vertl[1]; f2_vertl[1] = vertl[2]; f2_vertl[2] = vertl[7]; f2_vertl[3] = vertl[5]; fu = nmg_cface(s, f2_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* * we need to make the 2-manifolds share edge topology */ nmg_mesh_faces(tc_fu, fu, tol); nmg_mesh_faces(fl_fu, fu, tol); nmg_mesh_faces(bl_fu, fu, tol); nmg_mesh_faces(ul_fu, fu, tol); /* make a dangling internal face */ f2_vertl[0] = vertl[9]; f2_vertl[1] = vertl[10]; f2_vertl[2] = vertl[11]; f2_vertl[3] = vertl[8]; fu = nmg_cface(s, f2_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make faces share edge topology */ nmg_mesh_faces(tc_fu, fu, tol); nmg_mesh_faces(fl_fu, fu, tol); nmg_mesh_faces(bl_fu, fu, tol); /* make an exterior, connected dangling face */ f2_vertl[0] = vertl[0]; f2_vertl[1] = vertl[3]; f2_vertl[2] = vertl[31]; f2_vertl[3] = vertl[30]; fu = nmg_cface(s, f2_vertl, 4); vertl[30] = f2_vertl[3]; vertl[31] = f2_vertl[2]; nmg_vertex_g(vertl[30], 150.0, 100.0, 150.0); nmg_vertex_g(vertl[31], 150.0, 0.0, 150.0); (void)nmg_fu_planeeqn(fu, tol); nmg_mesh_faces(fr_fu, fu, tol); }
/** * 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; }
/* 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 ); }
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 extrude(int entityno) { fastf_t length; /* extrusion length */ vect_t edir; /* a unit vector (direction of extrusion */ vect_t evect; /* Scaled vector for extrusion */ int sol_num; /* IGES solid type number */ int curve; /* pointer to directory entry for base curve */ struct ptlist *curv_pts; /* List of points along curve */ int i; /* Default values */ VSET(edir, 0.0, 0.0, 1.0); /* 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, ""); /* Read pointer to directory entry for curve to be extruded */ Readint(&curve, ""); /* Convert this to a "dir" index */ curve = (curve-1)/2; Readcnv(&length, ""); Readflt(&edir[X], ""); Readflt(&edir[Y], ""); Readflt(&edir[Z], ""); if (length <= 0.0) { bu_log("Illegal parameters for entity D%07d (%s)\n" , dir[entityno]->direct, dir[entityno]->name); return 0; } /* * Unitize direction vector */ VUNITIZE(edir); /* Scale vector */ VSCALE(evect, edir, length); /* Switch based on type of curve to be extruded */ switch (dir[curve]->type) { case 100: /* circular arc */ return Extrudcirc(entityno, curve, evect); case 104: /* conic arc */ return Extrudcon(entityno, curve, evect); case 102: /* composite curve */ case 106: /* copius data */ case 112: /* parametric spline */ case 126: { /* B-spline */ int npts; struct model *m; struct nmgregion *r; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; struct ptlist *pt_ptr; npts = Getcurve(curve, &curv_pts); if (npts < 3) return 0; m = nmg_mm(); r = nmg_mrsv(m); s = BU_LIST_FIRST(shell, &r->s_hd); fu = nmg_cface(s, (struct vertex **)NULL, npts-1); pt_ptr = curv_pts; lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { struct vertex *v; v = eu->vu_p->v_p; nmg_vertex_gv(v, pt_ptr->pt); pt_ptr = pt_ptr->next; } if (nmg_calc_face_g(fu)) { bu_log("Extrude: Failed to calculate face geometry\n"); nmg_km(m); bu_free((char *)curv_pts, "curve_pts"); return 0; } if (nmg_extrude_face(fu, evect, &tol)) { bu_log("Extrude: extrusion failed\n"); nmg_km(m); bu_free((char *)curv_pts, "curve_pts"); return 0; } mk_bot_from_nmg(fdout, dir[entityno]->name, s); nmg_km(m); bu_free((char *)curv_pts, "curve_pts"); return 1; } default: i = (-1); while (dir[curve]->type != typecount[++i].type && i < ntypes); bu_log("Extrusions of %s are not allowed\n", typecount[i].name); break; } 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; }