static void nmg_to_obj(struct nmgregion *r, struct db_full_path *pathp, int region_id, int aircode, int los, int material_id) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; struct bu_ptbl norms; char *region_name; int numverts = 0; /* Number of vertices to output */ int numtri = 0; /* Number of triangles to output */ int i; NMG_CK_REGION( r ); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string( pathp ); #if 0 printf("Attempting to process region %s\n", region_name); fflush(stdout); #endif m = r->m_p; NMG_CK_MODEL( m ); /* triangulate model */ nmg_triangulate_model( m, &tol ); /* list all vertices in result */ nmg_vertex_tabulate( &verts, &r->l.magic ); /* Get number of vertices */ numverts = BU_PTBL_END (&verts); /* get list of vertexuse normals */ if ( do_normals ) nmg_vertexuse_normal_tabulate( &norms, &r->l.magic ); /* XXX Check vertices, shells faces first? Do not want to punt mid-stream */ /* BEGIN CHECK SECTION */ /* Check vertices */ for ( i=0; i<numverts; i++ ) { v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); } /* Check triangles */ for ( BU_LIST_FOR( s, shell, &r->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; /* check vertex numbers for each triangle */ for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); vert_count++; i = bu_ptbl_locate( &verts, (long *)v ); if ( i < 0 ) { /*XXX*/ bu_ptbl_free( &verts); /*XXX*/ bu_free( region_name, "region name" ); bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r ); bu_exit(1, "ERROR: Can't find vertex in list!"); } } if ( vert_count > 3 ) { /*XXX*/ bu_ptbl_free( &verts); /*XXX*/ bu_free( region_name, "region name" ); bu_log( "lu x%x has %d vertices!\n", lu, vert_count ); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if ( vert_count < 3 ) continue; numtri++; } } } /* END CHECK SECTION */ /* Write pertinent info for this region */ if ( usemtl ) fprintf( fp, "usemtl %d_%d_%d\n", aircode, los, material_id ); fprintf( fp, "g %s", pathp->fp_names[0]->d_namep ); for ( i=1; i<pathp->fp_len; i++ ) fprintf( fp, "/%s", pathp->fp_names[i]->d_namep ); fprintf( fp, "\n" ); /* Write vertices */ for ( i=0; i<numverts; i++ ) { v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); if (inches) fprintf( fp, "v %f %f %f\n", V3ARGSIN( v->vg_p->coord )); else fprintf( fp, "v %f %f %f\n", V3ARGS( v->vg_p->coord )); } /* Write vertexuse normals */ if ( do_normals ) { for ( i=0; i<BU_PTBL_END( &norms ); i++ ) { struct vertexuse_a_plane *va; va = (struct vertexuse_a_plane *)BU_PTBL_GET( &norms, i ); NMG_CK_VERTEXUSE_A_PLANE( va ); if (inches) fprintf( fp, "vn %f %f %f\n", V3ARGSIN( va->N )); else fprintf( fp, "vn %f %f %f\n", V3ARGS( va->N )); } } /* output triangles */ for ( BU_LIST_FOR( s, shell, &r->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; int vert_count=0; int use_normals=1; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; /* Each vertexuse of the face must have a normal in order * to use the normals in Wavefront */ if ( do_normals ) { for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); if ( !eu->vu_p->a.magic_p ) { use_normals = 0; break; } if ( *eu->vu_p->a.magic_p != NMG_VERTEXUSE_A_PLANE_MAGIC ) { use_normals = 0; break; } } } else use_normals = 0; fprintf( fp, "f" ); /* list vertex numbers for each triangle */ for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); vert_count++; i = bu_ptbl_locate( &verts, (long *)v ); if ( i < 0 ) { bu_ptbl_free( &verts); bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r ); /*XXX*/ bu_free( region_name, "region name" ); /*XXX*/ bu_exit(1, "Can't find vertex in list!\n"); } if ( use_normals ) { int j; j = bu_ptbl_locate( &norms, (long *)eu->vu_p->a.magic_p ); fprintf( fp, " %ld//%ld", i+1+vert_offset, j+1+norm_offset ); } else fprintf( fp, " %ld", i+1+vert_offset ); } fprintf( fp, "\n" ); if ( vert_count > 3 ) { bu_ptbl_free( &verts); bu_free( region_name, "region name" ); bu_log( "lu x%x has %d vertices!\n", lu, vert_count ); bu_exit(1, "ERROR: LU is not a triangle\n" ); } } } }
static void nmg_to_egg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float UNUSED(color[3]), void *client_data) { struct model *m; struct shell *s; struct vertex *v; char *region_name; int region_polys=0; int vert_count=0; struct egg_conv_data *conv_data = (struct egg_conv_data *)client_data; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &conv_data->tol); /* Write pertinent info for this region */ fprintf(conv_data->fp, " <VertexPool> %s {\n", (region_name+1)); /* Build the VertexPool */ for (BU_LIST_FOR (s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) { struct loopuse *lu; vect_t facet_normal; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; /* Grab the face normal and save it for all the vertex loops */ NMG_GET_FU_NORMAL(facet_normal, fu); for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* check vertex numbers for each triangle */ for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(conv_data->fp, " <Vertex> %d {\n %f %f %f\n <Normal> { %f %f %f }\n }\n", vert_count, V3ARGS(v->vg_p->coord), V3ARGS(facet_normal)); } } } } fprintf(conv_data->fp, " }\n"); vert_count = 0; for (BU_LIST_FOR (s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; fprintf(conv_data->fp, " <Polygon> { \n <RGBA> { 1 1 1 1 } \n <VertexRef> { "); /* check vertex numbers for each triangle */ for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(conv_data->fp, " %d", vert_count); } fprintf(conv_data->fp, " <Ref> { \"%s\" } }\n }\n", region_name+1); region_polys++; } } } conv_data->tot_polygons += region_polys; bu_free(region_name, "region name"); }
int ged_bev(struct ged *gedp, int argc, const char *argv[]) { static const char *usage = "[-t] new_obj obj1 op obj2 op obj3 ..."; int i; int c; int ncpu; const char *cmdname; char *newname; struct rt_db_internal intern; struct directory *dp; const char *opstr; int failed; /* static due to longjmp */ static int triangulate = 0; static union tree *tmp_tree = NULL; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } cmdname = argv[0]; /* Establish tolerances */ gedp->ged_wdbp->wdb_initial_tree_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol; gedp->ged_wdbp->wdb_initial_tree_state.ts_tol = &gedp->ged_wdbp->wdb_tol; gedp->ged_wdbp->wdb_ttol.magic = RT_TESS_TOL_MAGIC; /* Initial values for options, must be reset each time */ ncpu = 1; triangulate = 0; /* Parse options. */ bu_optind = 1; /* re-init bu_getopt() */ while ((c=bu_getopt(argc, (char * const *)argv, "t")) != -1) { switch (c) { case 't': triangulate = 1; break; default: { bu_vls_printf(gedp->ged_result_str, "%s: option '%c' unknown\n", cmdname, c); } break; } } argc -= bu_optind; argv += bu_optind; newname = (char *)argv[0]; argv++; argc--; if (argc < 1) { bu_vls_printf(gedp->ged_result_str, "%s: Nothing to evaluate!!!\n", cmdname); return GED_ERROR; } GED_CHECK_EXISTS(gedp, newname, LOOKUP_QUIET, GED_ERROR); bu_vls_printf(gedp->ged_result_str, "%s: tessellating primitives with tolerances a=%g, r=%g, n=%g\n", argv[0], gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm); bev_facetize_tree = (union tree *)0; bev_nmg_model = nmg_mm(); gedp->ged_wdbp->wdb_initial_tree_state.ts_m = &bev_nmg_model; opstr = NULL; tmp_tree = (union tree *)NULL; while (argc) { i = db_walk_tree(gedp->ged_wdbp->dbip, 1, (const char **)argv, ncpu, &gedp->ged_wdbp->wdb_initial_tree_state, 0, /* take all regions */ bev_facetize_region_end, nmg_booltree_leaf_tess, (void *)gedp); if (i < 0) { bu_vls_printf(gedp->ged_result_str, "%s: error in db_walk_tree()\n", cmdname); /* Destroy NMG */ nmg_km(bev_nmg_model); return GED_ERROR; } argc--; argv++; if (tmp_tree && opstr) { union tree *new_tree; db_op_t op = db_str2op(opstr); BU_ALLOC(new_tree, union tree); RT_TREE_INIT(new_tree); new_tree->tr_b.tb_regionp = REGION_NULL; new_tree->tr_b.tb_left = tmp_tree; new_tree->tr_b.tb_right = bev_facetize_tree; switch (op) { case DB_OP_UNION: new_tree->tr_op = OP_UNION; break; case DB_OP_SUBTRACT: new_tree->tr_op = OP_SUBTRACT; break; case DB_OP_INTERSECT: new_tree->tr_op = OP_INTERSECT; break; default: { bu_vls_printf(gedp->ged_result_str, "%s: Unrecognized operator: (%c)\nAborting\n", argv[0], opstr[0]); db_free_tree(bev_facetize_tree, &rt_uniresource); nmg_km(bev_nmg_model); return GED_ERROR; } } tmp_tree = new_tree; bev_facetize_tree = (union tree *)NULL; } else if (!tmp_tree && !opstr) { /* just starting out */ tmp_tree = bev_facetize_tree; bev_facetize_tree = (union tree *)NULL; } if (argc) { opstr = argv[0]; argc--; argv++; } else opstr = NULL; } if (tmp_tree) { /* Now, evaluate the boolean tree into ONE region */ bu_vls_printf(gedp->ged_result_str, "%s: evaluating boolean expressions\n", cmdname); if (BU_SETJUMP) { BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Boolean evaluation failed!!!\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } failed = nmg_boolean(tmp_tree, bev_nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource); BU_UNSETJUMP; } else failed = 1; if (failed) { bu_vls_printf(gedp->ged_result_str, "%s: no resulting region, aborting\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } /* New region remains part of this nmg "model" */ NMG_CK_REGION(tmp_tree->tr_d.td_r); bu_vls_printf(gedp->ged_result_str, "%s: facetize %s\n", cmdname, tmp_tree->tr_d.td_name); nmg_vmodel(bev_nmg_model); /* Triangulate model, if requested */ if (triangulate) { bu_vls_printf(gedp->ged_result_str, "%s: triangulating resulting object\n", cmdname); if (BU_SETJUMP) { BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Triangulation failed!!!\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } nmg_triangulate_model(bev_nmg_model, &gedp->ged_wdbp->wdb_tol); BU_UNSETJUMP; } bu_vls_printf(gedp->ged_result_str, "%s: converting NMG to database format\n", cmdname); /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_NMG; intern.idb_meth = &OBJ[ID_NMG]; intern.idb_ptr = (void *)bev_nmg_model; bev_nmg_model = (struct model *)NULL; GED_DB_DIRADD(gedp, dp, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); tmp_tree->tr_d.td_r = (struct nmgregion *)NULL; /* Free boolean tree, and the regions in it. */ db_free_tree(tmp_tree, &rt_uniresource); return GED_OK; }
static void nmg_to_acad(struct nmgregion *r, const struct db_full_path *pathp, int region_id) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; char *region_name; int numverts = 0; /* Number of vertices to output */ int numtri = 0; /* Number of triangles to output */ int tricount = 0; /* Triangle number */ int i; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &tol); /* list all vertices in result */ nmg_vertex_tabulate(&verts, &r->l.magic); /* Get number of vertices */ numverts = BU_PTBL_END (&verts); /* BEGIN CHECK SECTION */ /* Check vertices */ for (i=0; i<numverts; i++) { v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); } /* Check triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* check vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); vert_count++; i = bu_ptbl_locate(&verts, (long *)v); if (i < 0) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r); bu_exit(1, "ERROR: Triangle vertex was not located\n"); } } if (vert_count > 3) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("lu %p has too many (%d) vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) continue; numtri++; } } } /* END CHECK SECTION */ /* Write pertinent info for this region */ fprintf(fp, "%s\n", (region_name+1)); /* No mirror plane */ fprintf(fp, "%d\n", 0); /* Number of vertices */ fprintf(fp, "%d\n", numverts); /* Write numverts, then vertices */ for (i=0; i<numverts; i++) { v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); if (inches) fprintf(fp, "%f %f %f\n", V3ARGSIN(v->vg_p->coord)); else fprintf(fp, "%f %f %f\n", V3ARGS(v->vg_p->coord)); } /* Number of sub-parts (always 1 with BRL-CAD) */ fprintf(fp, "%d\n", 1); /* Write out name again */ fprintf(fp, "%s\n", (region_name+1)); /* Number of triangles, number of vert/tri (3) */ fprintf(fp, "%d %d\n", numtri, 3); /* output triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* list vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); vert_count++; i = bu_ptbl_locate(&verts, (long *)v); if (i < 0) { bu_ptbl_free(&verts); bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r); bu_free(region_name, "region name"); bu_exit(1, "ERROR: Can't find vertex in list!\n"); } fprintf(fp, " %d", i+1); } /* Output other info. for triangle ICOAT, component#, facet# */ /* Map Icoat from material table later */ /* fprintf(fp, "%s icomp=%d material=%d:\n", (region_name+1), region_id);*/ fprintf(fp, " %d %d %d\n", 0, region_id, ++tricount); if (vert_count > 3) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("lu %p has %d vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) continue; tot_polygons++; } } } /* regions_converted++; printf("Processed region %s\n", region_name); printf("Regions attempted = %d Regions done = %d\n", regions_tried, regions_converted); fflush(stdout); */ bu_ptbl_free(&verts); bu_free(region_name, "region name"); }
static void nmg_to_dxf(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float color[3]) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; char *region_name; int region_polys=0; int tri_count=0; int color_num; int do_triangulate=0; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* Count triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; int vert_count=0; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { vert_count++; } if (vert_count > 3) { do_triangulate = 1; goto triangulate; } tri_count++; } } } triangulate: if (do_triangulate) { /* triangulate model */ nmg_triangulate_model(m, &tol); /* Count triangles */ tri_count = 0; for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; tri_count++; } } } } nmg_vertex_tabulate(&verts, &r->l.magic); color_num = find_closest_color(color); if (polyface_mesh) { size_t i; fprintf(fp, "0\nPOLYLINE\n8\n%s\n62\n%d\n70\n64\n71\n%lu\n72\n%d\n", region_name, color_num, (unsigned long)BU_PTBL_LEN(&verts), tri_count); for (i = 0; i < BU_PTBL_LEN(&verts); i++) { fprintf(fp, "0\nVERTEX\n8\n%s\n", region_name); v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); if (inches) { fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGSIN(v->vg_p->coord)); } else { fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGS(v->vg_p->coord)); } } } /* Check triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; if (polyface_mesh) { fprintf(fp, "0\nVERTEX\n8\n%s\n70\n128\n10\n0.0\n20\n0.0\n30\n0.0\n", region_name); } else { fprintf(fp, "0\n3DFACE\n8\n%s\n62\n%d\n", region_name, color_num); } /* check vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (polyface_mesh) { fprintf(fp, "%d\n%d\n", vert_count+70, bu_ptbl_locate(&verts, (long *)v) + 1); } else { if (inches) { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X] / 25.4, 20 + vert_count - 1, v->vg_p->coord[Y] / 25.4, 30 + vert_count -1, v->vg_p->coord[Z] / 25.4); } else { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X], 20 + vert_count - 1, v->vg_p->coord[Y], 30 + vert_count -1, v->vg_p->coord[Z]); } } } if (vert_count > 3) { bu_free(region_name, "region name"); bu_log("lu %p has %d vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) { continue; } else { /* repeat the last vertex for the benefit of codes * that interpret the dxf specification for * 3DFACES as requiring a fourth vertex even when * only three are input. */ if (!polyface_mesh) { vert_count++; if (inches) { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X] / 25.4, 20 + vert_count - 1, v->vg_p->coord[Y] / 25.4, 30 + vert_count -1, v->vg_p->coord[Z] / 25.4); } else { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X], 20 + vert_count - 1, v->vg_p->coord[Y], 30 + vert_count -1, v->vg_p->coord[Z]); } } } tot_polygons++; region_polys++; } } } bu_ptbl_free(&verts); bu_free(region_name, "region name"); if (polyface_mesh) { fprintf(fp, "0\nSEQEND\n"); } }
int ged_facetize(struct ged *gedp, int argc, const char *argv[]) { int i; int c; char *newname; struct rt_db_internal intern; struct directory *dp; int failed; int nmg_use_tnurbs = 0; struct db_tree_state init_state; struct db_i *dbip; union tree *facetize_tree; struct model *nmg_model; static const char *usage = "[ [-P] | [-n] [-t] [-T] ] new_obj old_obj [old_obj2 old_obj3 ...]"; /* static due to jumping */ static int triangulate; static int make_bot; static int marching_cube; static int screened_poisson; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } dbip = gedp->ged_wdbp->dbip; RT_CHECK_DBI(dbip); db_init_db_tree_state(&init_state, dbip, gedp->ged_wdbp->wdb_resp); /* Establish tolerances */ init_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol; init_state.ts_tol = &gedp->ged_wdbp->wdb_tol; /* Initial values for options, must be reset each time */ marching_cube = 0; screened_poisson = 0; triangulate = 0; make_bot = 1; /* Parse options. */ bu_optind = 1; /* re-init bu_getopt() */ while ((c=bu_getopt(argc, (char * const *)argv, "mntTP")) != -1) { switch (c) { case 'm': marching_cube = triangulate = 1; /* no break, marching cubes assumes nmg for now */ case 'n': make_bot = 0; break; case 'P': screened_poisson = 1; triangulate = 1; make_bot = 1; break; case 'T': triangulate = 1; break; case 't': nmg_use_tnurbs = 1; break; default: { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } } } argc -= bu_optind; argv += bu_optind; if (argc < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n"); return GED_ERROR; } if (screened_poisson && (marching_cube || !make_bot || nmg_use_tnurbs)) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } newname = (char *)argv[0]; argv++; argc--; if (argc < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n"); return GED_ERROR; } if (db_lookup(dbip, newname, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "error: solid '%s' already exists, aborting\n", newname); return GED_ERROR; } if (screened_poisson) { struct rt_bot_internal *bot; BU_ALLOC(bot, struct rt_bot_internal); bot->magic = RT_BOT_INTERNAL_MAGIC; bot->mode = RT_BOT_SOLID; bot->orientation = RT_BOT_UNORIENTED; bot->thickness = (fastf_t *)NULL; bot->face_mode = (struct bu_bitv *)NULL; /* TODO - generate point cloud, then mesh - need to see the input points for debugging */ (void)rt_generate_mesh(&(bot->faces), (int *)&(bot->num_faces), (point_t **)&(bot->vertices), (int *)&(bot->num_vertices), dbip, argv[0], 15); /* Export BOT as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_BOT; intern.idb_meth = &OBJ[ID_BOT]; intern.idb_ptr = (void *) bot; } else { bu_vls_printf(gedp->ged_result_str, "facetize: tessellating primitives with tolerances a=%g, r=%g, n=%g\n", gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm); facetize_tree = (union tree *)0; nmg_model = nmg_mm(); init_state.ts_m = &nmg_model; i = db_walk_tree(dbip, argc, (const char **)argv, 1, &init_state, 0, /* take all regions */ facetize_region_end, nmg_use_tnurbs ? nmg_booltree_leaf_tnurb : nmg_booltree_leaf_tess, (void *)&facetize_tree ); if (i < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: error in db_walk_tree()\n"); /* Destroy NMG */ nmg_km(nmg_model); return GED_ERROR; } if (facetize_tree) { /* Now, evaluate the boolean tree into ONE region */ bu_vls_printf(gedp->ged_result_str, "facetize: evaluating boolean expressions\n"); if (!BU_SETJUMP) { /* try */ failed = nmg_boolean(facetize_tree, nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: facetization failed!!!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; } else failed = 1; if (failed) { bu_vls_printf(gedp->ged_result_str, "facetize: no resulting region, aborting\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } /* New region remains part of this nmg "model" */ NMG_CK_REGION(facetize_tree->tr_d.td_r); bu_vls_printf(gedp->ged_result_str, "facetize: %s\n", facetize_tree->tr_d.td_name); /* Triangulate model, if requested */ if (triangulate && !make_bot) { bu_vls_printf(gedp->ged_result_str, "facetize: triangulating resulting object\n"); if (!BU_SETJUMP) { /* try */ if (marching_cube == 1) nmg_triangulate_model_mc(nmg_model, &gedp->ged_wdbp->wdb_tol); else nmg_triangulate_model(nmg_model, &gedp->ged_wdbp->wdb_tol); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: triangulation failed!!!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; } if (make_bot) { struct rt_bot_internal *bot; struct nmgregion *r; struct shell *s; bu_vls_printf(gedp->ged_result_str, "facetize: converting to BOT format\n"); /* WTF, FIXME: this is only dumping the first shell of the first region */ r = BU_LIST_FIRST(nmgregion, &nmg_model->r_hd); if (r && BU_LIST_NEXT(nmgregion, &r->l) != (struct nmgregion *)&nmg_model->r_hd) bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one region, only facetizing the first\n"); s = BU_LIST_FIRST(shell, &r->s_hd); if (s && BU_LIST_NEXT(shell, &s->l) != (struct shell *)&r->s_hd) bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one shell, only facetizing the first\n"); if (!BU_SETJUMP) { /* try */ bot = (struct rt_bot_internal *)nmg_bot(s, &gedp->ged_wdbp->wdb_tol); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: conversion to BOT failed!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; nmg_km(nmg_model); nmg_model = (struct model *)NULL; /* Export BOT as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_BOT; intern.idb_meth = &OBJ[ID_BOT]; intern.idb_ptr = (void *) bot; } else { bu_vls_printf(gedp->ged_result_str, "facetize: converting NMG to database format\n"); /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_NMG; intern.idb_meth = &OBJ[ID_NMG]; intern.idb_ptr = (void *)nmg_model; nmg_model = (struct model *)NULL; } } dp=db_diradd(dbip, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", newname); return GED_ERROR; } if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Failed to write %s to database\n", newname); rt_db_free_internal(&intern); return GED_ERROR; } if (!screened_poisson) { facetize_tree->tr_d.td_r = (struct nmgregion *)NULL; /* Free boolean tree, and the regions in it */ db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; } return GED_OK; }