int soup_add_face(struct soup_s *s, point_t a, point_t b, point_t c, const struct bn_tol *tol) { plane_t p; /* solve the plane */ bn_mk_plane_3pts(p, a, b, c, tol); return soup_add_face_precomputed(s, a, b, c, p, OUTSIDE); }
/** * Read a polygon file and convert it to an NMG shell * * A polygon file consists of the following: * * The first line consists of two integer numbers: the number of * points (vertices) in the file, followed by the number of polygons * in the file. This line is followed by lines for each of the * vertices. Each vertex is listed on its own line, as the 3tuple "X * Y Z". After the list of vertices comes the list of polygons. * each polygon is represented by a line containing 1) the number of * vertices in the polygon, followed by 2) the indices of the * vertices that make up the polygon. * * Implicitly returns r->s_p which is a new shell containing all the * faces from the polygon file. * * XXX This is a horrible way to do this. Lee violates his own rules * about not creating fundamental structures on his own... :-) * Retired in favor of more modern tessellation strategies. */ struct shell * nmg_polytonmg(FILE *fp, struct nmgregion *r, const struct bn_tol *tol) { int i, j, num_pts, num_facets, pts_this_face, facet; int vl_len; struct vertex **v; /* list of all vertices */ struct vertex **vl; /* list of vertices for this polygon*/ point_t p; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; plane_t plane; struct model *m; s = nmg_msv(r); m = s->r_p->m_p; nmg_kvu(s->vu_p); /* get number of points & number of facets in file */ if (fscanf(fp, "%d %d", &num_pts, &num_facets) != 2) bu_bomb("polytonmg() Error in first line of poly file\n"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("points: %d facets: %d\n", num_pts, num_facets); v = (struct vertex **) bu_calloc(num_pts, sizeof (struct vertex *), "vertices"); /* build the vertices */ for (i = 0; i < num_pts; ++i) { GET_VERTEX(v[i], m); v[i]->magic = NMG_VERTEX_MAGIC; } /* read in the coordinates of the vertices */ for (i=0; i < num_pts; ++i) { if (fscanf(fp, "%lg %lg %lg", &p[0], &p[1], &p[2]) != 3) bu_bomb("polytonmg() Error reading point"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("read vertex #%d (%g %g %g)\n", i, p[0], p[1], p[2]); nmg_vertex_gv(v[i], p); } vl = (struct vertex **)bu_calloc(vl_len=8, sizeof (struct vertex *), "vertex parameter list"); for (facet = 0; facet < num_facets; ++facet) { if (fscanf(fp, "%d", &pts_this_face) != 1) bu_bomb("polytonmg() error getting pt count for this face"); if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("facet %d pts in face %d\n", facet, pts_this_face); if (pts_this_face > vl_len) { while (vl_len < pts_this_face) vl_len *= 2; vl = (struct vertex **)bu_realloc((char *)vl, vl_len*sizeof(struct vertex *), "vertex parameter list (realloc)"); } for (i=0; i < pts_this_face; ++i) { if (fscanf(fp, "%d", &j) != 1) bu_bomb("polytonmg() error getting point index for v in f"); vl[i] = v[j-1]; } fu = nmg_cface(s, vl, pts_this_face); lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); /* XXX should check for vertex-loop */ eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); if (bn_mk_plane_3pts(plane, eu->vu_p->v_p->vg_p->coord, BU_LIST_PNEXT(edgeuse, eu)->vu_p->v_p->vg_p->coord, BU_LIST_PLAST(edgeuse, eu)->vu_p->v_p->vg_p->coord, tol)) { bu_log("At %d in %s\n", __LINE__, __FILE__); bu_bomb("polytonmg() cannot make plane equation\n"); } else nmg_face_g(fu, plane); } for (i=0; i < num_pts; ++i) { if (BU_LIST_IS_EMPTY(&v[i]->vu_hd)) continue; FREE_VERTEX(v[i]); } bu_free((char *)v, "vertex array"); return s; }
int coplanar_2d_coord_sys(point_t *origin_pnt, vect_t *u_axis, vect_t *v_axis, const point_t *points_3d, int n) { int i = 0; int have_normal = 0; plane_t plane; fastf_t dist_pt_pt = 0.0; fastf_t vdot = 1.0; point_t p_farthest; int p_farthest_index = 0; vect_t normal = VINIT_ZERO; const struct bn_tol tol = {BN_TOL_MAGIC, BN_TOL_DIST/2.0, BN_TOL_DIST*BN_TOL_DIST/4.0, 1.0e-6, 1.0-1.0e-6}; /* Step 1 - find center point */ VSETALL(*origin_pnt, 0.0); for (i = 0; i < n; i++) { VADD2(*origin_pnt, *origin_pnt, points_3d[i]); } VSCALE(*origin_pnt, *origin_pnt, 1.0/n); /* Step 2 - find furthest points from the center point */ VSETALL(p_farthest, 0.0); for (i = 0; i < n; i++) { fastf_t curr_dist = DIST_PT_PT_SQ(*origin_pnt, points_3d[i]); if (curr_dist > dist_pt_pt) { dist_pt_pt = curr_dist; VMOVE(p_farthest, points_3d[i]); p_farthest_index = i; } } VSUB2(*u_axis, p_farthest, *origin_pnt); VUNITIZE(*u_axis); /* Step 3 - find normal vector of plane holding points */ i = 0; dist_pt_pt = DIST_PT_PT(*origin_pnt, p_farthest); while (i < n) { if (i != p_farthest_index) { vect_t temp_vect; fastf_t curr_vdot; VSUB2(temp_vect, points_3d[i], *origin_pnt); VUNITIZE(temp_vect); curr_vdot = fabs(VDOT(temp_vect, *u_axis)); if (curr_vdot < vdot) { if (!bn_mk_plane_3pts(plane, *origin_pnt, p_farthest, points_3d[i], &tol)) { VSET(normal, plane[0], plane[1], plane[2]); have_normal = 1; vdot = curr_vdot; } } } i++; } if (!have_normal) return -1; VUNITIZE(normal); /* Step 4 - use vectors from steps 2 and 3 to find y axis vector */ VCROSS(*v_axis, *u_axis, normal); VUNITIZE(*v_axis); return 0; }
int read_arbn(char *name) { int npt; /* # vertex pts to be read in */ int npe; /* # planes from 3 vertex points */ int neq; /* # planes from equation */ int nae; /* # planes from az, el & vertex index */ int nface; /* total number of faces */ double *input_points = (double *)0; double *vertex = (double *)0; /* vertex list of final solid */ int last_vertex; /* index of first unused vertex */ int max_vertex; /* size of vertex array */ int *used = (int *)0; /* plane eqn use count */ plane_t *eqn = (plane_t *)0; /* plane equations */ int cur_eq = 0; /* current (free) equation number */ int symm = 0; /* symmetry about Y used */ register int i; int j; int k; register int m; point_t cent; /* centroid of arbn */ struct bn_tol tol; /* XXX The tolerance here is sheer guesswork */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; npt = getint( scard, 10+0*10, 10 ); npe = getint( scard, 10+1*10, 10 ); neq = getint( scard, 10+2*10, 10 ); nae = getint( scard, 10+3*10, 10 ); nface = npe + neq + nae; if ( npt < 1 ) { /* Having one point is necessary to compute centroid */ printf("arbn defined without at least one point\n"); bad: if (npt>0) eat( (npt+1)/2 ); /* vertex input_points */ if (npe>0) eat( (npe+5)/6 ); /* vertex pt index numbers */ if (neq>0) eat( neq ); /* plane eqns? */ if (nae>0) eat( (nae+1)/2 ); /* az el & vertex index? */ return(-1); } /* Allocate storage for plane equations */ eqn = (plane_t *)bu_malloc(nface*sizeof(plane_t), "eqn"); /* Allocate storage for per-plane use count */ used = (int *)bu_malloc(nface*sizeof(int), "used"); if ( npt >= 1 ) { /* Obtain vertex input_points */ input_points = (double *)bu_malloc(npt*3*sizeof(double), "input_points"); if ( getxsoldata( input_points, npt*3, sol_work ) < 0 ) goto bad; } /* Get planes defined by three points, 6 per card */ for ( i=0; i<npe; i += 6 ) { if ( get_line( scard, sizeof(scard), "arbn vertex point indices" ) == EOF ) { printf("too few cards for arbn %d\n", sol_work); return(-1); } for ( j=0; j<6; j++ ) { int q, r, s; point_t a, b, c; q = getint( scard, 10+j*10+0, 4 ); r = getint( scard, 10+j*10+4, 3 ); s = getint( scard, 10+j*10+7, 3 ); if ( q == 0 || r == 0 || s == 0 ) continue; if ( q < 0 ) { VMOVE( a, &input_points[((-q)-1)*3] ); a[Y] = -a[Y]; symm = 1; } else { VMOVE( a, &input_points[((q)-1)*3] ); } if ( r < 0 ) { VMOVE( b, &input_points[((-r)-1)*3] ); b[Y] = -b[Y]; symm = 1; } else { VMOVE( b, &input_points[((r)-1)*3] ); } if ( s < 0 ) { VMOVE( c, &input_points[((-s)-1)*3] ); c[Y] = -c[Y]; symm = 1; } else { VMOVE( c, &input_points[((s)-1)*3] ); } if ( bn_mk_plane_3pts( eqn[cur_eq], a, b, c, &tol ) < 0 ) { printf("arbn degenerate plane\n"); VPRINT("a", a); VPRINT("b", b); VPRINT("c", c); continue; } cur_eq++; } } /* Get planes defined by their equation */ for ( i=0; i < neq; i++ ) { register double scale; if ( get_line( scard, sizeof(scard), "arbn plane equation card" ) == EOF ) { printf("too few cards for arbn %d\n", sol_work); return(-1); } eqn[cur_eq][0] = getdouble( scard, 10+0*10, 10 ); eqn[cur_eq][1] = getdouble( scard, 10+1*10, 10 ); eqn[cur_eq][2] = getdouble( scard, 10+2*10, 10 ); eqn[cur_eq][3] = getdouble( scard, 10+3*10, 10 ); scale = MAGNITUDE(eqn[cur_eq]); if ( scale < SMALL ) { printf("arbn plane normal too small\n"); continue; } scale = 1/scale; VSCALE( eqn[cur_eq], eqn[cur_eq], scale ); eqn[cur_eq][3] *= scale; cur_eq++; } /* Get planes defined by azimuth, elevation, and pt, 2 per card */ for ( i=0; i < nae; i += 2 ) { if ( get_line( scard, sizeof(scard), "arbn az/el card" ) == EOF ) { printf("too few cards for arbn %d\n", sol_work); return(-1); } for ( j=0; j<2; j++ ) { double az, el; int vert_no; double cos_el; point_t pt; az = getdouble( scard, 10+j*30+0*10, 10 ) * bn_degtorad; el = getdouble( scard, 10+j*30+1*10, 10 ) * bn_degtorad; vert_no = getint( scard, 10+j*30+2*10, 10 ); if ( vert_no == 0 ) break; cos_el = cos(el); eqn[cur_eq][X] = cos(az)*cos_el; eqn[cur_eq][Y] = sin(az)*cos_el; eqn[cur_eq][Z] = sin(el); if ( vert_no < 0 ) { VMOVE( pt, &input_points[((-vert_no)-1)*3] ); pt[Y] = -pt[Y]; } else { VMOVE( pt, &input_points[((vert_no)-1)*3] ); } eqn[cur_eq][3] = VDOT(pt, eqn[cur_eq]); cur_eq++; } } if ( nface != cur_eq ) { printf("arbn expected %d faces, got %d\n", nface, cur_eq); return(-1); } /* Average all given points together to find centroid */ /* This is why there must be at least one (two?) point given */ VSETALL(cent, 0); for ( i=0; i<npt; i++ ) { VADD2( cent, cent, &input_points[i*3] ); } VSCALE( cent, cent, 1.0/npt ); if ( symm ) cent[Y] = 0; /* Point normals away from centroid */ for ( i=0; i<nface; i++ ) { double dist; dist = VDOT( eqn[i], cent ) - eqn[i][3]; /* If dist is negative, 'cent' is inside halfspace */ #define DIST_TOL (1.0e-8) #define DIST_TOL_SQ (1.0e-10) if ( dist < -DIST_TOL ) continue; if ( dist > DIST_TOL ) { /* Flip halfspace over */ VREVERSE( eqn[i], eqn[i] ); eqn[i][3] = -eqn[i][3]; } else { /* Centroid lies on this face */ printf("arbn centroid lies on face\n"); return(-1); } } /* Release storage for input points */ bu_free( (char *)input_points, "input_points" ); input_points = (double *)0; /* * ARBN must be convex. Test for concavity. * Byproduct is an enumeration of all the verticies. */ last_vertex = max_vertex = 0; /* Zero face use counts */ for ( i=0; i<nface; i++ ) { used[i] = 0; } for ( i=0; i<nface-2; i++ ) { for ( j=i+1; j<nface-1; j++ ) { double dot; int point_count; /* # points on this line */ /* If normals are parallel, no intersection */ dot = VDOT( eqn[i], eqn[j] ); if ( !NEAR_ZERO( dot, 0.999999 ) ) continue; point_count = 0; for ( k=j+1; k<nface; k++ ) { point_t pt; if ( bn_mkpoint_3planes( pt, eqn[i], eqn[j], eqn[k] ) < 0 ) continue; /* See if point is outside arb */ for ( m=0; m<nface; m++ ) { if ( i==m || j==m || k==m ) continue; if ( VDOT(pt, eqn[m])-eqn[m][3] > DIST_TOL ) goto next_k; } /* See if vertex already was found */ for ( m=0; m<last_vertex; m++ ) { vect_t dist; VSUB2( dist, pt, &vertex[m*3] ); if ( MAGSQ(dist) < DIST_TOL_SQ ) goto next_k; } /* * Add point to vertex array. * If more room needed, realloc. */ if ( last_vertex >= max_vertex ) { if ( max_vertex == 0 ) { max_vertex = 3; vertex = (double *)bu_malloc( max_vertex*3*sizeof(double), "vertex" ); } else { max_vertex *= 10; vertex = (double *)bu_realloc( (char *)vertex, max_vertex*3*sizeof(double), "vertex" ); } } VMOVE( &vertex[last_vertex*3], pt ); last_vertex++; point_count++; /* Increment "face used" counts */ used[i]++; used[j]++; used[k]++; next_k: ; } if ( point_count > 2 ) { printf("arbn: warning, point_count on line=%d\n", point_count); } } } /* If any planes were not used, then arbn is not convex */ for ( i=0; i<nface; i++ ) { if ( used[i] != 0 ) continue; /* face was used */ printf("arbn face %d unused, solid is not convex\n", i); return(-1); } /* Write out the solid ! */ i = mk_arbn( outfp, name, nface, eqn ); if ( input_points ) bu_free( (char *)input_points, "input_points" ); if ( vertex ) bu_free( (char *)vertex, "vertex" ); if ( eqn ) bu_free( (char *)eqn, "eqn" ); if ( used ) bu_free( (char *)used, "used" ); return(i); }
void make_3manifold_bits(struct bn_tol *tol) { plane_t plane; struct faceuse *fu_end; memset((char *)vertl, 0, sizeof(vertl)); memset((char *)f_vertl, 0, sizeof(f_vertl)); /* front right */ f_vertl[0] = &vertl[0]; f_vertl[1] = &vertl[1]; f_vertl[2] = &vertl[2]; f_vertl[3] = &vertl[3]; fr_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[0], 100.0, 100.0, 100.0); nmg_vertex_g(vertl[1], 50.0, 100.0, 100.0); nmg_vertex_g(vertl[2], 50.0, 0.0, 100.0); nmg_vertex_g(vertl[3], 100.0, 0.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); /* make top right */ f_vertl[0] = &vertl[0]; f_vertl[1] = &vertl[4]; f_vertl[2] = &vertl[5]; f_vertl[3] = &vertl[1]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[4], 100.0, 100.0, 0.0); nmg_vertex_g(vertl[5], 50.0, 100.0, 0.0); (void)nmg_fu_planeeqn(fu, tol); /* back right */ f_vertl[0] = &vertl[5]; f_vertl[1] = &vertl[4]; f_vertl[2] = &vertl[6]; f_vertl[3] = &vertl[7]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[6], 100.0, 0.0, 0.0); nmg_vertex_g(vertl[7], 50.0, 0.0, 0.0); (void)nmg_fu_planeeqn(fu, tol); /* bottom right */ f_vertl[0] = &vertl[7]; f_vertl[1] = &vertl[6]; f_vertl[2] = &vertl[3]; f_vertl[3] = &vertl[2]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* right end */ f_vertl[0] = &vertl[3]; f_vertl[1] = &vertl[6]; f_vertl[2] = &vertl[4]; f_vertl[3] = &vertl[0]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make split top */ f_vertl[0] = &vertl[1]; f_vertl[1] = &vertl[5]; f_vertl[2] = &vertl[8]; f_vertl[3] = &vertl[9]; tc_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[8], 25.0, 100.0, 0.0); nmg_vertex_g(vertl[9], 25.0, 100.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[9]; f_vertl[1] = &vertl[8]; f_vertl[2] = &vertl[12]; f_vertl[3] = &vertl[13]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[12], 0.0, 100.0, 0.0); nmg_vertex_g(vertl[13], 0.0, 100.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); /* make split & funky front side * we make the convex face first, make the second (non-convex) portion * after the face normal has been computed. */ f_vertl[0] = &vertl[14]; f_vertl[1] = &vertl[18]; f_vertl[2] = &vertl[15]; f_vertl[3] = &vertl[16]; fl_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[14], 0.0, 25.0, 100.0); nmg_vertex_g(vertl[15], 25.0, 0.0, 100.0); nmg_vertex_g(vertl[16], 25.0, 25.0, 100.0); nmg_vertex_g(vertl[18], 0.0, 0.0, 100.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[1]; f_vertl[1] = &vertl[9]; f_vertl[2] = &vertl[10]; f_vertl[3] = &vertl[9]; f_vertl[4] = &vertl[13]; f_vertl[5] = &vertl[14]; f_vertl[6] = &vertl[16]; f_vertl[7] = &vertl[15]; f_vertl[8] = &vertl[2]; nmg_jf(fu, nmg_cmface(s, f_vertl, 9)); nmg_vertex_g(vertl[10], 25.0, 75.0, 100.0); /* make split back side */ f_vertl[0] = &vertl[5]; f_vertl[1] = &vertl[7]; f_vertl[2] = &vertl[17]; f_vertl[3] = &vertl[12]; f_vertl[4] = &vertl[8]; f_vertl[5] = &vertl[11]; f_vertl[6] = &vertl[8]; bl_fu = fu = nmg_cmface(s, f_vertl, 7); nmg_vertex_g(vertl[11], 25.0, 75.0, 0.0); nmg_vertex_g(vertl[17], 0.0, 0.0, 0.0); /* this face isn't strictly convex, so we have to make the plane * equation the old-fashioned way. */ bn_mk_plane_3pts(plane, vertl[7]->vg_p->coord, vertl[17]->vg_p->coord, vertl[12]->vg_p->coord, tol); nmg_face_g(fu, plane); /* make funky end */ f_vertl[0] = &vertl[14]; f_vertl[1] = &vertl[20]; f_vertl[2] = &vertl[19]; f_vertl[3] = &vertl[18]; fu_end = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[19], 0.0, 0.0, 75.0); nmg_vertex_g(vertl[20], 0.0, 25.0, 75.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[12]; f_vertl[1] = &vertl[17]; f_vertl[2] = &vertl[19]; f_vertl[3] = &vertl[20]; f_vertl[4] = &vertl[14]; f_vertl[5] = &vertl[13]; nmg_jf(fu, nmg_cmface(s, f_vertl, 6)); /* make funky bottom */ f_vertl[0] = &vertl[15]; f_vertl[1] = &vertl[18]; f_vertl[2] = &vertl[19]; f_vertl[3] = &vertl[21]; ul_fu = fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[21], 25.0, 0.0, 75.0); (void)nmg_fu_planeeqn(fu, tol); f_vertl[0] = &vertl[7]; f_vertl[1] = &vertl[2]; f_vertl[2] = &vertl[15]; f_vertl[3] = &vertl[21]; f_vertl[4] = &vertl[19]; f_vertl[5] = &vertl[17]; nmg_jf(fu, nmg_cmface(s, f_vertl, 6)); /* now create the (3manifold) hole through the object */ /* make the holes in the end face */ f_vertl[0] = &vertl[29]; f_vertl[1] = &vertl[28]; f_vertl[2] = &vertl[27]; f_vertl[3] = &vertl[26]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[26], 0.0, 60.0, 10.0); nmg_vertex_g(vertl[27], 0.0, 60.0, 25.0); nmg_vertex_g(vertl[28], 0.0, 40.0, 25.0); nmg_vertex_g(vertl[29], 0.0, 40.0, 10.0); /* GROSS HACK XXX * we reverse the orientation of the faceuses and loopuses * so that we can make the hole as a face, and transfer the hole * to an existing face */ lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); lu->orientation = OT_OPPOSITE; lu->lumate_p->orientation = OT_OPPOSITE; fu->orientation = OT_OPPOSITE; fu->fumate_p->orientation = OT_SAME; nmg_jf(fu_end, fu->fumate_p); f_vertl[0] = &vertl[22]; f_vertl[1] = &vertl[23]; f_vertl[2] = &vertl[24]; f_vertl[3] = &vertl[25]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[22], 10.0, 60.0, 0.0); nmg_vertex_g(vertl[23], 25.0, 60.0, 0.0); nmg_vertex_g(vertl[24], 25.0, 40.0, 0.0); nmg_vertex_g(vertl[25], 10.0, 40.0, 0.0); /* GROSS HACK XXX * we reverse the orientation of the faceuses and loopuses * so that we can make the hole as a face, and transfer the hole * to an existing face. */ lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); lu->orientation = OT_OPPOSITE; lu->lumate_p->orientation = OT_OPPOSITE; fu->orientation = OT_OPPOSITE; fu->fumate_p->orientation = OT_SAME; nmg_jf(bl_fu, fu->fumate_p); /* make the top of the hole */ f_vertl[0] = &vertl[22]; f_vertl[1] = &vertl[23]; f_vertl[2] = &vertl[27]; f_vertl[3] = &vertl[26]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make the bottom of the hole */ f_vertl[0] = &vertl[24]; f_vertl[1] = &vertl[25]; f_vertl[2] = &vertl[29]; f_vertl[3] = &vertl[28]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make origin-ward side of the hole */ f_vertl[0] = &vertl[22]; f_vertl[1] = &vertl[26]; f_vertl[2] = &vertl[29]; f_vertl[3] = &vertl[25]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* make last side of hole */ f_vertl[0] = &vertl[23]; f_vertl[1] = &vertl[24]; f_vertl[2] = &vertl[28]; f_vertl[3] = &vertl[27]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* now make the void in the center of the solid */ /* void bottom */ f_vertl[0] = &vertl[41]; f_vertl[1] = &vertl[40]; f_vertl[2] = &vertl[39]; f_vertl[3] = &vertl[38]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[38], 85.0, 40.0, 60.0); nmg_vertex_g(vertl[39], 65.0, 40.0, 60.0); nmg_vertex_g(vertl[40], 65.0, 40.0, 40.0); nmg_vertex_g(vertl[41], 85.0, 40.0, 40.0); (void)nmg_fu_planeeqn(fu, tol); /* void top */ f_vertl[0] = &vertl[42]; f_vertl[1] = &vertl[43]; f_vertl[2] = &vertl[44]; f_vertl[3] = &vertl[45]; fu = nmg_cmface(s, f_vertl, 4); nmg_vertex_g(vertl[42], 85.0, 60.0, 40.0); nmg_vertex_g(vertl[43], 85.0, 60.0, 60.0); nmg_vertex_g(vertl[44], 65.0, 60.0, 60.0); nmg_vertex_g(vertl[45], 65.0, 60.0, 40.0); (void)nmg_fu_planeeqn(fu, tol); /* void front */ f_vertl[0] = &vertl[44]; f_vertl[1] = &vertl[43]; f_vertl[2] = &vertl[38]; f_vertl[3] = &vertl[39]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* void back */ f_vertl[0] = &vertl[42]; f_vertl[1] = &vertl[45]; f_vertl[2] = &vertl[40]; f_vertl[3] = &vertl[41]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* void left */ f_vertl[0] = &vertl[45]; f_vertl[1] = &vertl[44]; f_vertl[2] = &vertl[39]; f_vertl[3] = &vertl[40]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); /* void right */ f_vertl[0] = &vertl[42]; f_vertl[1] = &vertl[41]; f_vertl[2] = &vertl[38]; f_vertl[3] = &vertl[43]; fu = nmg_cmface(s, f_vertl, 4); (void)nmg_fu_planeeqn(fu, tol); }
int bn_tri_tri_isect_coplanar(point_t V0, point_t V1, point_t V2, point_t U0, point_t U1, point_t U2, int area_flag) { int ret; fastf_t A[3]; short i0, i1; point_t E1, E2, N; plane_t P1, P2; static const struct bn_tol tol = { BN_TOL_MAGIC, EPSILON, EPSILON*EPSILON, 1e-6, 1-1e-6 }; /* compute plane of triangle (V0, V1, V2) */ ret = bn_mk_plane_3pts(P1, V0, V1, V2, &tol); if (ret) return -1; /* compute plane of triangle (U0, U1, U2) */ ret = bn_mk_plane_3pts(P2, U0, U1, U2, &tol); if (ret) return -1; /* verify that triangles are coplanar */ if (bn_coplanar(P1, P2, &tol) <= 0) return -1; /* first project onto an axis-aligned plane, that maximizes the area */ /* of the triangles, compute indices: i0, i1. */ VSUB2(E1, V1, V0); VSUB2(E2, V2, V0); VCROSS(N, E1, E2); A[0]=FABS(N[0]); A[1]=FABS(N[1]); A[2]=FABS(N[2]); if (A[0]>A[1]) { if (A[0]>A[2]) { i0=1; /* A[0] is greatest */ i1=2; } else { i0=0; /* A[2] is greatest */ i1=1; } } else { /* A[0]<=A[1] */ if (A[2]>A[1]) { i0=0; /* A[2] is greatest */ i1=1; } else { i0=0; /* A[1] is greatest */ i1=2; } } /* test all edges of triangle 1 against the edges of triangle 2 */ if (!area_flag) { EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2); EDGE_AGAINST_TRI_EDGES(V1, V2, U0, U1, U2); EDGE_AGAINST_TRI_EDGES(V2, V0, U0, U1, U2); } else { EDGE_AGAINST_TRI_EDGES_AREA(V0, V1, U0, U1, U2); EDGE_AGAINST_TRI_EDGES_AREA(V1, V2, U0, U1, U2); EDGE_AGAINST_TRI_EDGES_AREA(V2, V0, U0, U1, U2); } /* finally, test if tri1 is totally contained in tri2 or vice versa */ POINT_IN_TRI(V0, U0, U1, U2); POINT_IN_TRI(U0, V0, V1, V2); return 0; }