/** * B U _ P T B L * * This version maintained for source compatibility with existing NMG code. */ int bu_ptbl(struct bu_ptbl *b, int func, long int *p) { if (func == BU_PTBL_INIT) { bu_ptbl_init(b, 64, "bu_ptbl() buffer[]"); return 0; } else if (func == BU_PTBL_RST) { bu_ptbl_reset(b); return 0; } else if (func == BU_PTBL_INS) { return bu_ptbl_ins(b, p); } else if (func == BU_PTBL_LOC) { return bu_ptbl_locate(b, p); } else if ( func == BU_PTBL_ZERO ) { bu_ptbl_zero(b, p); return( 0 ); } else if (func == BU_PTBL_INS_UNIQUE) { return bu_ptbl_ins_unique(b, p); } else if (func == BU_PTBL_RM) { return bu_ptbl_rm(b, p); } else if (func == BU_PTBL_CAT) { bu_ptbl_cat( b, (const struct bu_ptbl *)p ); return(0); } else if (func == BU_PTBL_FREE) { bu_ptbl_free(b); return (0); } else { BU_CK_PTBL(b); bu_log("bu_ptbl(%8x) Unknown table function %d\n", b, func); bu_bomb("bu_ptbl"); } return(-1);/* this is here to keep lint happy */ }
void diff_free_result(struct diff_result *result) { unsigned int i = 0; if (result->obj_name) { bu_free(result->obj_name, "free name copy in diff result"); } BU_PUT(result->diff_tol, struct bn_tol); for (i = 0; i < BU_PTBL_LEN(result->param_diffs); i++) { struct diff_avp *avp = (struct diff_avp *)BU_PTBL_GET(result->param_diffs, i); diff_free_avp(avp); BU_PUT(avp, struct diff_avp); } bu_ptbl_free(result->param_diffs); BU_PUT(result->param_diffs, struct bu_ptbl); for (i = 0; i < BU_PTBL_LEN(result->attr_diffs); i++) { struct diff_avp *avp = (struct diff_avp *)BU_PTBL_GET(result->attr_diffs, i); diff_free_avp(avp); BU_PUT(avp, struct diff_avp); } bu_ptbl_free(result->attr_diffs); BU_PUT(result->attr_diffs, struct bu_ptbl); }
/** * R T _ F R E E _ S O L T A B * * Decrement use count on soltab structure. If no longer needed, * release associated storage, and free the structure. * * This routine semaphore protects against other copies of itself * running in parallel, and against other routines (such as * rt_find_identical_solid()) which might also be modifying the linked * list heads. * * Called by - * db_free_tree() * rt_clean() * rt_gettrees() * rt_kill_deal_solid_refs() */ void rt_free_soltab(struct soltab *stp) { int hash; RT_CK_SOLTAB(stp); if ( stp->st_id < 0 ) bu_bomb("rt_free_soltab: bad st_id"); hash = db_dirhash(stp->st_dp->d_namep); ACQUIRE_SEMAPHORE_TREE(hash); /* start critical section */ if ( --(stp->st_uses) > 0 ) { RELEASE_SEMAPHORE_TREE(hash); return; } BU_LIST_DEQUEUE( &(stp->l2) ); /* remove from st_dp->d_use_hd list */ BU_LIST_DEQUEUE( &(stp->l) ); /* uses rti_solidheads[] */ RELEASE_SEMAPHORE_TREE(hash); /* end critical section */ if ( stp->st_aradius > 0 ) { stp->st_meth->ft_free( stp ); stp->st_aradius = 0; } if ( stp->st_matp ) bu_free( (char *)stp->st_matp, "st_matp"); stp->st_matp = (matp_t)0; /* Sanity */ bu_ptbl_free(&stp->st_regions); stp->st_dp = DIR_NULL; /* Sanity */ if ( stp->st_path.magic ) { RT_CK_FULL_PATH( &stp->st_path ); db_free_full_path( &stp->st_path ); } bu_free( (char *)stp, "struct soltab" ); }
static void nmg_to_psurf(struct nmgregion *r, FILE *fp_psurf) /* NMG region to be converted. */ /* Jack format file to write vertex list to. */ { int i; int *map; /* map from v->index to Jack vert # */ struct bu_ptbl vtab; /* vertex table */ map = (int *)bu_calloc(r->m_p->maxindex, sizeof(int), "Jack vert map"); /* Built list of vertex structs */ nmg_vertex_tabulate( &vtab, &r->l.magic ); /* FIXME: What to do if 0 vertices? */ /* Print list of unique vertices and convert from mm to cm. */ for (i = 0; i < BU_PTBL_END(&vtab); i++) { struct vertex *v; struct vertex_g *vg; v = (struct vertex *)BU_PTBL_GET(&vtab, i); NMG_CK_VERTEX(v); vg = v->vg_p; NMG_CK_VERTEX_G(vg); NMG_INDEX_ASSIGN( map, v, i+1 ); /* map[v->index] = i+1 */ fprintf(fp_psurf, "%f\t%f\t%f\n", vg->coord[X] / 10., vg->coord[Y] / 10., vg->coord[Z] / 10.); } fprintf(fp_psurf, ";;\n"); jack_faces(r, fp_psurf, map); bu_ptbl_free(&vtab); bu_free( (char *)map, "Jack vert map" ); }
int ged_nmg_collapse(struct ged *gedp, int argc, const char *argv[]) { char *new_name; struct model *m; struct rt_db_internal intern; struct directory *dp; struct bu_ptbl faces; struct face *fp; size_t count; fastf_t tol_coll; fastf_t min_angle; static const char *usage = "nmg_prim new_prim max_err_dist [min_angle]"; 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 < 4) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } if (strchr(argv[2], '/')) { bu_vls_printf(gedp->ged_result_str, "Do not use '/' in solid names: %s\n", argv[2]); return GED_ERROR; } new_name = (char *)argv[2]; if (db_lookup(gedp->ged_wdbp->dbip, new_name, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "%s already exists\n", new_name); return GED_ERROR; } if ((dp=db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_NOISY)) == RT_DIR_NULL) return GED_ERROR; if (dp->d_flags & RT_DIR_COMB) { bu_vls_printf(gedp->ged_result_str, "%s is a combination, only NMG primitives are allowed here\n", argv[1]); return GED_ERROR; } if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (matp_t)NULL, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Failed to get internal form of %s!!!!\n", argv[1]); return GED_ERROR; } if (intern.idb_type != ID_NMG) { bu_vls_printf(gedp->ged_result_str, "%s is not an NMG solid!!!!\n", argv[1]); rt_db_free_internal(&intern); return GED_ERROR; } tol_coll = atof(argv[3]) * gedp->ged_wdbp->dbip->dbi_local2base; if (tol_coll <= 0.0) { bu_vls_printf(gedp->ged_result_str, "tolerance distance too small\n"); return GED_ERROR; } if (argc == 5) { min_angle = atof(argv[4]); if (min_angle < 0.0) { bu_vls_printf(gedp->ged_result_str, "Minimum angle cannot be less than zero\n"); return GED_ERROR; } } else min_angle = 0.0; m = (struct model *)intern.idb_ptr; NMG_CK_MODEL(m); /* check that all faces are planar */ nmg_face_tabulate(&faces, &m->magic); for (BU_PTBL_FOR(fp, (struct face *), &faces)) { if (fp->g.magic_p != NULL && *(fp->g.magic_p) != NMG_FACE_G_PLANE_MAGIC) { bu_log("\tnot planar\n"); bu_ptbl_free(&faces); bu_vls_printf(gedp->ged_result_str, "nmg_collapse can only be applied to NMG primitives with planar faces\n"); return GED_ERROR; } } bu_ptbl_free(&faces); /* triangulate model */ nmg_triangulate_model(m, &gedp->ged_wdbp->wdb_tol); count = (size_t)nmg_edge_collapse(m, &gedp->ged_wdbp->wdb_tol, tol_coll, min_angle); dp=db_diradd(gedp->ged_wdbp->dbip, new_name, 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", new_name); rt_db_free_internal(&intern); return GED_ERROR; } if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) { rt_db_free_internal(&intern); bu_vls_printf(gedp->ged_result_str, "Database write error, aborting.\n"); return GED_ERROR; } rt_db_free_internal(&intern); bu_vls_printf(gedp->ged_result_str, "%zu edges collapsed\n", count); return GED_OK; }
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" ); } } } }
int main(int argc, char **argv) { int i = 0; int diff_state = 0; struct bu_ptbl results; struct db_i *dbip1 = DBI_NULL; struct db_i *dbip2 = DBI_NULL; /*struct bu_vls diff_log = BU_VLS_INIT_ZERO;*/ struct bn_tol *diff_tol; BU_GET(diff_tol, struct bn_tol); diff_tol->dist = BN_TOL_DIST; BU_PTBL_INIT(&results); if (argc != 3) { bu_log("Error - please specify two .g files\n"); bu_exit(EXIT_FAILURE, NULL); } if (!bu_file_exists(argv[1], NULL)) { bu_exit(1, "Cannot stat file %s\n", argv[1]); } if (!bu_file_exists(argv[2], NULL)) { bu_exit(1, "Cannot stat file %s\n", argv[2]); } if ((dbip1 = db_open(argv[1], DB_OPEN_READONLY)) == DBI_NULL) { bu_exit(1, "Cannot open geometry database file %s\n", argv[1]); } RT_CK_DBI(dbip1); if (db_dirbuild(dbip1) < 0) { db_close(dbip1); bu_exit(1, "db_dirbuild failed on geometry database file %s\n", argv[1]); } /* Reset the material head so we don't get warnings when the global * is overwritten. This will go away when material_head ceases to * be a librt global.*/ rt_new_material_head(MATER_NULL); if ((dbip2 = db_open(argv[2], DB_OPEN_READONLY)) == DBI_NULL) { bu_exit(1, "Cannot open geometry database file %s\n", argv[2]); } RT_CK_DBI(dbip2); if (db_dirbuild(dbip2) < 0) { db_close(dbip1); db_close(dbip2); bu_exit(1, "db_dirbuild failed on geometry database file %s\n", argv[1]); } diff_state = db_diff(dbip1, dbip2, diff_tol, DB_COMPARE_ALL, &results); if (diff_state == DIFF_UNCHANGED) { bu_log("No differences found.\n"); } else { print_diff_summary(&results); } for (i = 0; i < (int)BU_PTBL_LEN(&results); i++) { struct diff_result *result = (struct diff_result *)BU_PTBL_GET(&results, i); diff_free_result(result); } bu_ptbl_free(&results); BU_PUT(diff_tol, struct bn_tol); db_close(dbip1); db_close(dbip2); return 0; }
static int selection_command( struct ged *gedp, struct rt_db_internal *ip, int argc, const char *argv[]) { int i; struct rt_selection_set *selection_set; struct bu_ptbl *selections; struct rt_selection *new_selection; struct rt_selection_query query; const char *cmd, *solid_name, *selection_name; /* 0 1 2 3 * brep <solid_name> selection subcommand */ if (argc < 4) { return -1; } solid_name = argv[1]; cmd = argv[3]; if (BU_STR_EQUAL(cmd, "append")) { /* append to named selection - selection is created if it doesn't exist */ void (*free_selection)(struct rt_selection *); /* 4 5 6 7 8 9 10 * selection_name startx starty startz dirx diry dirz */ if (argc != 11) { bu_log("wrong args for selection append"); return -1; } selection_name = argv[4]; /* find matching selections */ query.start[X] = atof(argv[5]); query.start[Y] = atof(argv[6]); query.start[Z] = atof(argv[7]); query.dir[X] = atof(argv[8]); query.dir[Y] = atof(argv[9]); query.dir[Z] = atof(argv[10]); query.sorting = RT_SORT_CLOSEST_TO_START; selection_set = ip->idb_meth->ft_find_selections(ip, &query); if (!selection_set) { bu_log("no matching selections"); return -1; } /* could be multiple options, just grabbing the first and * freeing the rest */ selections = &selection_set->selections; new_selection = (struct rt_selection *)BU_PTBL_GET(selections, 0); free_selection = selection_set->free_selection; for (i = BU_PTBL_LEN(selections) - 1; i > 0; --i) { long *s = BU_PTBL_GET(selections, i); free_selection((struct rt_selection *)s); bu_ptbl_rm(selections, s); } bu_ptbl_free(selections); BU_FREE(selection_set, struct rt_selection_set); /* get existing/new selections set in gedp */ selection_set = ged_get_selection_set(gedp, solid_name, selection_name); selection_set->free_selection = free_selection; selections = &selection_set->selections; /* TODO: Need to implement append by passing new and * existing selection to an rt_brep_evaluate_selection. * For now, new selection simply replaces old one. */ for (i = BU_PTBL_LEN(selections) - 1; i >= 0; --i) { long *s = BU_PTBL_GET(selections, i); free_selection((struct rt_selection *)s); bu_ptbl_rm(selections, s); } bu_ptbl_ins(selections, (long *)new_selection); } else if (BU_STR_EQUAL(cmd, "translate")) { struct rt_selection_operation operation; /* 4 5 6 7 * selection_name dx dy dz */ if (argc != 8) { return -1; } selection_name = argv[4]; selection_set = ged_get_selection_set(gedp, solid_name, selection_name); selections = &selection_set->selections; if (BU_PTBL_LEN(selections) < 1) { return -1; } for (i = 0; i < (int)BU_PTBL_LEN(selections); ++i) { int ret; operation.type = RT_SELECTION_TRANSLATION; operation.parameters.tran.dx = atof(argv[5]); operation.parameters.tran.dy = atof(argv[6]); operation.parameters.tran.dz = atof(argv[7]); ret = ip->idb_meth->ft_process_selection(ip, gedp->ged_wdbp->dbip, (struct rt_selection *)BU_PTBL_GET(selections, i), &operation); if (ret != 0) { return ret; } } } return 0; }
void db_close(register struct db_i *dbip) { register int i; register struct directory *dp, *nextdp; if (!dbip) return; RT_CK_DBI(dbip); if (RT_G_DEBUG&DEBUG_DB) bu_log("db_close(%s) %p uses=%d\n", dbip->dbi_filename, (void *)dbip, dbip->dbi_uses); bu_semaphore_acquire(BU_SEM_LISTS); if ((--dbip->dbi_uses) > 0) { bu_semaphore_release(BU_SEM_LISTS); /* others are still using this database */ return; } bu_semaphore_release(BU_SEM_LISTS); /* ready to free the database -- use count is now zero */ /* free up any mapped files */ if (dbip->dbi_mf) { /* * We're using an instance of a memory mapped file. * We have two choices: * Either dissociate from the memory mapped file * by clearing dbi_mf->apbuf, or * keeping our already-scanned dbip ready for * further use, with our dbi_uses counter at 0. * For speed of re-open, at the price of some address space, * the second choice is taken. */ bu_close_mapped_file(dbip->dbi_mf); bu_free_mapped_files(0); dbip->dbi_mf = (struct bu_mapped_file *)NULL; } /* try to ensure/encourage that the file is written out */ db_sync(dbip); if (dbip->dbi_fp) { fclose(dbip->dbi_fp); } if (dbip->dbi_title) bu_free(dbip->dbi_title, "dbi_title"); if (dbip->dbi_filename) bu_free(dbip->dbi_filename, "dbi_filename"); db_free_anim(dbip); rt_color_free(); /* Free MaterHead list */ /* Release map of database holes */ rt_mempurge(&(dbip->dbi_freep)); rt_memclose(); dbip->dbi_inmem = NULL; /* sanity */ bu_ptbl_free(&dbip->dbi_clients); /* Free all directory entries */ for (i = 0; i < RT_DBNHASH; i++) { for (dp = dbip->dbi_Head[i]; dp != RT_DIR_NULL;) { RT_CK_DIR(dp); nextdp = dp->d_forw; RT_DIR_FREE_NAMEP(dp); /* frees d_namep */ if ((dp->d_flags & RT_DIR_INMEM) && (dp->d_un.ptr != NULL)) { bu_free(dp->d_un.ptr, "db_close d_un.ptr"); dp->d_un.ptr = NULL; dp->d_len = 0; } /* Put 'dp' back on the freelist */ dp->d_forw = rt_uniresource.re_directory_hd; rt_uniresource.re_directory_hd = dp; /* null'ing the forward pointer here is a huge * memory leak as it causes the loss of all * nodes on the freelist except the first. * (so don't do it) */ dp = nextdp; } dbip->dbi_Head[i] = RT_DIR_NULL; /* sanity*/ } if (dbip->dbi_filepath != NULL) { bu_free_argv(2, dbip->dbi_filepath); dbip->dbi_filepath = NULL; /* sanity */ } bu_free((char *)dbip, "struct db_i"); }
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_draw_guts(struct ged *gedp, int argc, const char *argv[], int kind) { size_t i; int drawtrees_retval; int flag_A_attr=0; int flag_o_nonunique=1; int last_opt=0; struct bu_vls vls = BU_VLS_INIT_ZERO; static const char *usage = "<[-R -C#/#/# -s] objects> | <-o -A attribute name/value pairs>"; /* #define DEBUG_TIMING 1 */ #ifdef DEBUG_TIMING int64_t elapsedtime; #endif GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_DRAWABLE(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; } #ifdef DEBUG_TIMING elapsedtime = bu_gettime(); #endif /* skip past cmd */ --argc; ++argv; /* check args for "-A" (attributes) and "-o" */ for (i = 0; i < (size_t)argc; i++) { char *ptr_A=NULL; char *ptr_o=NULL; char *c; if (*argv[i] != '-') { /* Done checking options. If our display is non-empty, * add -R to keep current view. */ if (BU_LIST_NON_EMPTY(gedp->ged_gdp->gd_headDisplay)) { bu_vls_strcat(&vls, " -R"); } break; } ptr_A=strchr(argv[i], 'A'); if (ptr_A) flag_A_attr = 1; ptr_o=strchr(argv[i], 'o'); if (ptr_o) flag_o_nonunique = 2; last_opt = i; if (!ptr_A && !ptr_o) { bu_vls_putc(&vls, ' '); bu_vls_strcat(&vls, argv[i]); continue; } if (strlen(argv[i]) == ((size_t)1 + (ptr_A != NULL) + (ptr_o != NULL))) { /* argv[i] is just a "-A" or "-o" */ continue; } /* copy args other than "-A" or "-o" */ bu_vls_putc(&vls, ' '); c = (char *)argv[i]; while (*c != '\0') { if (*c != 'A' && *c != 'o') { bu_vls_putc(&vls, *c); } c++; } } if (flag_A_attr) { /* args are attribute name/value pairs */ struct bu_attribute_value_set avs; int max_count=0; int remaining_args=0; int new_argc=0; char **new_argv=NULL; struct bu_ptbl *tbl; remaining_args = argc - last_opt - 1; if (remaining_args < 2 || remaining_args%2) { bu_vls_printf(gedp->ged_result_str, "Error: must have even number of arguments (name/value pairs)\n"); bu_vls_free(&vls); return GED_ERROR; } bu_avs_init(&avs, (argc - last_opt)/2, "ged_draw_guts avs"); i = 0; while (i < (size_t)argc) { if (*argv[i] == '-') { i++; continue; } /* this is a name/value pair */ if (flag_o_nonunique == 2) { bu_avs_add_nonunique(&avs, argv[i], argv[i+1]); } else { bu_avs_add(&avs, argv[i], argv[i+1]); } i += 2; } tbl = db_lookup_by_attr(gedp->ged_wdbp->dbip, RT_DIR_REGION | RT_DIR_SOLID | RT_DIR_COMB, &avs, flag_o_nonunique); bu_avs_free(&avs); if (!tbl) { bu_log("Error: db_lookup_by_attr() failed!!\n"); bu_vls_free(&vls); return TCL_ERROR; } if (BU_PTBL_LEN(tbl) < 1) { /* nothing matched, just return */ bu_vls_free(&vls); return TCL_OK; } for (i = 0; i < BU_PTBL_LEN(tbl); i++) { struct directory *dp; dp = (struct directory *)BU_PTBL_GET(tbl, i); bu_vls_putc(&vls, ' '); bu_vls_strcat(&vls, dp->d_namep); } max_count = BU_PTBL_LEN(tbl) + last_opt + 1; bu_ptbl_free(tbl); bu_free((char *)tbl, "ged_draw_guts ptbl"); new_argv = (char **)bu_calloc(max_count+1, sizeof(char *), "ged_draw_guts new_argv"); new_argc = bu_argv_from_string(new_argv, max_count, bu_vls_addr(&vls)); /* First, delete any mention of these objects. * Silently skip any leading options (which start with minus signs). */ for (i = 0; i < (size_t)new_argc; ++i) { /* Skip any options */ if (new_argv[i][0] == '-') { /* If this option requires an argument which was * provided separately (e.g. '-C 0/255/0' instead of * '-C0/255/0'), skip the argument too. */ if (strlen(argv[i]) == 2 && strchr("mxCP", argv[i][1])) { i++; } continue; } dl_erasePathFromDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, gedp->ged_free_vlist_callback, new_argv[i], 0, gedp->freesolid); } drawtrees_retval = _ged_drawtrees(gedp, new_argc, (const char **)new_argv, kind, (struct _ged_client_data *)0); bu_vls_free(&vls); bu_free((char *)new_argv, "ged_draw_guts new_argv"); if (drawtrees_retval) { return GED_ERROR; } } else { int empty_display; bu_vls_free(&vls); empty_display = 1; if (BU_LIST_NON_EMPTY(gedp->ged_gdp->gd_headDisplay)) { empty_display = 0; } /* First, delete any mention of these objects. * Silently skip any leading options (which start with minus signs). */ for (i = 0; i < (size_t)argc; ++i) { /* Skip any options */ if (argv[i][0] == '-') { /* If this option requires an argument which was * provided separately (e.g. '-C 0/255/0' instead of * '-C0/255/0'), skip the argument too. */ if (strlen(argv[i]) == 2 && strchr("mxCP", argv[i][1])) { i++; } continue; } dl_erasePathFromDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, gedp->ged_free_vlist_callback, argv[i], 0, gedp->freesolid); } /* if our display is non-empty add -R to keep current view */ if (!empty_display) { int new_argc; char **new_argv; new_argc = argc + 1; new_argv = (char **)bu_malloc(new_argc * sizeof(char *), "ged_draw_guts new_argv"); new_argv[0] = bu_strdup("-R"); for (i = 0; i < (size_t)argc; ++i) { new_argv[i + 1] = bu_strdup(argv[i]); } drawtrees_retval = _ged_drawtrees(gedp, new_argc, (const char **)new_argv, kind, (struct _ged_client_data *)0); for (i = 0; i < (size_t)new_argc; ++i) { bu_free(new_argv[i], "ged_draw_guts new_argv[i] - bu_strdup(argv[i])"); } bu_free(new_argv, "ged_draw_guts new_argv"); } else { drawtrees_retval = _ged_drawtrees(gedp, argc, argv, kind, (struct _ged_client_data *)0); } if (drawtrees_retval) { return GED_ERROR; } } #ifdef DEBUG_TIMING elapsedtime = bu_gettime() - elapsedtime; { int seconds = elapsedtime / 1000000; int minutes = seconds / 60; int hours = minutes / 60; minutes = minutes % 60; seconds = seconds %60; bu_vls_printf(gedp->ged_result_str, "Elapsed time: %02d:%02d:%02d\n", hours, minutes, seconds); } #endif return GED_OK; }
/* 0 = no difference within tolerance, 1 = difference >= tolerance */ int analyze_raydiff(/* TODO - decide what to return. Probably some sort of left, common, right segment sets. See what rtcheck does... */ struct db_i *dbip, const char *obj1, const char *obj2, struct bn_tol *tol) { int ret; int count = 0; struct rt_i *rtip; int ncpus = bu_avail_cpus(); point_t min, mid, max; struct rt_pattern_data *xdata, *ydata, *zdata; fastf_t *rays; struct raydiff_container *state; if (!dbip || !obj1 || !obj2 || !tol) return 0; rtip = rt_new_rti(dbip); if (rt_gettree(rtip, obj1) < 0) return -1; if (rt_gettree(rtip, obj2) < 0) return -1; rt_prep_parallel(rtip, 1); /* Now we've got the bounding box - set up the grids */ VMOVE(min, rtip->mdl_min); VMOVE(max, rtip->mdl_max); VSET(mid, (max[0] - min[0])/2, (max[1] - min[1])/2, (max[2] - min[2])/2); BU_GET(xdata, struct rt_pattern_data); VSET(xdata->center_pt, min[0] - 0.1 * min[0], mid[1], mid[2]); VSET(xdata->center_dir, 1, 0, 0); xdata->vn = 2; xdata->pn = 2; xdata->n_vec = (vect_t *)bu_calloc(xdata->vn + 1, sizeof(vect_t), "vects array"); xdata->n_p = (fastf_t *)bu_calloc(xdata->pn + 1, sizeof(fastf_t), "params array"); xdata->n_p[0] = 50; /* TODO - get tolerances from caller */ xdata->n_p[1] = 50; VSET(xdata->n_vec[0], 0, max[1], 0); VSET(xdata->n_vec[1], 0, 0, max[2]); ret = rt_pattern(xdata, RT_PATTERN_RECT_ORTHOGRID); bu_free(xdata->n_vec, "x vec inputs"); bu_free(xdata->n_p, "x p inputs"); if (ret < 0) return -1; BU_GET(ydata, struct rt_pattern_data); VSET(ydata->center_pt, mid[0], min[1] - 0.1 * min[1], mid[2]); VSET(ydata->center_dir, 0, 1, 0); ydata->vn = 2; ydata->pn = 2; ydata->n_vec = (vect_t *)bu_calloc(ydata->vn + 1, sizeof(vect_t), "vects array"); ydata->n_p = (fastf_t *)bu_calloc(ydata->pn + 1, sizeof(fastf_t), "params array"); ydata->n_p[0] = 50; /* TODO - get tolerances from caller */ ydata->n_p[1] = 50; VSET(ydata->n_vec[0], max[0], 0, 0); VSET(ydata->n_vec[1], 0, 0, max[2]); ret = rt_pattern(ydata, RT_PATTERN_RECT_ORTHOGRID); bu_free(ydata->n_vec, "y vec inputs"); bu_free(ydata->n_p, "y p inputs"); if (ret < 0) return -1; BU_GET(zdata, struct rt_pattern_data); VSET(zdata->center_pt, mid[0], mid[1], min[2] - 0.1 * min[2]); VSET(zdata->center_dir, 0, 0, 1); zdata->vn = 2; zdata->pn = 2; zdata->n_vec = (vect_t *)bu_calloc(zdata->vn + 1, sizeof(vect_t), "vects array"); zdata->n_p = (fastf_t *)bu_calloc(zdata->pn + 1, sizeof(fastf_t), "params array"); zdata->n_p[0] = 50; /* TODO - get tolerances from caller */ zdata->n_p[1] = 50; VSET(zdata->n_vec[0], max[0], 0, 0); VSET(zdata->n_vec[1], 0, max[1], 0); ret = rt_pattern(zdata, RT_PATTERN_RECT_ORTHOGRID); bu_free(zdata->n_vec, "x vec inputs"); bu_free(zdata->n_p, "x p inputs"); if (ret < 0) return -1; /* Consolidate the grids into a single ray array */ { size_t i, j; rays = (fastf_t *)bu_calloc((xdata->ray_cnt + ydata->ray_cnt + zdata->ray_cnt + 1) * 6, sizeof(fastf_t), "rays"); count = 0; for (i = 0; i < xdata->ray_cnt; i++) { for (j = 0; j < 6; j++) { rays[6*count+j] = xdata->rays[6*i + j]; } count++; } for (i = 0; i < ydata->ray_cnt; i++) { for (j = 0; j < 6; j++) { rays[6*count+j] = ydata->rays[6*i + j]; } count++; } for (i = 0; i < zdata->ray_cnt; i++) { for (j = 0; j < 6; j++) { rays[6*count+j] = zdata->rays[6*i+j]; } count++; } } bu_free(xdata->rays, "x rays"); bu_free(ydata->rays, "y rays"); bu_free(zdata->rays, "z rays"); BU_PUT(xdata, struct rt_pattern_data); BU_PUT(ydata, struct rt_pattern_data); BU_PUT(zdata, struct rt_pattern_data); bu_log("ray cnt: %d\n", count); { int i, j; ncpus = 2; state = (struct raydiff_container *)bu_calloc(ncpus+1, sizeof(struct raydiff_container), "resources"); for (i = 0; i < ncpus+1; i++) { state[i].rtip = rtip; state[i].tol = 0.5; state[i].ncpus = ncpus; state[i].left_name = bu_strdup(obj1); state[i].right_name = bu_strdup(obj2); BU_GET(state[i].resp, struct resource); rt_init_resource(state[i].resp, i, state->rtip); BU_GET(state[i].left, struct bu_ptbl); bu_ptbl_init(state[i].left, 64, "left solid hits"); BU_GET(state[i].both, struct bu_ptbl); bu_ptbl_init(state[i].both, 64, "hits on both solids"); BU_GET(state[i].right, struct bu_ptbl); bu_ptbl_init(state[i].right, 64, "right solid hits"); state[i].rays_cnt = count; state[i].rays = rays; } bu_parallel(raydiff_gen_worker, ncpus, (void *)state); /* Collect and print all of the results */ for (i = 0; i < ncpus+1; i++) { for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j); bu_log("Result: LEFT diff vol (%s): %g %g %g -> %g %g %g\n", obj1, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt)); } for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j); bu_log("Result: BOTH): %g %g %g -> %g %g %g\n", V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt)); } for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j); bu_log("Result: RIGHT diff vol (%s): %g %g %g -> %g %g %g\n", obj2, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt)); } } /* Free results */ for (i = 0; i < ncpus+1; i++) { for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j); BU_PUT(dseg, struct diff_seg); } bu_ptbl_free(state[i].left); BU_PUT(state[i].left, struct diff_seg); for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j); BU_PUT(dseg, struct diff_seg); } bu_ptbl_free(state[i].both); BU_PUT(state[i].both, struct diff_seg); for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j); BU_PUT(dseg, struct diff_seg); } bu_ptbl_free(state[i].right); BU_PUT(state[i].right, struct diff_seg); bu_free((void *)state[i].left_name, "left name"); bu_free((void *)state[i].right_name, "right name"); BU_PUT(state[i].resp, struct resource); } bu_free(state, "free state containers"); } return 0; }
HIDDEN int nmg_brep_face(ON_Brep **b, const struct faceuse *fu, const struct bn_tol *tol, long *brepi) { const struct face_g_plane *fg = fu->f_p->g.plane_p; struct bu_ptbl vert_table; struct vertex **pt; int ret = 0; int pnt_cnt = 0; int pnt_index = 0; vect_t u_axis, v_axis; point_t obr_center; point_t *points_3d = NULL; point_t *points_obr = NULL; struct loopuse *lu; struct edgeuse *eu; /* Find out how many points we have, set up any uninitialized ON_Brep vertex * structures, and prepare a map of NMG index values to the point array indices */ nmg_tabulate_face_g_verts(&vert_table, fg); for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { if (brepi[(*pt)->vg_p->index] == -INT_MAX) { ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF); brepi[(*pt)->vg_p->index] = vert.m_vertex_index; } pnt_cnt++; } /* Prepare the 3D obr input array */ points_3d = (point_t *)bu_calloc(pnt_cnt + 1, sizeof(point_t), "nmg points"); for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { VSET(points_3d[pnt_index], (*pt)->vg_p->coord[0],(*pt)->vg_p->coord[1],(*pt)->vg_p->coord[2]); pnt_index++; } bu_ptbl_free(&vert_table); /* Calculate the 3D coplanar oriented bounding rectangle (obr) */ ret += bg_3d_coplanar_obr(&obr_center, &u_axis, &v_axis, (const point_t *)points_3d, pnt_cnt); if (ret) { bu_log("Failed to get oriented bounding rectangle for NMG faceuse #%lu\n", fu->index); return -1; } bu_free(points_3d, "done with obr 3d point inputs"); /* Use the obr to define the 3D corner points of the NURBS surface */ points_obr = (point_t *)bu_calloc(3 + 1, sizeof(point_t), "points_3d"); VADD3(points_obr[2], obr_center, u_axis, v_axis); VSCALE(u_axis, u_axis, -1); VADD3(points_obr[3], obr_center, u_axis, v_axis); VSCALE(v_axis, v_axis, -1); VADD3(points_obr[0], obr_center, u_axis, v_axis); VSCALE(u_axis, u_axis, -1); VADD3(points_obr[1], obr_center, u_axis, v_axis); /* We need to orient our surface correctly according to the NMG - using * the openNURBS FlipFace function later does not seem to work very * well. If an outer loop is found in the NMG with a cw orientation, * factor that in in addition to the fu->f_p->flip flag. */ int ccw = 0; vect_t vtmp, uv1, uv2, vnormal; point_t center; VADD2(center, points_obr[0], points_obr[1]); VADD2(center, center, points_obr[2]); VADD2(center, center, points_obr[3]); VSCALE(center, center, 0.25); for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1; } if (ccw != -1) { VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]); } else { VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]); } if (fu->f_p->flip) VSET(vnormal, -vnormal[0], -vnormal[1], -vnormal[2]); VSUB2(uv1, points_obr[0], center); VSUB2(uv2, points_obr[1], center); VCROSS(vtmp, uv1, uv2); if (VDOT(vtmp, vnormal) < 0) { VMOVE(vtmp, points_obr[0]); VMOVE(points_obr[0], points_obr[1]); VMOVE(points_obr[1], vtmp); VMOVE(vtmp, points_obr[3]); VMOVE(points_obr[3], points_obr[2]); VMOVE(points_obr[2], vtmp); } /* Now that we've got our points correctly oriented for * the NURBS surface, proceed to create it. */ ON_3dPoint p1 = ON_3dPoint(points_obr[0]); ON_3dPoint p2 = ON_3dPoint(points_obr[1]); ON_3dPoint p3 = ON_3dPoint(points_obr[2]); ON_3dPoint p4 = ON_3dPoint(points_obr[3]); (*b)->m_S.Append(sideSurface(p1, p2, p3, p4)); ON_Surface *surf = (*(*b)->m_S.Last()); int surfindex = (*b)->m_S.Count(); ON_BrepFace& face = (*b)->NewFace(surfindex - 1); // With the surface and the face defined, make // trimming loops and create faces. To generate UV // coordinates for each from and to for the // edgecurves, the UV origin is defined to be v1, // v1->v2 is defined as the U domain, and v1->v4 is // defined as the V domain. VSUB2(u_axis, points_obr[2], points_obr[1]); VSUB2(v_axis, points_obr[0], points_obr[1]); fastf_t u_axis_dist = MAGNITUDE(u_axis); fastf_t v_axis_dist = MAGNITUDE(v_axis); /* Now that we have the surface and the face, add the loops */ for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex // Check if this is an inner or outer loop ON_BrepLoop::TYPE looptype = (lu->orientation == OT_SAME) ? ON_BrepLoop::outer : ON_BrepLoop::inner; ON_BrepLoop& loop = (*b)->NewLoop(looptype, face); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { vect_t ev1, ev2; struct vertex_g *vg1 = eu->vu_p->v_p->vg_p; struct vertex_g *vg2 = eu->eumate_p->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg1); NMG_CK_VERTEX_G(vg2); VMOVE(ev1, vg1->coord); VMOVE(ev2, vg2->coord); // Add edge if not already added if (brepi[eu->e_p->index] == -INT_MAX) { /* always add edges with the small vertex index as from */ int vert1 = (vg1->index <= vg2->index) ? brepi[vg1->index] : brepi[vg2->index]; int vert2 = (vg1->index > vg2->index) ? brepi[vg1->index] : brepi[vg2->index]; // Create and add 3D curve ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point()); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); // Create and add 3D edge ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1); e.m_tolerance = 0.0; brepi[eu->e_p->index] = e.m_edge_index; } // Regardless of whether the edge existed as an object, it needs to be added to the trimming loop ON_3dPoint vg1pt(vg1->coord); int orientation = ((vg1pt != (*b)->m_V[(*b)->m_E[(int)brepi[eu->e_p->index]].m_vi[0]].Point())) ? 1 : 0; // Make a 2d trimming curve, create a trim, and add the trim to the loop vect_t vect1, vect2, u_component, v_component; double u0, u1, v0, v1; ON_2dPoint from_uv, to_uv; VSUB2(vect1, ev1, points_obr[0]); VSUB2(vect2, ev2, points_obr[0]); surf->GetDomain(0, &u0, &u1); surf->GetDomain(1, &v0, &v1); VPROJECT(vect1, u_axis, u_component, v_component); from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); VPROJECT(vect2, u_axis, u_component, v_component); to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); ON_Curve* c2d = new ON_LineCurve(from_uv, to_uv); c2d->SetDomain(0.0, 1.0); int c2i = (*b)->m_C2.Count(); (*b)->m_C2.Append(c2d); ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[(int)brepi[eu->e_p->index]], orientation, loop, c2i); trim.m_type = ON_BrepTrim::mated; trim.m_tolerance[0] = 0.0; trim.m_tolerance[1] = 0.0; } } bu_free(points_obr, "Done with obr"); return 0; }
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"); }
extern "C" void rt_nmg_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol) { struct model *m; struct nmgregion *r; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; int edge_index; long* brepi; RT_CK_DB_INTERNAL(ip); m = (struct model *)ip->idb_ptr; NMG_CK_MODEL(m); brepi = static_cast<long*>(bu_malloc(m->maxindex * sizeof(long), "rt_nmg_brep: brepi[]")); for (int i = 0; i < m->maxindex; i++) brepi[i] = -INT_MAX; for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) { for (BU_LIST_FOR(s, shell, &r->s_hd)) { for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; // Need to create ON_NurbsSurface based on plane of // face in order to have UV space in which to define // trimming loops. Bounding points are NOT on the // face plane, so another approach must be used. // // General approach: For all loops in the faceuse, // collect all the vertices. Find the center point of // all the vertices, and search for the point with the // greatest distance from that center point. Once // found, cross the vector between the center point // and furthest point with the normal of the face and // scale the resulting vector to have the same length // as the vector to the furthest point. Add the two // resulting vectors to find the first corner point. // Mirror the first corner point across the center to // find the second corner point. Cross the two // vectors created by the first two corner points with // the face normal to get the vectors of the other two // corners, and scale the resulting vectors to the // same magnitude as the first two. These four points // bound all vertices on the plane and form a suitable // staring point for a UV space, since all points on // all the edges are equal to or further than the // distance between the furthest vertex and the center // point. // ............. ............. // . .* . . // . . . . . // . . . . . // . . . * . // . . . . . // . . . . . // . . . . . // . * * . . // . . . . // . . . . // . . . . // . *. . . // . ... ...* . // . .... .... . // . * . // ........................... // const struct face_g_plane *fg = fu->f_p->g.plane_p; struct bu_ptbl vert_table; nmg_tabulate_face_g_verts(&vert_table, fg); point_t tmppt, center, max_pt; struct vertex **pt; VSET(tmppt, 0, 0, 0); VSET(max_pt, 0, 0, 0); int ptcnt = 0; for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { tmppt[0] += (*pt)->vg_p->coord[0]; tmppt[1] += (*pt)->vg_p->coord[1]; tmppt[2] += (*pt)->vg_p->coord[2]; ptcnt++; if (brepi[(*pt)->vg_p->index] == -INT_MAX) { ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF); brepi[(*pt)->vg_p->index] = vert.m_vertex_index; } } VSET(center, tmppt[0]/ptcnt, tmppt[1]/ptcnt, tmppt[2]/ptcnt); fastf_t max_dist = 0.0; fastf_t curr_dist; for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { tmppt[0] = (*pt)->vg_p->coord[0]; tmppt[1] = (*pt)->vg_p->coord[1]; tmppt[2] = (*pt)->vg_p->coord[2]; curr_dist = DIST_PT_PT(center, tmppt); if (curr_dist > max_dist) { max_dist = curr_dist; VMOVE(max_pt, tmppt); } } bu_ptbl_free(&vert_table); int ccw = 0; vect_t vtmp, uv1, uv2, uv3, uv4, vnormal; // If an outer loop is found in the nmg with a cw // orientation, use a flipped normal to form the NURBS // surface for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1; } if (ccw != -1) { VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]); } else { VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]); } VSUB2(uv1, max_pt, center); VCROSS(vtmp, uv1, vnormal); VADD2(uv1, uv1, vtmp); VCROSS(uv2, uv1, vnormal); VREVERSE(uv3, uv1); VCROSS(uv4, uv3, vnormal); VADD2(uv1, uv1, center); VADD2(uv2, uv2, center); VADD2(uv3, uv3, center); VADD2(uv4, uv4, center); ON_3dPoint p1 = ON_3dPoint(uv1); ON_3dPoint p2 = ON_3dPoint(uv2); ON_3dPoint p3 = ON_3dPoint(uv3); ON_3dPoint p4 = ON_3dPoint(uv4); (*b)->m_S.Append(sideSurface(p1, p4, p3, p2)); ON_Surface *surf = (*(*b)->m_S.Last()); int surfindex = (*b)->m_S.Count(); // Now that we have the surface, define the face ON_BrepFace& face = (*b)->NewFace(surfindex - 1); // With the surface and the face defined, make // trimming loops and create faces. To generate UV // coordinates for each from and to for the // edgecurves, the UV origin is defined to be v1, // v1->v2 is defined as the U domain, and v1->v4 is // defined as the V domain. vect_t u_axis, v_axis; VSUB2(u_axis, uv2, uv1); VSUB2(v_axis, uv4, uv1); fastf_t u_axis_dist = MAGNITUDE(u_axis); fastf_t v_axis_dist = MAGNITUDE(v_axis); // Now that the surface context is set up, add the loops. for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { int edges=0; if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex ON_BrepLoop::TYPE looptype; // Check if this is an inner or outer loop if (lu->orientation == OT_SAME) { looptype = ON_BrepLoop::outer; } else { looptype = ON_BrepLoop::inner; } ON_BrepLoop& loop = (*b)->NewLoop(looptype, face); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { ++edges; vect_t ev1, ev2; struct vertex_g *vg1, *vg2; vg1 = eu->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg1); int vert1 = brepi[vg1->index]; VMOVE(ev1, vg1->coord); vg2 = eu->eumate_p->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg2); int vert2 = brepi[vg2->index]; VMOVE(ev2, vg2->coord); // Add edge if not already added if (brepi[eu->e_p->index] == -INT_MAX) { /* always add edges with the small vertex index as from */ if (vg1->index > vg2->index) { int tmpvert = vert1; vert1 = vert2; vert2 = tmpvert; } // Create and add 3D curve ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point()); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); // Create and add 3D edge ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1); e.m_tolerance = 0.0; brepi[eu->e_p->index] = e.m_edge_index; } // Regardless of whether the edge existed as // an object, it needs to be added to the // trimming loop vect_t u_component, v_component; ON_3dPoint vg1pt(vg1->coord); int orientation = 0; edge_index = brepi[eu->e_p->index]; if (vg1pt != (*b)->m_V[(*b)->m_E[edge_index].m_vi[0]].Point()) { orientation = 1; } // Now, make 2d trimming curves vect_t vect1, vect2; VSUB2(vect1, ev1, uv1); VSUB2(vect2, ev2, uv1); ON_2dPoint from_uv, to_uv; double u0, u1, v0, v1; surf->GetDomain(0, &u0, &u1); surf->GetDomain(1, &v0, &v1); VPROJECT(vect1, u_axis, u_component, v_component); from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); VPROJECT(vect2, u_axis, u_component, v_component); to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); ON_3dPoint S1, S2; ON_3dVector Su, Sv; surf->Ev1Der(from_uv.x, from_uv.y, S1, Su, Sv); surf->Ev1Der(to_uv.x, to_uv.y, S2, Su, Sv); ON_Curve* c2d = new ON_LineCurve(from_uv, to_uv); c2d->SetDomain(0.0, 1.0); int c2i = (*b)->m_C2.Count(); (*b)->m_C2.Append(c2d); edge_index = brepi[eu->e_p->index]; ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[edge_index], orientation, loop, c2i); trim.m_type = ON_BrepTrim::mated; trim.m_tolerance[0] = 0.0; trim.m_tolerance[1] = 0.0; } } } (*b)->SetTrimIsoFlags(); } } bu_free(brepi, "rt_nmg_brep: brepi[]"); }
HIDDEN int move_all_func(struct ged *gedp, int nflag, const char *old_name, const char *new_name) { int i; struct ged_display_list *gdlp; struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; struct bu_ptbl stack; /* rename the record itself */ if ((dp = db_lookup(gedp->ged_wdbp->dbip, old_name, LOOKUP_NOISY)) == RT_DIR_NULL) return GED_ERROR; if (db_lookup(gedp->ged_wdbp->dbip, new_name, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "%s: already exists", new_name); return GED_ERROR; } /* if this was a sketch, we need to look for all the extrude * objects that might use it. * * This has to be done here, before we rename the (possible) sketch object * because the extrude will do a rt_db_get on the sketch when we call * rt_db_get_internal on it. */ if (dp->d_major_type == DB5_MAJORTYPE_BRLCAD && \ dp->d_minor_type == DB5_MINORTYPE_BRLCAD_SKETCH) { struct directory *dirp; for (i = 0; i < RT_DBNHASH; i++) { for (dirp = gedp->ged_wdbp->dbip->dbi_Head[i]; dirp != RT_DIR_NULL; dirp = dirp->d_forw) { if (dirp->d_major_type == DB5_MAJORTYPE_BRLCAD && \ dirp->d_minor_type == DB5_MINORTYPE_BRLCAD_EXTRUDE) { struct rt_extrude_internal *extrude; if (rt_db_get_internal(&intern, dirp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { bu_log("Can't get extrude %s?\n", dirp->d_namep); continue; } extrude = (struct rt_extrude_internal *)intern.idb_ptr; RT_EXTRUDE_CK_MAGIC(extrude); if (BU_STR_EQUAL(extrude->sketch_name, old_name)) { if (nflag) { bu_vls_printf(gedp->ged_result_str, "%s ", dirp->d_namep); rt_db_free_internal(&intern); } else { bu_free(extrude->sketch_name, "sketch name"); extrude->sketch_name = bu_strdup(new_name); if (rt_db_put_internal(dirp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) { bu_log("oops\n"); } } } else rt_db_free_internal(&intern); } } } } if (!nflag) { /* Change object name in the directory. */ if (db_rename(gedp->ged_wdbp->dbip, dp, new_name) < 0) { bu_vls_printf(gedp->ged_result_str, "error in rename to %s, aborting", new_name); return GED_ERROR; } /* Change name in the file */ if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Database read error, aborting"); return GED_ERROR; } if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Database write error, aborting"); return GED_ERROR; } } bu_ptbl_init(&stack, 64, "combination stack for wdb_mvall_cmd"); /* Examine all COMB nodes */ for (i = 0; i < RT_DBNHASH; i++) { for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) { if (nflag) { union tree *comb_leaf; int done=0; if (!(dp->d_flags & RT_DIR_COMB)) continue; if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) continue; comb = (struct rt_comb_internal *)intern.idb_ptr; bu_ptbl_reset(&stack); /* visit each leaf in the combination */ comb_leaf = comb->tree; if (comb_leaf) { while (!done) { while (comb_leaf->tr_op != OP_DB_LEAF) { bu_ptbl_ins(&stack, (long *)comb_leaf); comb_leaf = comb_leaf->tr_b.tb_left; } if (BU_STR_EQUAL(comb_leaf->tr_l.tl_name, old_name)) { bu_vls_printf(gedp->ged_result_str, "%s ", dp->d_namep); } if (BU_PTBL_END(&stack) < 1) { done = 1; break; } comb_leaf = (union tree *)BU_PTBL_GET(&stack, BU_PTBL_END(&stack)-1); if (comb_leaf->tr_op != OP_DB_LEAF) { bu_ptbl_rm(&stack, (long *)comb_leaf); comb_leaf = comb_leaf->tr_b.tb_right; } } } rt_db_free_internal(&intern); } else { int comb_mvall_status = db_comb_mvall(dp, gedp->ged_wdbp->dbip, old_name, new_name, &stack); if (!comb_mvall_status) continue; if (comb_mvall_status == 2) { bu_ptbl_free(&stack); bu_vls_printf(gedp->ged_result_str, "Database write error, aborting"); return GED_ERROR; } } } } bu_ptbl_free(&stack); if (!nflag) { /* Change object name anywhere in the display list path. */ for (BU_LIST_FOR(gdlp, ged_display_list, gedp->ged_gdp->gd_headDisplay)) { int first = 1; int found = 0; struct bu_vls new_path = BU_VLS_INIT_ZERO; char *dupstr = strdup(bu_vls_addr(&gdlp->gdl_path)); char *tok = strtok(dupstr, "/"); while (tok) { if (BU_STR_EQUAL(tok, old_name)) { found = 1; if (first) { first = 0; bu_vls_printf(&new_path, "%s", new_name); } else bu_vls_printf(&new_path, "/%s", new_name); } else { if (first) { first = 0; bu_vls_printf(&new_path, "%s", tok); } else bu_vls_printf(&new_path, "/%s", tok); } tok = strtok((char *)NULL, "/"); } if (found) { bu_vls_free(&gdlp->gdl_path); bu_vls_printf(&gdlp->gdl_path, "%s", bu_vls_addr(&new_path)); } free((void *)dupstr); bu_vls_free(&new_path); } } return GED_OK; }
static size_t show_dangling_edges(struct ged *gedp, const uint32_t *magic_p, const char *name, int out_type) { FILE *plotfp = NULL; const char *manifolds = NULL; const struct edgeuse *eur; int done; point_t pt1, pt2; size_t i, cnt; struct bn_vlblock *vbp = NULL; struct bu_list *vhead = NULL; struct bu_ptbl faces; struct bu_vls plot_file_name = BU_VLS_INIT_ZERO; struct edgeuse *eu = NULL; struct face *fp = NULL; struct faceuse *fu, *fu1, *fu2; struct faceuse *newfu = NULL; struct loopuse *lu = NULL; /* out_type: 0 = none, 1 = show, 2 = plot */ if (out_type < 0 || out_type > 2) { bu_log("Internal error, open edge test failed.\n"); return 0; } if (out_type == 1) { vbp = rt_vlblock_init(); vhead = rt_vlblock_find(vbp, 0xFF, 0xFF, 0x00); } bu_ptbl_init(&faces, 64, "faces buffer"); nmg_face_tabulate(&faces, magic_p); cnt = 0; for (i = 0; i < (size_t)BU_PTBL_END(&faces) ; i++) { fp = (struct face *)BU_PTBL_GET(&faces, i); NMG_CK_FACE(fp); fu = fu1 = fp->fu_p; NMG_CK_FACEUSE(fu1); fu2 = fp->fu_p->fumate_p; NMG_CK_FACEUSE(fu2); done = 0; while (!done) { NMG_CK_FACEUSE(fu); for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); eur = nmg_radial_face_edge_in_shell(eu); newfu = eur->up.lu_p->up.fu_p; while (manifolds && NMG_MANIFOLDS(manifolds, newfu) & NMG_2MANIFOLD && eur != eu->eumate_p) { eur = nmg_radial_face_edge_in_shell(eur->eumate_p); newfu = eur->up.lu_p->up.fu_p; } if (eur == eu->eumate_p) { VMOVE(pt1, eu->vu_p->v_p->vg_p->coord); VMOVE(pt2, eu->eumate_p->vu_p->v_p->vg_p->coord); if (out_type == 1) { BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt1, BN_VLIST_LINE_MOVE); BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt2, BN_VLIST_LINE_DRAW); } else if (out_type == 2) { if (!plotfp) { bu_vls_sprintf(&plot_file_name, "%s.%p.pl", name, (void *)magic_p); if ((plotfp = fopen(bu_vls_addr(&plot_file_name), "wb")) == (FILE *)NULL) { bu_vls_free(&plot_file_name); bu_log("Error, unable to create plot file (%s), open edge test failed.\n", bu_vls_addr(&plot_file_name)); return 0; } } pdv_3line(plotfp, pt1, pt2); } cnt++; } } } } if (fu == fu1) fu = fu2; if (fu == fu2) done = 1; }; } if (out_type == 1) { /* Add overlay */ _ged_cvt_vlblock_to_solids(gedp, vbp, (char *)name, 0); rt_vlblock_free(vbp); bu_log("Showing open edges...\n"); } else if (out_type == 2) { if (plotfp) { (void)fclose(plotfp); bu_log("Wrote plot file (%s)\n", bu_vls_addr(&plot_file_name)); bu_vls_free(&plot_file_name); } } bu_ptbl_free(&faces); return cnt; }