int nmg_eu_is_part_of_crack(const struct edgeuse *eu) { struct loopuse *lu; struct edgeuse *eu_test; NMG_CK_EDGEUSE(eu); /* must be part of a loop to be a crack */ if (*eu->up.magic_p != NMG_LOOPUSE_MAGIC) return 0; lu = eu->up.lu_p; NMG_CK_LOOPUSE(lu); for (BU_LIST_FOR(eu_test, edgeuse, &lu->down_hd)) { if (eu_test == eu) continue; if (eu_test->vu_p->v_p == eu->eumate_p->vu_p->v_p && eu_test->eumate_p->vu_p->v_p == eu->vu_p->v_p) return 1; } return 0; }
/** * Make sure that the lu and fu orientation flags are consistent with * the geometric arrangement of the vertices and the faceuse normal. */ void nmg_ck_lu_orientation(struct loopuse *lu, const struct bn_tol *tolp) { struct faceuse *fu; plane_t fu_peqn; plane_t lu_peqn; fastf_t dot; NMG_CK_LOOPUSE(lu); fu = lu->up.fu_p; /* parent had better be faceuse */ NMG_CK_FACEUSE(fu); NMG_GET_FU_PLANE(fu_peqn, fu); nmg_loop_plane_newell(lu, lu_peqn); dot = VDOT(fu_peqn, lu_peqn); if (NEAR_ZERO(dot, tolp->perp)) return; /* can't determine geometric orientation */ if (dot < 0.0) { bu_log("nmg_ck_lu_orientation() lu=%p, dot=%g, fu_orient=%s, lu_orient=%s\n", (void *)lu, dot, nmg_orientation(fu->orientation), nmg_orientation(lu->orientation) ); bu_bomb("nmg_ck_lu_orientation() loop orientation flags do not match geometry\n"); } }
static void Write_euclid_face(const struct loopuse *lu, const int facet_type, const int regionid, const int face_number) { struct faceuse *fu; struct edgeuse *eu; plane_t plane; int vertex_count = 0; NMG_CK_LOOPUSE(lu); if (verbose) bu_log("Write_euclid_face: lu=%p, facet_type=%d, regionid=%d, face_number=%d\n", (void *)lu, facet_type, regionid, face_number); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) return; if (*lu->up.magic_p != NMG_FACEUSE_MAGIC) return; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) vertex_count++; fprintf(fp_out, "%10d%3d 0. 1%5d", regionid, facet_type, vertex_count); vertex_count = 0; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { struct vertex *v; int i; NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); /* fprintf(fp_out, "%10d%8f%8f%8f", ++vertex_count, V3ARGS(v->vg_p->coord)); */ vertex_count++; fprintf(fp_out, "%10d", vertex_count); for (i=X; i<=Z; i++) fastf_print(fp_out, 8, v->vg_p->coord[i]); } fu = lu->up.fu_p; NMG_CK_FACEUSE(fu); NMG_GET_FU_PLANE(plane, fu); fprintf(fp_out, "%10d%15.5f%15.5f%15.5f%15.5f", face_number, V4ARGS(plane)); }
/** * Intersect all the edges in fu1 that don't lie on any of the faces * of shell s2 with s2, i.e. "interior" edges, where the endpoints lie * on s2, but the edge is not shared with a face of s2. Such edges * wouldn't have been processed by the NEWLINE version of * nmg_isect_two_generic_faces(), so intersections need to be looked * for here. Fortunately, it's easy to reject everything except edges * that need processing using only the topology structures. * * The "_int" at the end of the name is to signify that this routine * does only "interior" edges, and is not a general face/shell * intersector. */ void nmg_isect_face3p_shell_int(struct nmg_inter_struct *is, struct faceuse *fu1, struct shell *s2) { struct shell *s1; struct loopuse *lu1; struct edgeuse *eu1; NMG_CK_INTER_STRUCT(is); NMG_CK_FACEUSE(fu1); NMG_CK_SHELL(s2); s1 = fu1->s_p; NMG_CK_SHELL(s1); if (RTG.NMG_debug & DEBUG_POLYSECT) bu_log("nmg_isect_face3p_shell_int(, fu1=x%x, s2=x%x) START\n", fu1, s2); for (BU_LIST_FOR (lu1, loopuse, &fu1->lu_hd)) { NMG_CK_LOOPUSE(lu1); if (BU_LIST_FIRST_MAGIC(&lu1->down_hd) == NMG_VERTEXUSE_MAGIC) continue; for (BU_LIST_FOR (eu1, edgeuse, &lu1->down_hd)) { struct edgeuse *eu2; eu2 = nmg_find_matching_eu_in_s(eu1, s2); if (eu2) { bu_log("nmg_isect_face3p_shell_int() eu1=x%x, e1=x%x, eu2=x%x, e2=x%x (nothing to do)\n", eu1, eu1->e_p, eu2, eu2->e_p); /* Whether the edgeuse is in a face, or a wire * edgeuse, the other guys will isect it. */ continue; } /* vu2a and vu2b are in shell s2, but there is no edge * running between them in shell s2. Create a line of * intersection, and go to it!. */ bu_log("nmg_isect_face3p_shell_int(, s2=x%x) eu1=x%x, no eu2\n", s2, eu1); /* XXX eso no existe todavia */ /* nmg_isect_edge3p_shell(is, eu1, s2); */ } } if (RTG.NMG_debug & DEBUG_POLYSECT) bu_log("nmg_isect_face3p_shell_int(, fu1=x%x, s2=x%x) END\n", fu1, s2); }
/** * Count number of vertices in an NMG loop. */ static int verts_in_nmg_loop(struct loopuse *lu) { int cnt; struct edgeuse *eu; struct vertex *v; /* Count number of vertices in loop. */ cnt = 0; 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); NMG_CK_EDGE(eu->e_p); NMG_CK_VERTEXUSE(eu->vu_p); NMG_CK_VERTEX(eu->vu_p->v_p); cnt++; } } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
void nmg_visit_loopuse(struct loopuse *lu, const struct nmg_visit_handlers *htab, void *state) /* Handler's private state */ { NMG_CK_LOOPUSE(lu); if (htab->bef_loopuse) htab->bef_loopuse((uint32_t *)lu, state, 0); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { struct vertexuse *vu; vu = BU_LIST_FIRST(vertexuse, &lu->down_hd); nmg_visit_vertexuse(vu, htab, state); } else { struct edgeuse *eu; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { nmg_visit_edgeuse(eu, htab, state); } } nmg_visit_loop(lu->l_p, htab, state); if (htab->aft_loopuse) htab->aft_loopuse((uint32_t *)lu, state, 1); }
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"); }
/* * J A C K _ F A C E S * * Continues the conversion of an nmg into Jack format. Before * this routine is called, a list of unique vertices has been * stored in a heap. Using this heap and the nmg structure, a * list of face vertices is written to the Jack data base file. */ static void jack_faces(struct nmgregion *r, FILE *fp_psurf, int *map) /* NMG region to be converted. */ /* Jack format file to write face vertices to. */ { struct edgeuse *eu; struct faceuse *fu; struct loopuse *lu; struct shell *s; struct vertex *v; for (BU_LIST_FOR(s, shell, &r->s_hd)) { /* Shell is made of faces. */ for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; 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); NMG_CK_EDGE(eu->e_p); NMG_CK_VERTEXUSE(eu->vu_p); NMG_CK_VERTEX(eu->vu_p->v_p); NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, eu->vu_p->v_p)); } } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { v = BU_LIST_PNEXT(vertexuse, &lu->down_hd)->v_p; NMG_CK_VERTEX(v); NMG_CK_VERTEX_G(v->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, v)); } else bu_log("jack_faces: loopuse mess up! (1)\n"); fprintf(fp_psurf, ";\n"); } } /* Shell contains loops. */ for (BU_LIST_FOR(lu, loopuse, &s->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); NMG_CK_EDGE(eu->e_p); NMG_CK_VERTEXUSE(eu->vu_p); NMG_CK_VERTEX(eu->vu_p->v_p); NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, eu->vu_p->v_p)); } } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { v = BU_LIST_PNEXT(vertexuse, &lu->down_hd)->v_p; NMG_CK_VERTEX(v); NMG_CK_VERTEX_G(v->vg_p); fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, v)); } else bu_log("jack_faces: loopuse mess up! (1)\n"); fprintf(fp_psurf, ";\n"); }
void nmg_2_vrml(struct db_tree_state *tsp, const struct db_full_path *pathp, struct model *m) { struct mater_info *mater = &tsp->ts_mater; const struct bn_tol *tol2 = tsp->ts_tol; struct nmgregion *reg; struct bu_ptbl verts; struct vrml_mat mat; struct bu_vls vls = BU_VLS_INIT_ZERO; char *tok; int i; int first = 1; int is_light = 0; point_t ave_pt = VINIT_ZERO; struct bu_vls shape_name = BU_VLS_INIT_ZERO; char *full_path; /* There may be a better way to capture the region_id, than * getting the rt_comb_internal structure, (and may be a better * way to capture the rt_comb_internal struct), but for now I just * copied the method used in select_lights/select_non_lights above, * could have used a global variable but I noticed none other were * used, so I didn't want to be the first */ struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; /* static due to libbu exception handling */ static float r, g, b; NMG_CK_MODEL(m); full_path = db_path_to_string(pathp); RT_CK_FULL_PATH(pathp); dp = DB_FULL_PATH_CUR_DIR(pathp); if (!(dp->d_flags & RT_DIR_COMB)) { return; } id = rt_db_get_internal(&intern, dp, dbip, (matp_t)NULL, &rt_uniresource); if (id < 0) { bu_log("Cannot internal form of %s\n", dp->d_namep); return; } if (id != ID_COMBINATION) { bu_log("Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (mater->ma_color_valid) { r = mater->ma_color[0]; g = mater->ma_color[1]; b = mater->ma_color[2]; } else { r = g = b = 0.5; } if (mater->ma_shader) { tok = strtok(mater->ma_shader, tok_sep); bu_strlcpy(mat.shader, tok, TXT_NAME_SIZE); } else { mat.shader[0] = '\0'; } mat.shininess = -1; mat.transparency = -1.0; mat.lt_fraction = -1.0; VSETALL(mat.lt_dir, 0.0); mat.lt_angle = -1.0; mat.tx_file[0] = '\0'; mat.tx_w = -1; mat.tx_n = -1; bu_vls_strcpy(&vls, &mater->ma_shader[strlen(mat.shader)]); (void)bu_struct_parse(&vls, vrml_mat_parse, (char *)&mat, NULL); if (bu_strncmp("light", mat.shader, 5) == 0) { /* this is a light source */ is_light = 1; } else { path_2_vrml_id(&shape_name, full_path); fprintf(fp_out, "\t\tDEF %s Shape {\n", bu_vls_addr(&shape_name)); fprintf(fp_out, "\t\t\t# Component_ID: %ld %s\n", comb->region_id, full_path); fprintf(fp_out, "\t\t\tappearance Appearance {\n"); if (bu_strncmp("plastic", mat.shader, 7) == 0) { if (mat.shininess < 0) { mat.shininess = 10; } if (mat.transparency < SMALL_FASTF) { mat.transparency = 0.0; } fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b); fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0)); if (mat.transparency > SMALL_FASTF) { fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency); } fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0); } else if (bu_strncmp("glass", mat.shader, 5) == 0) { if (mat.shininess < 0) { mat.shininess = 4; } if (mat.transparency < SMALL_FASTF) { mat.transparency = 0.8; } fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b); fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0)); if (mat.transparency > SMALL_FASTF) { fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency); } fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0); } else if (bu_strncmp("texture", mat.shader, 7) == 0) { if (mat.tx_w < 0) { mat.tx_w = 512; } if (mat.tx_n < 0) { mat.tx_n = 512; } if (strlen(mat.tx_file)) { int tex_fd; unsigned char tex_buf[TXT_BUF_LEN * 3]; if ((tex_fd = open(mat.tx_file, O_RDONLY | O_BINARY)) == (-1)) { bu_log("Cannot open texture file (%s)\n", mat.tx_file); perror("g-vrml: "); } else { long tex_len; long bytes_read = 0; long bytes_to_go = 0; /* Johns note - need to check (test) the texture stuff */ fprintf(fp_out, "\t\t\t\ttextureTransform TextureTransform {\n"); fprintf(fp_out, "\t\t\t\t\tscale 1.33333 1.33333\n\t\t\t\t}\n"); fprintf(fp_out, "\t\t\t\ttexture PixelTexture {\n"); fprintf(fp_out, "\t\t\t\t\trepeatS TRUE\n"); fprintf(fp_out, "\t\t\t\t\trepeatT TRUE\n"); fprintf(fp_out, "\t\t\t\t\timage %d %d %d\n", mat.tx_w, mat.tx_n, 3); tex_len = mat.tx_w*mat.tx_n * 3; while (bytes_read < tex_len) { int nbytes; long readval; bytes_to_go = tex_len - bytes_read; CLAMP(bytes_to_go, 0, TXT_BUF_LEN * 3); nbytes = 0; while (nbytes < bytes_to_go) { readval = read(tex_fd, &tex_buf[nbytes], bytes_to_go-nbytes); if (readval < 0) { perror("READ ERROR"); break; } else { nbytes += readval; } } bytes_read += nbytes; for (i = 0; i < nbytes; i += 3) { fprintf(fp_out, "\t\t\t0x%02x%02x%02x\n", tex_buf[i], tex_buf[i+1], tex_buf[i+2]); } } fprintf(fp_out, "\t\t\t\t}\n"); close(tex_fd); } } } else if (mater->ma_color_valid) { /* no shader specified, but a color is assigned */ fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g }\n", r, g, b); } else { /* If no color was defined set the colors according to the thousands groups */ int thou = comb->region_id / 1000; thou == 0 ? fprintf(fp_out, "\t\t\tmaterial USE Material_999\n") : thou == 1 ? fprintf(fp_out, "\t\t\tmaterial USE Material_1999\n") : thou == 2 ? fprintf(fp_out, "\t\t\tmaterial USE Material_2999\n") : thou == 3 ? fprintf(fp_out, "\t\t\tmaterial USE Material_3999\n") : thou == 4 ? fprintf(fp_out, "\t\t\tmaterial USE Material_4999\n") : thou == 5 ? fprintf(fp_out, "\t\t\tmaterial USE Material_5999\n") : thou == 6 ? fprintf(fp_out, "\t\t\tmaterial USE Material_6999\n") : thou == 7 ? fprintf(fp_out, "\t\t\tmaterial USE Material_7999\n") : thou == 8 ? fprintf(fp_out, "\t\t\tmaterial USE Material_8999\n") : fprintf(fp_out, "\t\t\tmaterial USE Material_9999\n"); } } if (!is_light) { nmg_triangulate_model(m, tol2); fprintf(fp_out, "\t\t\t}\n"); fprintf(fp_out, "\t\t\tgeometry IndexedFaceSet {\n"); fprintf(fp_out, "\t\t\t\tcoord Coordinate {\n"); } /* get list of vertices */ nmg_vertex_tabulate(&verts, &m->magic); if (!is_light) { fprintf(fp_out, "\t\t\t\t\tpoint ["); } else { VSETALL(ave_pt, 0.0); } for (i = 0; i < BU_PTBL_END(&verts); i++) { struct vertex *v; struct vertex_g *vg; point_t pt_meters; v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); vg = v->vg_p; NMG_CK_VERTEX_G(vg); /* convert to desired units */ VSCALE(pt_meters, vg->coord, scale_factor); if (is_light) { VADD2(ave_pt, ave_pt, pt_meters); } if (first) { if (!is_light) { fprintf(fp_out, " %10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i); } first = 0; } else if (!is_light) { fprintf(fp_out, "\t\t\t\t\t%10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i); } } if (!is_light) { fprintf(fp_out, "\t\t\t\t\t]\n\t\t\t\t}\n"); } else { fastf_t one_over_count; one_over_count = 1.0/(fastf_t)BU_PTBL_END(&verts); VSCALE(ave_pt, ave_pt, one_over_count); } first = 1; if (!is_light) { fprintf(fp_out, "\t\t\t\tcoordIndex [\n"); for (BU_LIST_FOR(reg, nmgregion, &m->r_hd)) { struct shell *s; NMG_CK_REGION(reg); for (BU_LIST_FOR(s, shell, ®->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; } if (!first) { fprintf(fp_out, ",\n"); } else { first = 0; } fprintf(fp_out, "\t\t\t\t\t"); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { struct vertex *v; NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(fp_out, " %d,", bu_ptbl_locate(&verts, (long *)v)); } fprintf(fp_out, "-1"); } } } } fprintf(fp_out, "\n\t\t\t\t]\n\t\t\t\tnormalPerVertex FALSE\n"); fprintf(fp_out, "\t\t\t\tconvex FALSE\n"); fprintf(fp_out, "\t\t\t\tcreaseAngle 0.5\n"); fprintf(fp_out, "\t\t\t}\n\t\t}\n"); } else {
/* IEEE patch number of the Bi-Cubic Bezier patch and convert it * to a B-Spline surface (Bezier surfaces are a subset of B-spline surfaces * and output it to a BRL-CAD binary format. */ void dump_patch(int (*patch)[4]) { struct vertex *verts[4]; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; int i, j, pt_type; fastf_t *mesh=NULL; fastf_t *ukv=NULL; fastf_t *vkv=NULL; /* U and V parametric Direction Spline parameters * Cubic = order 4, * knot size is Control point + order = 8 * control point size is 4 * point size is 3 */ for ( i=0; i<4; i++ ) verts[i] = (struct vertex *)NULL; fu = nmg_cface( s, verts, 4 ); NMG_CK_FACEUSE( fu ); for ( i=0; i<4; i++ ) { struct vertexuse *vu; vect_t uvw; point_t pnt; int k, j; switch ( i ) { default: case 0: VSET( uvw, 0.0, 0.0, 0.0 ); k = 0; j = 0; break; case 1: VSET( uvw, 1.0, 0.0, 0.0 ); k = 0; j = 3; break; case 2: VSET( uvw, 1.0, 1.0, 0.0 ); k = 3; j = 3; break; case 3: VSET( uvw, 0.0, 1.0, 0.0 ); k = 3; j = 0; break; } VSET( pnt , ducks[patch[k][j]-1].x * 1000 , ducks[patch[k][j]-1].y * 1000 , ducks[patch[k][j]-1].z * 1000 ); nmg_vertex_gv( verts[i], pnt ); for ( BU_LIST_FOR( vu, vertexuse, &verts[i]->vu_hd ) ) nmg_vertexuse_a_cnurb( vu, uvw ); } pt_type = RT_NURB_MAKE_PT_TYPE(3, RT_NURB_PT_XYZ, 0); /* see nurb.h for details */ nmg_face_g_snurb( fu, 4, 4, 8, 8, ukv, vkv, 4, 4, pt_type, mesh ); NMG_CK_FACE( fu->f_p ); NMG_CK_FACE_G_SNURB( fu->f_p->g.snurb_p ); mesh = fu->f_p->g.snurb_p->ctl_points; /* Copy the control points */ for ( i = 0; i< 4; i++) for ( j = 0; j < 4; j++) { *mesh = ducks[patch[i][j]-1].x * 1000; *(mesh+1) = ducks[patch[i][j]-1].y * 1000; *(mesh+2) = ducks[patch[i][j]-1].z * 1000; mesh += 3; } /* Both u and v knot vectors are [ 0 0 0 0 1 1 1 1] */ ukv = fu->f_p->g.snurb_p->u.knots; vkv = fu->f_p->g.snurb_p->v.knots; /* set the knot vectors */ for ( i=0; i<4; i++ ) { *(ukv+i) = 0.0; *(vkv+i) = 0.0; } for ( i=0; i<4; i++ ) { *(ukv+4+i) = 1.0; *(vkv+4+i) = 1.0; } /* set eu geometry */ pt_type = RT_NURB_MAKE_PT_TYPE(2, RT_NURB_PT_UV, 0); /* see nurb.h for details */ lu = BU_LIST_FIRST( loopuse, &fu->lu_hd ); NMG_CK_LOOPUSE( lu ); for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { #if 0 nmg_edge_g_cnurb( eu, 2, 0, (fastf_t *)NULL, 2 , pt_type, (fastf_t *)NULL ); #else nmg_edge_g_cnurb_plinear( eu ); #endif } nmg_face_bb( fu->f_p, &tol ); }
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" ); } } } }
void process_non_light(struct model *m) { /* static due to bu exception handling */ static struct shell *s; static struct shell *next_s; static struct faceuse *fu; static struct faceuse *next_fu; static struct loopuse *lu; static struct nmgregion *reg; /* triangulate any faceuses with holes */ for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) ) { NMG_CK_REGION( reg ); s = BU_LIST_FIRST( shell, ®->s_hd ); while ( BU_LIST_NOT_HEAD( s, ®->s_hd ) ) { NMG_CK_SHELL( s ); next_s = BU_LIST_PNEXT( shell, &s->l ); fu = BU_LIST_FIRST( faceuse, &s->fu_hd ); while ( BU_LIST_NOT_HEAD( &fu->l, &s->fu_hd ) ) { int shell_is_dead=0; NMG_CK_FACEUSE( fu ); next_fu = BU_LIST_PNEXT( faceuse, &fu->l ); if ( fu->orientation != OT_SAME ) { fu = next_fu; continue; } if ( fu->fumate_p == next_fu ) { /* make sure next_fu is not the mate of fu */ next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l ); } /* check if this faceuse has any holes */ for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { NMG_CK_LOOPUSE( lu ); if ( lu->orientation == OT_OPPOSITE ) { /* this is a hole, so * triangulate the faceuse */ if ( !BU_SETJUMP ) { /* try */ if ( nmg_triangulate_fu( fu, &tol ) ) { if ( nmg_kfu( fu ) ) { (void) nmg_ks( s ); shell_is_dead = 1; } } } else { /* catch */ bu_log( "A face has failed triangulation!\n" ); if ( next_fu == fu->fumate_p ) next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l ); if ( nmg_kfu( fu ) ) { (void) nmg_ks( s ); shell_is_dead = 1; } } BU_UNSETJUMP; break; } } if ( shell_is_dead ) break; fu = next_fu; } s = next_s; } } }
void nmg_2_vrml(FILE *fp, const struct db_full_path *pathp, struct model *m, struct mater_info *mater) { struct nmgregion *reg; struct bu_ptbl verts; struct vrml_mat mat; struct bu_vls vls = BU_VLS_INIT_ZERO; char *tok; int i; int first=1; int is_light=0; float r, g, b; point_t ave_pt; char *full_path; /*There may be a better way to capture the region_id, than getting the rt_comb_internal structure, * (and may be a better way to capture the rt_comb_internal struct), but for now I just copied the * method used in select_lights/select_non_lights above, could have used a global variable but I noticed * none other were used, so I didn't want to be the first */ struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; NMG_CK_MODEL( m ); BARRIER_CHECK; full_path = db_path_to_string( pathp ); /* replace all occurrences of '.' with '_' */ char_replace(full_path, '.', '_'); RT_CK_FULL_PATH( pathp ); dp = DB_FULL_PATH_CUR_DIR( pathp ); if ( !(dp->d_flags & RT_DIR_COMB) ) return; id = rt_db_get_internal( &intern, dp, dbip, (matp_t)NULL, &rt_uniresource ); if ( id < 0 ) { bu_log( "Cannot internal form of %s\n", dp->d_namep ); return; } if ( id != ID_COMBINATION ) { bu_log( "Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep ); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB( comb ); if ( mater->ma_color_valid ) { r = mater->ma_color[0]; g = mater->ma_color[1]; b = mater->ma_color[2]; } else { r = g = b = 0.5; } if ( mater->ma_shader ) { tok = strtok( mater->ma_shader, tok_sep ); bu_strlcpy( mat.shader, tok, TXT_NAME_SIZE ); } else mat.shader[0] = '\0'; mat.shininess = -1; mat.transparency = -1.0; mat.lt_fraction = -1.0; VSETALL( mat.lt_dir, 0.0 ); mat.lt_angle = -1.0; mat.tx_file[0] = '\0'; mat.tx_w = -1; mat.tx_n = -1; bu_vls_strcpy( &vls, &mater->ma_shader[strlen(mat.shader)] ); (void)bu_struct_parse( &vls, vrml_mat_parse, (char *)&mat, NULL); if ( bu_strncmp( "light", mat.shader, 5 ) == 0 ) { /* this is a light source */ is_light = 1; } else { fprintf( fp, "\t<Shape DEF=\"%s\">\n", full_path); fprintf( fp, "\t\t<Appearance>\n"); if ( bu_strncmp( "plastic", mat.shader, 7 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 10; V_MAX(mat.transparency, 0.0); fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( bu_strncmp( "glass", mat.shader, 5 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 4; if ( mat.transparency < 0.0 ) mat.transparency = 0.8; fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( mater->ma_color_valid ) { fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\"/>\n", r, g, b); } else { /* If no color was defined set the colors according to the thousands groups */ int thou = comb->region_id/1000; thou == 0 ? fprintf( fp, "\t\t\t<Material USE=\"Material_999\"/>\n") : thou == 1 ? fprintf( fp, "\t\t\t<Material USE=\"Material_1999\"/>\n") : thou == 2 ? fprintf( fp, "\t\t\t<Material USE=\"Material_2999\"/>\n") : thou == 3 ? fprintf( fp, "\t\t\t<Material USE=\"Material_3999\"/>\n") : thou == 4 ? fprintf( fp, "\t\t\t<Material USE=\"Material_4999\"/>\n") : thou == 5 ? fprintf( fp, "\t\t\t<Material USE=\"Material_5999\"/>\n") : thou == 6 ? fprintf( fp, "\t\t\t<Material USE=\"Material_6999\"/>\n") : thou == 7 ? fprintf( fp, "\t\t\t<Material USE=\"Material_7999\"/>\n") : thou == 8 ? fprintf( fp, "\t\t\t<Material USE=\"Material_8999\"/>\n") : fprintf( fp, "\t\t\t<Material USE=\"Material_9999\"/>\n"); } } if ( !is_light ) { process_non_light(m); fprintf( fp, "\t\t</Appearance>\n"); } /* FIXME: need code to handle light */ /* get list of vertices */ nmg_vertex_tabulate( &verts, &m->magic ); fprintf( fp, "\t\t<IndexedFaceSet coordIndex=\"\n"); first = 1; if ( !is_light ) { for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) ) { struct shell *s; NMG_CK_REGION( reg ); for ( BU_LIST_FOR( s, shell, ®->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; if ( !first ) fprintf( fp, ",\n" ); else first = 0; fprintf( fp, "\t\t\t\t" ); for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { struct vertex *v; NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); fprintf( fp, " %d,", bu_ptbl_locate( &verts, (long *)v ) ); } fprintf( fp, "-1" ); } } } } /* close coordIndex */ fprintf( fp, "\" "); fprintf( fp, "normalPerVertex=\"false\" "); fprintf( fp, "convex=\"false\" "); fprintf( fp, "creaseAngle=\"0.5\" "); /* close IndexedFaceSet open tag */ fprintf( fp, ">\n"); } fprintf( fp, "\t\t\t<Coordinate point=\""); for ( i=0; i<BU_PTBL_END( &verts ); i++ ) { struct vertex *v; struct vertex_g *vg; point_t pt_meters; v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); vg = v->vg_p; NMG_CK_VERTEX_G( vg ); /* convert to desired units */ VSCALE( pt_meters, vg->coord, scale_factor ); if ( is_light ) VADD2( ave_pt, ave_pt, pt_meters ); if ( first ) { if ( !is_light ) fprintf( fp, " %10.10e %10.10e %10.10e, ", V3ARGS(pt_meters)); first = 0; } else if ( !is_light ) fprintf( fp, "%10.10e %10.10e %10.10e, ", V3ARGS( pt_meters )); } /* close point */ fprintf(fp, "\""); /* close Coordinate */ fprintf(fp, "/>\n"); /* IndexedFaceSet end tag */ fprintf( fp, "\t\t</IndexedFaceSet>\n"); /* Shape end tag */ fprintf( fp, "\t</Shape>\n"); BARRIER_CHECK; }
int nmg_class_pt_euvu(const fastf_t *pt, struct edgeuse *eu_in, const struct bn_tol *tol) { struct loopuse *lu; struct edgeuse *prev_eu; struct edgeuse *eu; struct vertex *v0, *v1, *v2; vect_t left; vect_t eu_dir; vect_t other_eudir; vect_t pt_dir; fastf_t xo, yo; fastf_t xpt, ypt; fastf_t len; int quado, quadpt; int nmg_class = NMG_CLASS_Unknown; int eu_is_crack = 0; int prev_eu_is_crack = 0; NMG_CK_EDGEUSE(eu_in); BN_CK_TOL(tol); eu = eu_in; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("nmg_class_pt_euvu((%g %g %g), eu=%p)\n", V3ARGS(pt), (void *)eu); if (UNLIKELY(*eu->up.magic_p != NMG_LOOPUSE_MAGIC)) { bu_log("nmg_class_pt_euvu() called with eu (%p) that isn't part of a loop\n", (void *)eu); bu_bomb("nmg_class_pt_euvu() called with eu that isn't part of a loop"); } lu = eu->up.lu_p; NMG_CK_LOOPUSE(lu); eu_is_crack = nmg_eu_is_part_of_crack(eu); prev_eu = BU_LIST_PPREV_CIRC(edgeuse, &eu->l); prev_eu_is_crack = nmg_eu_is_part_of_crack(prev_eu); /* if both EU's are cracks, we cannot classify */ if (eu_is_crack && prev_eu_is_crack) return NMG_CLASS_Unknown; if (eu_is_crack) { struct edgeuse *eu_test; int done = 0; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("nmg_class_pt_euvu: eu %p is a crack\n", (void *)eu); /* find next eu from this vertex that is not a crack */ eu_test = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l); while (!done) { while (eu_test->vu_p->v_p != eu->vu_p->v_p && eu_test != eu) eu_test = BU_LIST_PNEXT_CIRC(edgeuse, &eu_test->l); if (eu_test == eu) done = 1; if (!nmg_eu_is_part_of_crack(eu_test)) done = 1; if (!done) eu_test = BU_LIST_PNEXT_CIRC(edgeuse, &eu_test->l); } if (eu_test == eu) /* can't get away from crack */ return NMG_CLASS_Unknown; else eu = eu_test; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tUsing eu %p instead\n", (void *)eu); } if (prev_eu_is_crack) { struct edgeuse *eu_test; int done = 0; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("nmg_class_pt_euvu: prev_eu (%p) is a crack\n", (void *)prev_eu); /* find previous eu ending at this vertex that is not a crack */ eu_test = BU_LIST_PPREV_CIRC(edgeuse, &prev_eu->l); while (!done) { while (eu_test->eumate_p->vu_p->v_p != eu->vu_p->v_p && eu_test != prev_eu) eu_test = BU_LIST_PPREV_CIRC(edgeuse, &eu_test->l); if (eu_test == prev_eu) done = 1; if (!nmg_eu_is_part_of_crack(eu_test)) done = 1; if (!done) eu_test = BU_LIST_PPREV_CIRC(edgeuse, &eu_test->l); } if (eu_test == prev_eu) /* can't get away from crack */ return NMG_CLASS_Unknown; else prev_eu = eu_test; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tUsing prev_eu %p instead\n", (void *)prev_eu); } /* left is the Y-axis of our XY-coordinate system */ if (UNLIKELY(nmg_find_eu_leftvec(left, eu))) { bu_log("nmg_class_pt_euvu: nmg_find_eu_leftvec() for eu=%p failed!\n", (void *)eu); bu_bomb("nmg_class_pt_euvu: nmg_find_eu_leftvec() failed!"); } if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tprev_eu = %p, left = (%g %g %g)\n", (void *)prev_eu, V3ARGS(left)); /* v0 is the origin of the XY-coordinate system */ v0 = eu->vu_p->v_p; NMG_CK_VERTEX(v0); /* v1 is on the X-axis */ v1 = eu->eumate_p->vu_p->v_p; NMG_CK_VERTEX(v1); /* v2 determines angle prev_eu makes with X-axis */ v2 = prev_eu->vu_p->v_p; NMG_CK_VERTEX(v2); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tv0=%p, v1=%p, v2=%p\n", (void *)v0, (void *)v1, (void *)v2); /* eu_dir is our X-direction */ VSUB2(eu_dir, v1->vg_p->coord, v0->vg_p->coord); /* other_eudir is direction along the previous EU (from origin) */ VSUB2(other_eudir, v2->vg_p->coord, v0->vg_p->coord); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\teu_dir=(%g %g %g), other_eudir=(%g %g %g)\n", V3ARGS(eu_dir), V3ARGS(other_eudir)); /* get X and Y components for other_eu */ xo = VDOT(eu_dir, other_eudir); yo = VDOT(left, other_eudir); /* which quadrant does this XY point lie in */ quado = Quadrant(xo, yo); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\txo=%g, yo=%g, quadrant=%d\n", xo, yo, quado); /* get direction to PT from origin */ VSUB2(pt_dir, pt, v0->vg_p->coord); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tpt_dir=(%g %g %g)\n", V3ARGS(pt_dir)); /* get X and Y components for PT */ xpt = VDOT(eu_dir, pt_dir); ypt = VDOT(left, pt_dir); /* which quadrant does this XY point lie in */ quadpt = Quadrant(xpt, ypt); if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\txpt=%g, ypt=%g, quadrant=%d\n", xpt, ypt, quadpt); /* do a quadrant comparison first (cheap!!!) */ if (quadpt < quado) return NMG_CLASS_AinB; if (quadpt > quado) return NMG_CLASS_AoutB; /* both are in the same quadrant, need to normalize the coordinates */ len = sqrt(xo*xo + yo*yo); xo = xo/len; yo = yo/len; len = sqrt(xpt*xpt + ypt*ypt); xpt = xpt/len; ypt = ypt/len; if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("\tNormalized xo, yo=(%g %g), xpt, ypt=(%g %g)\n", xo, yo, xpt, ypt); switch (quadpt) { case 1: if (xpt >= xo && ypt <= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; case 2: if (xpt >= xo && ypt >= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; case 3: if (xpt <= xo && ypt >= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; case 4: if (xpt <= xo && ypt <= yo) nmg_class = NMG_CLASS_AinB; else nmg_class = NMG_CLASS_AoutB; break; default: bu_log("This can't happen (illegal quadrant %d)\n", quadpt); bu_bomb("This can't happen (illegal quadrant)\n"); break; } if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) bu_log("returning %s\n", nmg_class_name(nmg_class)); return nmg_class; }
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"); } }
/* routine to output the faceted NMG representation of a BRL-CAD region */ static void output_nmg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id)) { struct model *m; struct shell *s; struct vertex *v; char *region_name; 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); /* Output triangles */ if (verbose) { printf("Convert these triangles to your format for region %s\n", region_name); } else { printf("Converted %s\n", region_name); } 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 if needed */ /* 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; /* loop through the edges in this loop (facet) */ if (verbose) printf("\tfacet:\n"); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (verbose) printf("\t\t(%g %g %g)\n", V3ARGS(v->vg_p->coord)); } tot_polygons++; } } } bu_free(region_name, "region name"); }
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; }
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"); }
/** * Make a life-and-death decision on every element of a shell. * Descend the "great chain of being" from the face to loop to edge to * vertex, saving or demoting along the way. * * Note that there is no moving of items from one shell to another. */ HIDDEN void nmg_eval_shell(register struct shell *s, struct nmg_bool_state *bs) { struct faceuse *fu; struct faceuse *nextfu; struct loopuse *lu; struct loopuse *nextlu; struct edgeuse *eu; struct edgeuse *nexteu; struct vertexuse *vu; int loops_retained; NMG_CK_SHELL(s); BN_CK_TOL(bs->bs_tol); if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * For each face in the shell, process all the loops in the face, * and then handle the face and all loops as a unit. */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ fu = BU_LIST_FIRST(faceuse, &s->fu_hd); while (BU_LIST_NOT_HEAD(fu, &s->fu_hd)) { NMG_CK_FACEUSE(fu); nextfu = BU_LIST_PNEXT(faceuse, fu); /* Faceuse mates will be handled at same time as OT_SAME fu */ if (fu->orientation != OT_SAME) { fu = nextfu; continue; } if (fu->fumate_p == nextfu) nextfu = BU_LIST_PNEXT(faceuse, nextfu); /* Consider this face */ NMG_CK_FACE(fu->f_p); loops_retained = 0; lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); while (BU_LIST_NOT_HEAD(lu, &fu->lu_hd)) { NMG_CK_LOOPUSE(lu); nextlu = BU_LIST_PNEXT(loopuse, lu); if (lu->lumate_p == nextlu) nextlu = BU_LIST_PNEXT(loopuse, nextlu); NMG_CK_LOOP(lu->l_p); nmg_ck_lu_orientation(lu, bs->bs_tol); switch (nmg_eval_action(&lu->l_p->magic, bs)) { case BACTION_KILL: /* Kill by demoting loop to edges */ if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { /* loop of single vertex */ (void)nmg_klu(lu); } else if (nmg_demote_lu(lu) == 0) { nmg_eval_plot(bs, nmg_eval_count++); /* debug */ } lu = nextlu; continue; case BACTION_RETAIN: loops_retained++; break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } lu = nextlu; } if (RTG.NMG_debug & DEBUG_BOOLEVAL) bu_log("faceuse %p loops retained=%d\n", (void *)fu, loops_retained); if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * Here, faceuse will have 0 or more loopuses still in it. * Decide the fate of the face; if the face dies, * then any remaining loops, edges, etc., will die too. */ if (BU_LIST_IS_EMPTY(&fu->lu_hd)) { if (loops_retained) bu_bomb("nmg_eval_shell() empty faceuse with retained loops?\n"); /* faceuse is empty, face & mate die */ if (RTG.NMG_debug & DEBUG_BOOLEVAL) bu_log("faceuse %p empty, kill\n", (void *)fu); nmg_kfu(fu); /* kill face & mate, dequeue from shell */ if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); nmg_eval_plot(bs, nmg_eval_count++); /* debug */ fu = nextfu; continue; } if (loops_retained <= 0) { nmg_pr_fu(fu, (char *)NULL); bu_bomb("nmg_eval_shell() non-empty faceuse, no loops retained?\n"); } fu = nextfu; } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * For each loop in the shell, process. * Each loop is either a wire-loop, or a vertex-with-self-loop. * Only consider wire loops here. */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ lu = BU_LIST_FIRST(loopuse, &s->lu_hd); while (BU_LIST_NOT_HEAD(lu, &s->lu_hd)) { NMG_CK_LOOPUSE(lu); nextlu = BU_LIST_PNEXT(loopuse, lu); if (lu->lumate_p == nextlu) nextlu = BU_LIST_PNEXT(loopuse, nextlu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) { /* ignore vertex-with-self-loop */ lu = nextlu; continue; } NMG_CK_LOOP(lu->l_p); switch (nmg_eval_action(&lu->l_p->magic, bs)) { case BACTION_KILL: /* Demote the loopuse into wire edges */ /* kill loop & mate */ if (nmg_demote_lu(lu) == 0) nmg_eval_plot(bs, nmg_eval_count++); /* debug */ lu = nextlu; continue; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } lu = nextlu; } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * For each wire-edge in the shell, ... */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ eu = BU_LIST_FIRST(edgeuse, &s->eu_hd); while (BU_LIST_NOT_HEAD(eu, &s->eu_hd)) { NMG_CK_EDGEUSE(eu); nexteu = BU_LIST_PNEXT(edgeuse, eu); /* may be head */ if (eu->eumate_p == nexteu) nexteu = BU_LIST_PNEXT(edgeuse, nexteu); /* Consider this edge */ NMG_CK_EDGE(eu->e_p); switch (nmg_eval_action(&eu->e_p->magic, bs)) { case BACTION_KILL: /* Demote the edegeuse (and mate) into vertices */ if (nmg_demote_eu(eu) == 0) nmg_eval_plot(bs, nmg_eval_count++); /* debug */ eu = nexteu; continue; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } eu = nexteu; } /* * For each lone vertex-with-self-loop, process. * Note that these are intermixed in the loop list. * Each loop is either a wire-loop, or a vertex-with-self-loop. * Only consider cases of vertex-with-self-loop here. * * This case has to be handled separately, because a wire-loop * may be demoted to a set of wire-edges above, some of which * may be retained. The non-retained wire-edges may in turn * be demoted into vertex-with-self-loop objects above, * which will be processed here. */ nmg_eval_plot(bs, nmg_eval_count++); /* debug */ lu = BU_LIST_FIRST(loopuse, &s->lu_hd); while (BU_LIST_NOT_HEAD(lu, &s->lu_hd)) { NMG_CK_LOOPUSE(lu); nextlu = BU_LIST_PNEXT(loopuse, lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_VERTEXUSE_MAGIC) { /* ignore any remaining wire-loops */ lu = nextlu; continue; } if (nextlu == lu->lumate_p) nextlu = BU_LIST_PNEXT(loopuse, nextlu); vu = BU_LIST_PNEXT(vertexuse, &lu->down_hd); NMG_CK_VERTEXUSE(vu); NMG_CK_VERTEX(vu->v_p); switch (nmg_eval_action(&vu->v_p->magic, bs)) { case BACTION_KILL: /* Eliminate the loopuse, and mate */ nmg_klu(lu); lu = nextlu; continue; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } lu = nextlu; } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); /* * Final case: shell of a single vertexuse */ vu = s->vu_p; if (vu) { NMG_CK_VERTEXUSE(vu); NMG_CK_VERTEX(vu->v_p); switch (nmg_eval_action(&vu->v_p->magic, bs)) { case BACTION_KILL: nmg_kvu(vu); nmg_eval_plot(bs, nmg_eval_count++); /* debug */ s->vu_p = (struct vertexuse *)0; /* sanity */ break; case BACTION_RETAIN: break; default: bu_bomb("nmg_eval_shell() bad BACTION\n"); } } if (RTG.NMG_debug & DEBUG_VERIFY) nmg_vshell(&s->r_p->s_hd, s->r_p); nmg_eval_plot(bs, nmg_eval_count++); /* debug */ }
struct faceuse * Make_planar_face(struct shell *s, int entityno, int face_orient) { int sol_num; /* IGES solid type number */ int no_of_edges; /* edge count for this loop */ int no_of_param_curves; int vert_count = 0; /* Actual number of vertices used to make face */ struct iges_edge_use *edge_list; /* list of edgeuses from iges loop entity */ struct faceuse *fu = NULL; /* NMG face use */ struct loopuse *lu; /* NMG loop use */ struct vertex ***verts; /* list of vertices */ struct iges_vertex_list *v_list; int done; int i, j, k; /* Acquiring Data */ if (dir[entityno]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[entityno]->direct, dir[entityno]->name); return 0; } Readrec(dir[entityno]->param); Readint(&sol_num, ""); if (sol_num != 508) { bu_exit(1, "ERROR: Entity #%d is not a loop (it's a %s)\n", entityno, iges_type(sol_num)); } Readint(&no_of_edges, ""); edge_list = (struct iges_edge_use *)bu_calloc(no_of_edges, sizeof(struct iges_edge_use) , "Make_face (edge_list)"); for (i = 0; i < no_of_edges; i++) { Readint(&edge_list[i].edge_is_vertex, ""); Readint(&edge_list[i].edge_de, ""); Readint(&edge_list[i].index, ""); Readint(&edge_list[i].orient, ""); if (!face_orient) { /* need opposite orientation of edge */ if (edge_list[i].orient) edge_list[i].orient = 0; else edge_list[i].orient = 1; } edge_list[i].root = (struct iges_param_curve *)NULL; Readint(&no_of_param_curves, ""); for (j = 0; j < no_of_param_curves; j++) { struct iges_param_curve *new_crv; struct iges_param_curve *crv; Readint(&k, ""); /* ignore iso-parametric flag */ BU_ALLOC(new_crv, struct iges_param_curve); if (edge_list[i].root == (struct iges_param_curve *)NULL) edge_list[i].root = new_crv; else { crv = edge_list[i].root; while (crv->next != (struct iges_param_curve *)NULL) crv = crv->next; crv->next = new_crv; } Readint(&new_crv->curve_de, ""); new_crv->next = (struct iges_param_curve *)NULL; } } verts = (struct vertex ***)bu_calloc(no_of_edges, sizeof(struct vertex **) , "Make_face: vertex_list **"); for (i = 0; i < no_of_edges; i++) { if (face_orient) verts[i] = Get_vertex(&edge_list[i]); else verts[no_of_edges-1-i] = Get_vertex(&edge_list[i]); } /* eliminate zero length edges */ vert_count = no_of_edges; done = 0; while (!done) { done = 1; for (i = 0; i < vert_count; i++) { k = i + 1; if (k == vert_count) k = 0; if (verts[i] == verts[k]) { bu_log("Ignoring zero length edge\n"); done = 0; vert_count--; for (j = i; j < vert_count; j++) verts[j] = verts[j+1]; } } } if (vert_count) { plane_t pl; /* Plane equation for face */ fastf_t area; /* area of loop */ fastf_t dist; vect_t min2max; point_t outside_pt; fu = nmg_cmface(s, verts, vert_count); /* associate geometry */ v_list = vertex_root; while (v_list != NULL) { for (i = 0; i < v_list->no_of_verts; i++) { if (v_list->i_verts[i].v != NULL && v_list->i_verts[i].v->vg_p == NULL) { NMG_CK_VERTEX(v_list->i_verts[i].v); nmg_vertex_gv(v_list->i_verts[i].v , v_list->i_verts[i].pt); } } v_list = v_list->next; } lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); NMG_CK_LOOPUSE(lu); area = nmg_loop_plane_area(lu, pl); if (area < 0.0) { bu_log("Could not calculate area for face (entityno = %d)\n", entityno); nmg_pr_fu_briefly(fu, ""); nmg_kfu(fu); fu = (struct faceuse *)NULL; goto err; } nmg_face_g(fu, pl); nmg_face_bb(fu->f_p, &tol); /* find a point that is surely outside the loop */ VSUB2(min2max, fu->f_p->max_pt, fu->f_p->min_pt); VADD2(outside_pt, fu->f_p->max_pt, min2max); /* move it to the plane of the face */ dist = DIST_PT_PLANE(outside_pt, pl); VJOIN1(outside_pt, outside_pt, -dist, pl); if (nmg_class_pt_lu_except(outside_pt, lu, (struct edge *)NULL, &tol) != NMG_CLASS_AoutB) { nmg_reverse_face(fu); if (fu->orientation != OT_SAME) { fu = fu->fumate_p; if (fu->orientation != OT_SAME) bu_exit(1, "ERROR: no OT_SAME use for a face!\n"); } } } else bu_log("No edges left!\n"); err: bu_free((char *)edge_list, "Make_face (edge_list)"); bu_free((char *)verts, "Make_face (vertexlist)"); return fu; }
/* * Default keypoint in model space is established in "pt". Returns * GED_ERROR if unable to determine a keypoint, otherwise returns * GED_OK. */ int _ged_get_solid_keypoint(struct ged *const gedp, fastf_t *const pt, const struct rt_db_internal *const ip, const fastf_t *const mat) { point_t mpt; RT_CK_DB_INTERNAL(ip); switch (ip->idb_type) { case ID_CLINE: { struct rt_cline_internal *cli = (struct rt_cline_internal *)ip->idb_ptr; RT_CLINE_CK_MAGIC(cli); VMOVE(mpt, cli->v); break; } case ID_PARTICLE: { struct rt_part_internal *part = (struct rt_part_internal *)ip->idb_ptr; RT_PART_CK_MAGIC(part); VMOVE(mpt, part->part_V); break; } case ID_PIPE: { struct rt_pipe_internal *pipeip; struct wdb_pipept *pipe_seg; pipeip = (struct rt_pipe_internal *)ip->idb_ptr; RT_PIPE_CK_MAGIC(pipeip); pipe_seg = BU_LIST_FIRST(wdb_pipept, &pipeip->pipe_segs_head); VMOVE(mpt, pipe_seg->pp_coord); break; } case ID_METABALL: { struct rt_metaball_internal *metaball = (struct rt_metaball_internal *)ip->idb_ptr; struct wdb_metaballpt *metaballpt; RT_METABALL_CK_MAGIC(metaball); VSETALL(mpt, 0.0); metaballpt = BU_LIST_FIRST(wdb_metaballpt, &metaball->metaball_ctrl_head); VMOVE(mpt, metaballpt->coord); break; } case ID_ARBN: { struct rt_arbn_internal *arbn = (struct rt_arbn_internal *)ip->idb_ptr; size_t i, j, k; int good_vert = 0; RT_ARBN_CK_MAGIC(arbn); for (i = 0; i < arbn->neqn; i++) { for (j = i + 1; j < arbn->neqn; j++) { for (k = j + 1; k < arbn->neqn; k++) { if (!bn_mkpoint_3planes(mpt, arbn->eqn[i], arbn->eqn[j], arbn->eqn[k])) { size_t l; good_vert = 1; for (l = 0; l < arbn->neqn; l++) { if (l == i || l == j || l == k) continue; if (DIST_PT_PLANE(mpt, arbn->eqn[l]) > gedp->ged_wdbp->wdb_tol.dist) { good_vert = 0; break; } } if (good_vert) break; } } if (good_vert) break; } if (good_vert) break; } break; } case ID_EBM: { struct rt_ebm_internal *ebm = (struct rt_ebm_internal *)ip->idb_ptr; point_t pnt; RT_EBM_CK_MAGIC(ebm); VSETALL(pnt, 0.0); MAT4X3PNT(mpt, ebm->mat, pnt); break; } case ID_BOT: { struct rt_bot_internal *bot = (struct rt_bot_internal *)ip->idb_ptr; VMOVE(mpt, bot->vertices); break; } case ID_DSP: { struct rt_dsp_internal *dsp = (struct rt_dsp_internal *)ip->idb_ptr; point_t pnt; RT_DSP_CK_MAGIC(dsp); VSETALL(pnt, 0.0); MAT4X3PNT(mpt, dsp->dsp_stom, pnt); break; } case ID_HF: { struct rt_hf_internal *hf = (struct rt_hf_internal *)ip->idb_ptr; RT_HF_CK_MAGIC(hf); VMOVE(mpt, hf->v); break; } case ID_VOL: { struct rt_vol_internal *vol = (struct rt_vol_internal *)ip->idb_ptr; point_t pnt; RT_VOL_CK_MAGIC(vol); VSETALL(pnt, 0.0); MAT4X3PNT(mpt, vol->mat, pnt); break; } case ID_HALF: { struct rt_half_internal *haf = (struct rt_half_internal *)ip->idb_ptr; RT_HALF_CK_MAGIC(haf); VSCALE(mpt, haf->eqn, haf->eqn[H]); break; } case ID_ARB8: { struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr; RT_ARB_CK_MAGIC(arb); VMOVE(mpt, arb->pt[0]); break; } case ID_ELL: case ID_SPH: { struct rt_ell_internal *ell = (struct rt_ell_internal *)ip->idb_ptr; RT_ELL_CK_MAGIC(ell); VMOVE(mpt, ell->v); break; } case ID_SUPERELL: { struct rt_superell_internal *superell = (struct rt_superell_internal *)ip->idb_ptr; RT_SUPERELL_CK_MAGIC(superell); VMOVE(mpt, superell->v); break; } case ID_TOR: { struct rt_tor_internal *tor = (struct rt_tor_internal *)ip->idb_ptr; RT_TOR_CK_MAGIC(tor); VMOVE(mpt, tor->v); break; } case ID_TGC: case ID_REC: { struct rt_tgc_internal *tgc = (struct rt_tgc_internal *)ip->idb_ptr; RT_TGC_CK_MAGIC(tgc); VMOVE(mpt, tgc->v); break; } case ID_GRIP: { struct rt_grip_internal *gip = (struct rt_grip_internal *)ip->idb_ptr; RT_GRIP_CK_MAGIC(gip); VMOVE(mpt, gip->center); break; } case ID_ARS: { struct rt_ars_internal *ars = (struct rt_ars_internal *)ip->idb_ptr; RT_ARS_CK_MAGIC(ars); VMOVE(mpt, &ars->curves[0][0]); break; } case ID_RPC: { struct rt_rpc_internal *rpc = (struct rt_rpc_internal *)ip->idb_ptr; RT_RPC_CK_MAGIC(rpc); VMOVE(mpt, rpc->rpc_V); break; } case ID_RHC: { struct rt_rhc_internal *rhc = (struct rt_rhc_internal *)ip->idb_ptr; RT_RHC_CK_MAGIC(rhc); VMOVE(mpt, rhc->rhc_V); break; } case ID_EPA: { struct rt_epa_internal *epa = (struct rt_epa_internal *)ip->idb_ptr; RT_EPA_CK_MAGIC(epa); VMOVE(mpt, epa->epa_V); break; } case ID_EHY: { struct rt_ehy_internal *ehy = (struct rt_ehy_internal *)ip->idb_ptr; RT_EHY_CK_MAGIC(ehy); VMOVE(mpt, ehy->ehy_V); break; } case ID_HYP: { struct rt_hyp_internal *hyp = (struct rt_hyp_internal *)ip->idb_ptr; RT_HYP_CK_MAGIC(hyp); VMOVE(mpt, hyp->hyp_Vi); break; } case ID_ETO: { struct rt_eto_internal *eto = (struct rt_eto_internal *)ip->idb_ptr; RT_ETO_CK_MAGIC(eto); VMOVE(mpt, eto->eto_V); break; } case ID_POLY: { struct rt_pg_face_internal *_poly; struct rt_pg_internal *pg = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pg); _poly = pg->poly; VMOVE(mpt, _poly->verts); break; } case ID_SKETCH: { struct rt_sketch_internal *skt = (struct rt_sketch_internal *)ip->idb_ptr; RT_SKETCH_CK_MAGIC(skt); VMOVE(mpt, skt->V); break; } case ID_EXTRUDE: { struct rt_extrude_internal *extr = (struct rt_extrude_internal *)ip->idb_ptr; RT_EXTRUDE_CK_MAGIC(extr); if (extr->skt && extr->skt->verts) { VJOIN2(mpt, extr->V, extr->skt->verts[0][0], extr->u_vec, extr->skt->verts[0][1], extr->v_vec); } else { VMOVE(mpt, extr->V); } break; } case ID_NMG: { struct vertex *v; struct vertexuse *vu; struct edgeuse *eu; struct loopuse *lu; struct faceuse *fu; struct shell *s; struct nmgregion *r; struct model *m = (struct model *) ip->idb_ptr; NMG_CK_MODEL(m); /* set default first */ VSETALL(mpt, 0.0); if (BU_LIST_IS_EMPTY(&m->r_hd)) break; r = BU_LIST_FIRST(nmgregion, &m->r_hd); if (!r) break; NMG_CK_REGION(r); if (BU_LIST_IS_EMPTY(&r->s_hd)) break; s = BU_LIST_FIRST(shell, &r->s_hd); if (!s) break; NMG_CK_SHELL(s); if (BU_LIST_IS_EMPTY(&s->fu_hd)) fu = (struct faceuse *)NULL; else fu = BU_LIST_FIRST(faceuse, &s->fu_hd); if (fu) { NMG_CK_FACEUSE(fu); lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); NMG_CK_VERTEXUSE(eu->vu_p); v = eu->vu_p->v_p; } else { vu = BU_LIST_FIRST(vertexuse, &lu->down_hd); NMG_CK_VERTEXUSE(vu); v = vu->v_p; } NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } if (BU_LIST_IS_EMPTY(&s->lu_hd)) lu = (struct loopuse *)NULL; else lu = BU_LIST_FIRST(loopuse, &s->lu_hd); if (lu) { NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); NMG_CK_VERTEXUSE(eu->vu_p); v = eu->vu_p->v_p; } else { vu = BU_LIST_FIRST(vertexuse, &lu->down_hd); NMG_CK_VERTEXUSE(vu); v = vu->v_p; } NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } if (BU_LIST_IS_EMPTY(&s->eu_hd)) eu = (struct edgeuse *)NULL; else eu = BU_LIST_FIRST(edgeuse, &s->eu_hd); if (eu) { NMG_CK_EDGEUSE(eu); NMG_CK_VERTEXUSE(eu->vu_p); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } vu = s->vu_p; if (vu) { NMG_CK_VERTEXUSE(vu); v = vu->v_p; NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } } default: VSETALL(mpt, 0.0); bu_vls_printf(gedp->ged_result_str, "get_solid_keypoint: unrecognized solid type"); return GED_ERROR; } MAT4X3PNT(pt, mat, mpt); return GED_OK; }
int nmg_uv_in_lu(const fastf_t u, const fastf_t v, const struct loopuse *lu) { struct edgeuse *eu; int crossings=0; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) return( 0 ); for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { struct edge_g_cnurb *eg; if ( !eu->g.magic_p ) { bu_log( "nmg_uv_in_lu: eu (x%x) has no geometry!!!\n", eu ); bu_bomb( "nmg_uv_in_lu: eu has no geometry!!!\n" ); } if ( *eu->g.magic_p != NMG_EDGE_G_CNURB_MAGIC ) { bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing eu (x%x) that is not CNURB!!!!\n", lu, eu ); bu_bomb( "nmg_uv_in_lu: Called with lu containing eu that is not CNURB!!!\n" ); } eg = eu->g.cnurb_p; if ( eg->order <= 0 ) { struct vertexuse *vu1, *vu2; struct vertexuse_a_cnurb *vua1, *vua2; point_t uv1, uv2; fastf_t slope, intersept; fastf_t u_on_curve; vu1 = eu->vu_p; vu2 = eu->eumate_p->vu_p; if ( !vu1->a.magic_p || !vu2->a.magic_p ) { bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu with no attribute!!!!\n", lu ); bu_bomb( "nmg_uv_in_lu: Called with lu containing vu with no attribute!!!\n" ); } if ( *vu1->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC || *vu2->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC ) { bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu that is not CNURB!!!!\n", lu ); bu_bomb( "nmg_uv_in_lu: Called with lu containing vu that is not CNURB!!!\n" ); } vua1 = vu1->a.cnurb_p; vua2 = vu2->a.cnurb_p; VMOVE( uv1, vua1->param ); VMOVE( uv2, vua2->param ); if ( RT_NURB_IS_PT_RATIONAL( eg->pt_type ) ) { uv1[0] /= uv1[2]; uv1[1] /= uv1[2]; uv2[0] /= uv2[2]; uv2[1] /= uv2[2]; } if ( uv1[1] < v && uv2[1] < v ) continue; if ( uv1[1] > v && uv2[1] > v ) continue; if ( uv1[0] <= u && uv2[0] <= u ) continue; if ( uv1[0] == uv2[0] ) { if ( (uv1[1] <= v && uv2[1] >= v) || (uv2[1] <= v && uv1[1] >= v) ) crossings++; continue; } /* need to calculate intersection */ slope = (uv1[1] - uv2[1])/(uv1[0] - uv2[0]); intersept = uv1[1] - slope * uv1[0]; u_on_curve = (v - intersept)/slope; if ( u_on_curve > u ) crossings++; } else crossings += rt_uv_in_trim( eg, u, v ); } if ( crossings & 01 ) return( 1 ); else return( 0 ); }