/* * 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; }
/** * 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 */ }
/* Routine to write an nmgregion in the Euclid "decoded" format */ static void Write_euclid_region(struct nmgregion *r, struct db_tree_state *tsp) { struct shell *s; struct facets *faces=NULL; int i, j; NMG_CK_REGION(r); if (verbose) bu_log("Write_euclid_region: r=%p\n", (void *)r); /* if bounds haven't been calculated, do it now */ if (r->ra_p == NULL) nmg_region_a(r, &tol); /* Check if region extents are beyond the limitations of the format */ for (i=X; i<ELEMENTS_PER_POINT; i++) { if (r->ra_p->min_pt[i] < (-999999.0)) { bu_log("g-euclid: Coordinates too large (%g) for Euclid format\n", r->ra_p->min_pt[i]); return; } if (r->ra_p->max_pt[i] > 9999999.0) { bu_log("g-euclid: Coordinates too large (%g) for Euclid format\n", r->ra_p->max_pt[i]); return; } } /* write out each face in the region */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; int no_of_loops = 0; int no_of_holes = 0; if (fu->orientation != OT_SAME) continue; /* count the loops in this face */ for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; no_of_loops++; } if (!no_of_loops) continue; faces = (struct facets *)bu_calloc(no_of_loops, sizeof(struct facets), "g-euclid: faces"); i = 0; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; faces[i].lu = lu; if (lu->orientation == OT_OPPOSITE) faces[i].facet_type = 1; /* this is a hole */ else faces[i].facet_type = (-1); /* TBD */ faces[i].outer_loop = NULL; i++; } /* determine type of face * 0 -> simple facet (no holes) * 1 -> a hole * 2 -> a facet that will have holes */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == 1) no_of_holes++; } if (!no_of_holes) { /* no holes, so each loop is a simple face (type 0) */ for (i = 0; i < no_of_loops; i++) faces[i].facet_type = 0; } else if (no_of_loops == no_of_holes + 1) { struct loopuse *outer_lu = (struct loopuse *)NULL; /* only one outer loop, so find it */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == (-1)) { outer_lu = faces[i].lu; faces[i].facet_type = 2; break; } } /* every hole must have this same outer_loop */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == 1) faces[i].outer_loop = outer_lu; } } else { int loop1, loop2; int outer_loop_count; /* must determine which holes go with which outer loops */ for (loop1 = 0; loop1 < no_of_loops; loop1++) { if (faces[loop1].facet_type != 1) continue; /* loop1 is a hole look for loops containing loop1 */ outer_loop_count = 0; for (loop2 = 0; loop2 < no_of_loops; loop2++) { int nmg_class; if (faces[loop2].facet_type == 1) continue; nmg_class = nmg_classify_lu_lu(faces[loop1].lu, faces[loop2].lu, &tol); if (nmg_class != NMG_CLASS_AinB) continue; /* loop1 is inside loop2, possible outer loop */ faces[loop2].facet_type = (-2); outer_loop_count++; } if (outer_loop_count > 1) { /* must choose outer loop from a list of candidates * if any of these candidates contain one of the * other candidates, the outer one can be eliminated * as a possible choice */ for (loop2 = 0; loop2 < no_of_loops; loop2++) { if (faces[loop2].facet_type != (-2)) continue; for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type != (-2)) continue; if (nmg_classify_lu_lu(faces[i].lu, faces[loop2].lu, &tol)) { if (faces[i].facet_type != (-2)) continue; faces[loop2].facet_type = (-1); outer_loop_count--; } } } } if (outer_loop_count != 1) { bu_log("Failed to find outer loop for hole in component %d\n", tsp->ts_regionid); goto outt; } for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == (-2)) { faces[i].facet_type = 2; faces[loop1].outer_loop = faces[i].lu; } } } /* Check */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type < 0) { /* all holes have been placed * so these must be simple faces */ faces[i].facet_type = 0; } if (faces[i].facet_type == 1 && faces[i].outer_loop == NULL) { bu_log("Failed to find outer loop for hole in component %d\n", tsp->ts_regionid); goto outt; } } } /* output faces with holes first */ for (i = 0; i < no_of_loops; i++) { struct loopuse *outer_loop; if (faces[i].facet_type != 2) continue; outer_loop = faces[i].lu; Write_euclid_face(outer_loop, 2, tsp->ts_regionid, ++face_count); /* output holes for this face */ for (j = 0; j < no_of_loops; j++) { if (j == i) continue; if (faces[j].outer_loop == outer_loop) Write_euclid_face(faces[j].lu, 1, tsp->ts_regionid, ++face_count); } } /* output simple faces */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type != 0) continue; Write_euclid_face(faces[i].lu, 0, tsp->ts_regionid, ++face_count); } bu_free((char *)faces, "g-euclid: faces"); faces = (struct facets*)NULL; } } regions_written++; outt: if (faces) bu_free((char *)faces, "g-euclid: faces"); return; }
/** * R T _ M E T A B A L L _ T E S S * * Tessellate a metaball. */ int rt_metaball_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol) { struct rt_metaball_internal *mb; fastf_t mtol, radius; point_t center, min, max; fastf_t i, j, k, finalstep = +INFINITY; struct bu_vls times = BU_VLS_INIT_ZERO; struct wdb_metaballpt *mbpt; struct shell *s; int numtri = 0; if (r == NULL || m == NULL) return -1; *r = NULL; NMG_CK_MODEL(m); RT_CK_DB_INTERNAL(ip); mb = (struct rt_metaball_internal *)ip->idb_ptr; RT_METABALL_CK_MAGIC(mb); rt_prep_timer(); /* since this geometry isn't necessarily prepped, we have to figure out the * finalstep and bounding box manually. */ for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) V_MIN(finalstep, mbpt->fldstr); finalstep /= (fastf_t)1e5; radius = rt_metaball_get_bounding_sphere(¢er, mb->threshold, mb); if(radius < 0) { /* no control points */ bu_log("Attempting to tesselate metaball with no control points"); return -1; } rt_metaball_bbox(ip, &min, &max, tol); /* TODO: get better sampling tolerance, unless this is "good enough" */ mtol = ttol->abs; V_MAX(mtol, ttol->rel * radius * 10); V_MAX(mtol, tol->dist); *r = nmg_mrsv(m); /* new empty nmg */ s = BU_LIST_FIRST(shell, &(*r)->s_hd); /* the incredibly naïve approach. Time could be cut in half by simply * caching 4 point values, more by actually marching or doing active * refinement. This is the simplest pattern for now. */ for (i = min[X]; i < max[X]; i += mtol) for (j = min[Y]; j < max[Y]; j += mtol) for (k = min[Z]; k < max[Z]; k += mtol) { point_t p[8]; int pv = 0; /* generate the vertex values */ #define MEH(c,di,dj,dk) VSET(p[c], i+di, j+dj, k+dk); pv |= rt_metaball_point_inside((const point_t *)&p[c], mb) << c; MEH(0, 0, 0, mtol); MEH(1, mtol, 0, mtol); MEH(2, mtol, 0, 0); MEH(3, 0, 0, 0); MEH(4, 0, mtol, mtol); MEH(5, mtol, mtol, mtol); MEH(6, mtol, mtol, 0); MEH(7, 0, mtol, 0); #undef MEH if ( pv != 0 && pv != 255 ) { /* entire cube is either inside or outside */ point_t edges[12]; int rval; /* compute the edge values (if needed) */ #define MEH(a,b,c) if(!(pv&(1<<b)&&pv&(1<<c))) { \ rt_metaball_find_intersection(edges+a, mb, (const point_t *)(p+b), (const point_t *)(p+c), mtol, finalstep); \ } /* magic numbers! an edge, then the two attached vertices. * For edge/vertex mapping, refer to the awesome ascii art * at the beginning of this file. */ MEH(0 ,0,1); MEH(1 ,1,2); MEH(2 ,2,3); MEH(3 ,0,3); MEH(4 ,4,5); MEH(5 ,5,6); MEH(6 ,6,7); MEH(7 ,4,7); MEH(8 ,0,4); MEH(9 ,1,5); MEH(10,2,6); MEH(11,3,7); #undef MEH rval = nmg_mc_realize_cube(s, pv, (point_t *)edges, tol); numtri += rval; if(rval < 0) { bu_log("Error attempting to realize a cube O.o\n"); return rval; } } } nmg_mark_edges_real(&s->l.magic); nmg_region_a(*r, tol); nmg_model_fuse(m, tol); rt_get_timer(×, NULL); bu_log("metaball tesselate (%d triangles): %s\n", numtri, bu_vls_addr(×)); return 0; }
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; }
/** * "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; }
int brep(int entityno) { int sol_num; /* IGES solid type number */ int shell_de; /* Directory sequence number for a shell */ int orient; /* Orientation of shell */ int *void_shell_de; /* Directory sequence number for an void shell */ int *void_orient; /* Orientation of void shell */ int num_of_voids; /* Number of inner void shells */ struct model *m; /* NMG model */ struct nmgregion *r; /* NMG region */ struct shell **void_shells; /* List of void shells */ struct shell *s_outer; /* Outer shell */ struct iges_vertex_list *v_list; struct iges_edge_list *e_list; int i; /* 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 , ""); Readint(&shell_de , ""); Readint(&orient , ""); Readint(&num_of_voids , ""); if (num_of_voids) { void_shell_de = (int *)bu_calloc(num_of_voids , sizeof(int) , "BREP: void shell DE's"); void_orient = (int *)bu_calloc(num_of_voids , sizeof(int) , "BREP: void shell orients"); void_shells = (struct shell **)bu_calloc(num_of_voids , sizeof(struct shell *) , "BREP: void shell pointers"); for (i = 0; i < num_of_voids; i++) { Readint(&void_shell_de[i] , ""); Readint(&void_orient[i] , ""); } } else { void_shell_de = NULL; void_orient = NULL; void_shells = NULL; } /* start building */ m = nmg_mmr(); r = BU_LIST_FIRST(nmgregion, &m->r_hd); /* Put outer shell in region */ if ((s_outer = Get_outer_shell(r , (shell_de - 1)/2)) == (struct shell *)NULL) goto err; ON_Brep* outer = ON_Brep::New(); if (Get_outer_brep(outer, (shell_de - 1)/2, orient)) goto err; /* Put voids in */ for (i = 0; i < num_of_voids; i++) { if ((void_shells[i] = Add_inner_shell(r, (void_shell_de[i] - 1)/2)) == (struct shell *)NULL) goto err; } /* orient loops */ Orient_loops(r); /* orient shells */ nmg_fix_normals(s_outer , &tol); for (i = 0; i < num_of_voids; i++) { nmg_fix_normals(void_shells[i] , &tol); nmg_invert_shell(void_shells[i]); } if (do_bots) { /* Merge all shells into one */ for (i = 0; i < num_of_voids; i++) nmg_js(s_outer, void_shells[i], &tol); /* write out BOT */ if (mk_bot_from_nmg(fdout, dir[entityno]->name, s_outer)) goto err; } else { /* Compute "geometry" for region and shell */ nmg_region_a(r , &tol); /* Write NMG solid */ if (mk_nmg(fdout , dir[entityno]->name , m)) goto err; } if (num_of_voids) { bu_free((char *)void_shell_de , "BREP: void shell DE's"); bu_free((char *)void_orient , "BREP: void shell orients"); bu_free((char *)void_shells , "brep: void shell list"); } v_list = vertex_root; while (v_list != NULL) { bu_free((char *)v_list->i_verts , "brep: iges_vertex"); bu_free((char *)v_list , "brep: vertex list"); v_list = v_list->next; } vertex_root = NULL; e_list = edge_root; while (e_list != NULL) { bu_free((char *)e_list->i_edge , "brep:iges_edge"); bu_free((char *)e_list , "brep: edge list"); e_list = e_list->next; } edge_root = NULL; return 1; err : if (num_of_voids) { bu_free((char *)void_shell_de , "BREP: void shell DE's"); bu_free((char *)void_orient , "BREP: void shell orients"); bu_free((char *)void_shells , "brep: void shell list"); } nmg_km(m); return 0; }