示例#1
0
文件: nmg_mesh.c 项目: kanzure/brlcad
/**
 * Scan through all the edges of fu1 and fu2, ensuring that all
 * edges involving the same vertex pair are indeed shared.
 * This means worrying about merging ("meshing") all the faces in the
 * proper radial orientation around the edge.
 * XXX probably should return count;
 */
void
nmg_mesh_faces(struct faceuse *fu1, struct faceuse *fu2, const struct bn_tol *tol)
{
    int count = 0;

    NMG_CK_FACEUSE(fu1);
    NMG_CK_FACEUSE(fu2);
    BN_CK_TOL(tol);

    if (RTG.NMG_debug & DEBUG_MESH_EU && RTG.NMG_debug & DEBUG_PLOTEM) {
	nmg_pl_2fu("Before_mesh%d.plot3", fu1, fu2, 1);
    }

    if (RTG.NMG_debug & DEBUG_MESH_EU)
	bu_log("meshing self (fu1 %8p)\n", (void *)fu1);
    count += nmg_mesh_two_faces(fu1, fu1, tol);

    if (RTG.NMG_debug & DEBUG_MESH_EU)
	bu_log("meshing self (fu2 %8p)\n", (void *)fu2);
    count += nmg_mesh_two_faces(fu2, fu2, tol);

    if (RTG.NMG_debug & DEBUG_MESH_EU)
	bu_log("meshing to other (fu1:%8p fu2:%8p)\n", (void *)fu1, (void *)fu2);
    count += nmg_mesh_two_faces(fu1, fu2, tol);

    if (RTG.NMG_debug & DEBUG_MESH_EU && RTG.NMG_debug & DEBUG_PLOTEM) {
	nmg_pl_2fu("After_mesh%d.plot3", fu1, fu2, 1);
    }
}
示例#2
0
文件: nmg_eval.c 项目: kanzure/brlcad
/**
 * 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");
    }
}
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;

    // Verify NMG
    RT_CK_DB_INTERNAL(ip);
    m = (struct model *)ip->idb_ptr;
    NMG_CK_MODEL(m);

    // Both NMG and brep structures re-use components between faces.  In order to track
    // when the conversion routine has already handled an NMG element, use an array.
    long *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;

    // Iterate over all faces in the NMG
    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;
		if (nmg_brep_face(b, fu, tol, brepi)) return;
	    }
	    (*b)->SetTrimIsoFlags();
	}
    }
}
示例#4
0
文件: nmg_mesh.c 项目: kanzure/brlcad
/**
 * The return is the number of edges meshed.
 */
int
nmg_mesh_face_shell(struct faceuse *fu1, struct shell *s, const struct bn_tol *tol)
{
    register struct faceuse *fu2;
    int count = 0;

    NMG_CK_FACEUSE(fu1);
    NMG_CK_SHELL(s);
    BN_CK_TOL(tol);

    count += nmg_mesh_two_faces(fu1, fu1, tol);
    for (BU_LIST_FOR(fu2, faceuse, &s->fu_hd)) {
	NMG_CK_FACEUSE(fu2);
	count += nmg_mesh_two_faces(fu2, fu2, tol);
	count += nmg_mesh_two_faces(fu1, fu2, tol);
    }
    /* XXX What about wire edges in the shell? */
    return count;
}
示例#5
0
文件: nmg_mesh.c 项目: kanzure/brlcad
/**
 * Mesh every edge in shell 1 with every edge in shell 2.
 * The return is the number of edges meshed.
 *
 * Does not use nmg_mesh_face_shell() to keep face/self meshing
 * to the absolute minimum necessary.
 */
int
nmg_mesh_shell_shell(struct shell *s1, struct shell *s2, const struct bn_tol *tol)
{
    struct faceuse *fu1;
    struct faceuse *fu2;
    int count = 0;

    NMG_CK_SHELL(s1);
    NMG_CK_SHELL(s2);
    BN_CK_TOL(tol);

    nmg_region_v_unique(s1->r_p, tol);
    nmg_region_v_unique(s2->r_p, tol);

    /* First, mesh all faces of shell 2 with themselves */
    for (BU_LIST_FOR(fu2, faceuse, &s2->fu_hd)) {
	NMG_CK_FACEUSE(fu2);
	count += nmg_mesh_two_faces(fu2, fu2, tol);
    }

    /* Visit every face in shell 1 */
    for (BU_LIST_FOR(fu1, faceuse, &s1->fu_hd)) {
	NMG_CK_FACEUSE(fu1);

	/* First, mesh each face in shell 1 with itself */
	count += nmg_mesh_two_faces(fu1, fu1, tol);

	/* Visit every face in shell 2 */
	for (BU_LIST_FOR(fu2, faceuse, &s2->fu_hd)) {
	    NMG_CK_FACEUSE(fu2);
	    count += nmg_mesh_two_faces(fu1, fu2, tol);
	}
    }

    /* XXX What about wire edges in the shell? */

    /* Visit every wire loop in shell 1 */

    /* Visit every wire edge in shell 1 */

    return count;
}
示例#6
0
文件: g-euclid.c 项目: kanzure/brlcad
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);
}
void
nmg_visit_faceuse(struct faceuse *fu, const struct nmg_visit_handlers *htab, void *state)


/* Handler's private state */
{
    struct loopuse *lu;

    NMG_CK_FACEUSE(fu);

    if (htab->bef_faceuse) htab->bef_faceuse((uint32_t *)fu, state, 0);

    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
	nmg_visit_loopuse(lu, htab, state);
    }

    nmg_visit_face(fu->f_p, htab, state);

    if (htab->aft_faceuse) htab->aft_faceuse((uint32_t *)fu, 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");
}
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, &reg->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 {
示例#11
0
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[]");
}
示例#12
0
文件: g-obj.c 项目: cciechad/brlcad
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" );
		}
	    }
	}
    }
示例#13
0
文件: g-off.c 项目: cciechad/brlcad
/*
 *	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(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, &reg->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;
}
示例#15
0
/* 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 );
}
示例#16
0
文件: nmg_eval.c 项目: kanzure/brlcad
/**
 * 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 */
}
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, &reg->s_hd );
	while ( BU_LIST_NOT_HEAD( s, &reg->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;
	}
    }
}
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");
}
示例#19
0
/* 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");
}
示例#20
0
文件: bot_fuse.c 项目: kanzure/brlcad
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;
}
示例#21
0
文件: off-g.c 项目: kanzure/brlcad
int read_faces(struct model *m, FILE *fgeom)
{
    int 		   nverts, nfaces, nedges;
    int 	   i, j, fail=0;
    fastf_t 	  *pts;
    struct vertex 	 **verts;
    struct faceuse 	 **outfaceuses;
    struct nmgregion  *r;
    struct shell 	  *s;
    size_t ret;

    /* Get numbers of vertices and faces, and grab the appropriate amount of memory */
    if (fscanf(fgeom, "%d %d %d", &nverts, &nfaces, &nedges) != 3)
	bu_exit(1, "Cannot read number of vertices, faces, edges.\n");

    pts = (fastf_t *) bu_malloc(sizeof(fastf_t) * 3 * nverts, "points list");
    verts = (struct vertex **) bu_malloc(sizeof(struct vertex *) * nverts, "vertices");
    outfaceuses = (struct faceuse **) bu_malloc(sizeof(struct faceuse *) * nfaces, "faceuses");

    /* Read in vertex geometry, store in geometry list */
    for (i = 0; i < nverts; i++) {
	double scan[3];
	if (fscanf(fgeom, "%lf %lf %lf", &scan[0], &scan[1], &scan[2]) != 3) {
	    bu_exit(1, "Not enough data points in geometry file.\n");
	}
	pts[3*i] = scan[0];
	pts[3*i+1] = scan[1];
	pts[3*i+2] = scan[2];

	verts[i] = (struct vertex *) 0;
	ret = fscanf(fgeom, "%*[^\n]");
	if (ret > 0)
	    bu_log("unknown parsing error\n");
    }

    r = nmg_mrsv(m);		/* Make region, empty shell, vertex. */
    s = BU_LIST_FIRST(shell, &r->s_hd);


    for (i = 0; i < nfaces; i++) {
	/* Read in each of the faces */
	struct vertex **vlist;
	int *pinds;

	if (fscanf(fgeom, "%d", &nedges) != 1) {
	    bu_exit(1, "Not enough faces in geometry file.\n");
	}
	/* Grab memory for list for this face. */
	vlist = (struct vertex **) bu_malloc(sizeof(struct vertex *) * nedges, "vertex list");
	pinds = (int *) bu_malloc(sizeof(int) * nedges, "point indices");

	for (j = 0; j < nedges; j++) {
	    /* Read list of point indices. */
	    if (fscanf(fgeom, "%d", &pinds[j]) != 1) {
		bu_exit(1, "Not enough points on face.\n");
	    }
	    vlist[j] = verts[pinds[j]-1];
	}

	outfaceuses[i] = nmg_cface(s, vlist, nedges);	/* Create face. */
	NMG_CK_FACEUSE(outfaceuses[i]);

	for (j = 0; j < nedges; j++)		/* Save (possibly) newly created vertex structs. */
	    verts[pinds[j]-1] = vlist[j];

	ret = fscanf(fgeom, "%*[^\n]");
	if (ret > 0)
	    bu_log("unknown parsing error\n");

	bu_free((char *)vlist, "vertext list");
	bu_free((char *)pinds, "point indices");
    }

    for (i = 0; i < nverts; i++)
	if (verts[i] != 0)
	    nmg_vertex_gv(verts[i], &pts[3*i]);
	else
	    fprintf(stderr, "Warning: vertex %d unused.\n", i+1);

    for (i = 0; i < nfaces; i++) {
	plane_t pl;

	fprintf(stderr, "planeeqning face %d.\n", i);
	if ( nmg_loop_plane_area( BU_LIST_FIRST( loopuse, &outfaceuses[i]->lu_hd ), pl ) < 0.0 )
	    fail = 1;
	else
	    nmg_face_g( outfaceuses[i], pl );

    }

    if (fail) return -1;

    nmg_gluefaces(outfaceuses, nfaces, &tol);
    nmg_region_a(r, &tol);

    bu_free((char *)pts, "points list");
    return 0;
}
示例#22
0
文件: nmg_mesh.c 项目: kanzure/brlcad
/**
 * Make all the edgeuses around eu2's edge to refer to eu1's edge,
 * taking care to organize them into the proper angular orientation,
 * so that the attached faces are correctly arranged radially
 * around the edge.
 *
 * This depends on both edges being part of face loops,
 * with vertex and face geometry already associated.
 *
 * The two edgeuses being joined might well be from separate shells,
 * so the issue of preserving (simple) faceuse orientation parity
 * (SAME, OPPOSITE, OPPOSITE, SAME, ...)
 * can't be used here -- that only applies to faceuses from the same shell.
 *
 * Some of the edgeuses around both edges may be wires.
 *
 * Call to nmg_check_radial at end has been deleted.
 * Note that after two radial EU's have been joined
 * a third cannot be joined to them without creating
 * unclosed space that nmg_check_radial will find.
 */
void
nmg_radial_join_eu(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
{

    NMG_CK_EDGEUSE(eu1);
    NMG_CK_EDGEUSE(eu1->radial_p);
    NMG_CK_EDGEUSE(eu1->eumate_p);
    NMG_CK_EDGEUSE(eu2);
    NMG_CK_EDGEUSE(eu2->radial_p);
    NMG_CK_EDGEUSE(eu2->eumate_p);
    BN_CK_TOL(tol);

    if (eu1->e_p == eu2->e_p) return;

    if (!NMG_ARE_EUS_ADJACENT(eu1, eu2))
	bu_bomb("nmg_radial_join_eu() edgeuses don't share vertices.\n");

    if (eu1->vu_p->v_p == eu1->eumate_p->vu_p->v_p) bu_bomb("nmg_radial_join_eu(): 0 length edge (topology)\n");

    if (bn_pt3_pt3_equal(eu1->vu_p->v_p->vg_p->coord,
			 eu1->eumate_p->vu_p->v_p->vg_p->coord, tol))
    {
	bu_log("vertices should have been fused:\n");
	bu_log("\tvertex %p (%.12f %.12f %.12f)\n",
	       (void *)eu1->vu_p->v_p,
	       V3ARGS(eu1->vu_p->v_p->vg_p->coord));
	bu_log("\tvertex %p (%.12f %.12f %.12f)\n",
	       (void *)eu1->eumate_p->vu_p->v_p,
	       V3ARGS(eu1->eumate_p->vu_p->v_p->vg_p->coord));
	bu_bomb("nmg_radial_join_eu(): 0 length edge (geometry)\n");
    }

#if 1
    nmg_radial_join_eu_NEW(eu1, eu2, tol);
    return;
#else

    /* Ensure faces are of same orientation, if both eu's have faces */
    fu1 = nmg_find_fu_of_eu(eu1);
    fu2 = nmg_find_fu_of_eu(eu2);
    if (fu1 && fu2) {
	if (fu1->orientation != fu2->orientation) {
	    eu2 = eu2->eumate_p;
	    fu2 = nmg_find_fu_of_eu(eu2);
	    if (fu1->orientation != fu2->orientation)
		bu_bomb("nmg_radial_join_eu(): Cannot find matching orientations for faceuses\n");
	}
    }

    /* XXX This angle-based algorithm can't handle snurb faces! */
    if (fu1 && fu1->f_p->g.magic_p && *fu1->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC) return;
    if (fu2 && fu2->f_p->g.magic_p && *fu2->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC) return;

    /* Construct local coordinate system for this edge,
     * so all angles can be measured relative to a common reference.
     */
    nmg_eu_2vecs_perp(xvec, yvec, zvec, original_eu1, tol);

    if (RTG.NMG_debug & DEBUG_MESH_EU) {
	bu_log("nmg_radial_join_eu(eu1=%p, eu2=%p) e1=%p, e2=%p\n",
	       (void *)eu1, (void *)eu2,
	       (void *)eu1->e_p, (void *)eu2->e_p);
	nmg_euprint("\tJoining", eu1);
	nmg_euprint("\t     to", eu2);
	bu_log("Faces around eu1:\n");
	nmg_pr_fu_around_eu_vecs(eu1, xvec, yvec, zvec, tol);
	bu_log("Faces around eu2:\n");
	nmg_pr_fu_around_eu_vecs(eu2, xvec, yvec, zvec, tol);
    }

    best_eg = nmg_pick_best_edge_g(eu1, eu2, tol);

    for (iteration1=0; eu2 && iteration1 < 10000; iteration1++) {
	int code = 0;
	struct edgeuse *first_eu1 = eu1;
	int wire_skip = 0;
	/* Resume where we left off from last eu2 insertion */

	/* find a place to insert eu2 around eu1's edge */
	for (iteration2=0; iteration2 < 10000; iteration2++) {
	    struct faceuse *fur;

	    abs1 = abs2 = absr = -M_2PI;

	    eur = eu1->radial_p;
	    NMG_CK_EDGEUSE(eur);

	    fu2 = nmg_find_fu_of_eu(eu2);
	    if (fu2 == (struct faceuse *)NULL) {
		/* eu2 is a wire, it can go anywhere */
		bu_log("eu2=%p is a wire, insert after eu1=%p\n", (void *)eu2, (void *)eu1);
		goto insert;
	    }
	    fu1 = nmg_find_fu_of_eu(eu1);
	    if (fu1 == (struct faceuse *)NULL) {
		/* eu1 is a wire, skip on to real face eu */
		bu_log("eu1=%p is a wire, skipping on\n", (void *)eu1);
		wire_skip++;
		goto cont;
	    }
	    fur = nmg_find_fu_of_eu(eur);
	    while (fur == (struct faceuse *)NULL) {
		/* eur is wire, advance eur */
		bu_log("eur=%p is a wire, advancing to non-wire eur\n", (void *)eur);
		eur = eur->eumate_p->radial_p;
		wire_skip++;
		if (eur == eu1->eumate_p) {
		    bu_log("went all the way around\n");
		    /* Went all the way around */
		    goto insert;
		}
		fur = nmg_find_fu_of_eu(eur);
	    }
	    NMG_CK_FACEUSE(fu1);
	    NMG_CK_FACEUSE(fu2);
	    NMG_CK_FACEUSE(fur);

	    /*
	     * Can't just check for shared fg here,
	     * the angle changes by +/- 180 degrees,
	     * depending on which side of the eu the loop is on
	     * along this edge.
	     */
	    abs1 = nmg_measure_fu_angle(eu1, xvec, yvec, zvec);
	    abs2 = nmg_measure_fu_angle(eu2, xvec, yvec, zvec);
	    absr = nmg_measure_fu_angle(eur, xvec, yvec, zvec);

	    if (RTG.NMG_debug & DEBUG_MESH_EU) {
		bu_log("  abs1=%g, abs2=%g, absr=%g\n",
		       abs1*RAD2DEG,
		       abs2*RAD2DEG,
		       absr*RAD2DEG);
	    }

	    /* If abs1 == absr, warn about unfused faces, and skip. */
	    if (NEAR_EQUAL(abs1, absr, 1.0e-8)) {
		if (fu1->f_p->g.plane_p == fur->f_p->g.plane_p) {
		    /* abs1 == absr, faces are fused, don't insert here. */
		    if (RTG.NMG_debug & DEBUG_MESH_EU) {
			bu_log("fu1 and fur share face geometry %p (flip1=%d, flip2=%d), skip\n",
			       (void *)fu1->f_p->g.plane_p, fu1->f_p->flip, fur->f_p->flip);
		    }
		    goto cont;
		}

		bu_log("nmg_radial_join_eu: WARNING 2 faces should have been fused, may be ambiguous.\n  abs1=%e, absr=%e, asb2=%e\n",
		       abs1*RAD2DEG, absr*RAD2DEG, abs2*RAD2DEG);
		bu_log("  fu1=%p, f1=%p, f1->flip=%d, fg1=%p\n",
		       (void *)fu1, (void *)fu1->f_p, fu1->f_p->flip, (void *)fu1->f_p->g.plane_p);
		bu_log("  fu2=%p, f2=%p, f2->flip=%d, fg2=%p\n",
		       (void *)fu2, (void *)fu2->f_p, fu2->f_p->flip, (void *)fu2->f_p->g.plane_p);
		bu_log("  fur=%p, fr=%p, fr->flip=%d, fgr=%p\n",
		       (void *)fur, (void *)fur->f_p, fur->f_p->flip, (void *)fur->f_p->g.plane_p);
		PLPRINT("  fu1", fu1->f_p->g.plane_p->N);
		PLPRINT("  fu2", fu2->f_p->g.plane_p->N);
		PLPRINT("  fur", fur->f_p->g.plane_p->N);
		{
		    int debug = RTG.NMG_debug;

		    if (nmg_two_face_fuse(fu1->f_p, fur->f_p, tol) == 0)
			bu_bomb("faces didn't fuse?\n");
		    RTG.NMG_debug = debug;
		}
		bu_log("  nmg_radial_join_eu() skipping this eu\n");
		goto cont;
	    }

	    /*
	     * If abs1 < abs2 < absr
	     * (taking into account 360 wrap),
	     * then insert face here.
	     * Special handling if abs1==abs2 or abs2==absr.
	     */
	    code = nmg_is_angle_in_wedge(abs1, absr, abs2);
	    if (RTG.NMG_debug & DEBUG_MESH_EU)
		bu_log("    code=%d %s\n", code, (code!=0)?"INSERT_HERE":"skip");
	    if (code > 0) break;
	    if (code == -1) {
		/* absr == abs2 */
		break;
	    }
	    if (code <= -2) {
		/* abs1 == abs2 */
		break;
	    }

	cont:
	    /* If eu1 is only one pair of edgeuses, done */
	    if (eu1 == eur->eumate_p) break;
	    eu1 = eur->eumate_p;
	    if (eu1 == first_eu1) {
		/* If all eu's were wires, here is fine */
		if (wire_skip >= iteration2) break;
		/* Nope, something bad happened */
		bu_bomb("nmg_radial_join_eu():  went full circle, no face insertion point.\n");
		break;
	    }
	}
	if (iteration2 >= 10000) {
	    bu_bomb("nmg_radial_join_eu: infinite loop (2)\n");
	}

	/* find the next use of the edge eu2 is on.  If eu2 and its
	 * mate are the last uses of the edge, there will be no next
	 * edgeuse to move. (Loop termination condition).
	 */
    insert:
	nexteu = eu2->radial_p;
	if (nexteu == eu2->eumate_p)
	    nexteu = (struct edgeuse *)NULL;

	/* because faces are always created with counter-clockwise
	 * exterior loops and clockwise interior loops,
	 * radial edgeuses IN THE SAME SHELL will never point in
	 * the same direction or share the same vertex.  We thus make
	 * sure that eu2 is an edgeuse which might be radial to eu1
	 * XXX Need to look back for last eu IN THE SHELL OF eu2.
	 * XXX Even this isn't good enough, as we may be inserting
	 * XXX something new _after_ that last starting point.
	 */
	eus = eu1;
	while (nmg_find_s_of_eu(eus) != nmg_find_s_of_eu(eu2)) {
	    eus = eus->eumate_p->radial_p;
	    if (eus == eu1) break;	/* full circle */
	}

	if (eu2->vu_p->v_p == eus->vu_p->v_p)
	    eu2 = eu2->eumate_p;

	if (RTG.NMG_debug & DEBUG_MESH_EU) {
	    bu_log("  Inserting.  code=%d\n", code);
	    bu_log("joining eu1=%p eu2=%p with abs1=%g, absr=%g\n",
		   (void *)eu1, (void *)eu2,
		   abs1*RAD2DEG, absr*RAD2DEG);
	}

	/*
	 * Make eu2 radial to eu1.
	 * This should insert eu2 between eu1 and eu1->radial_p
	 * (which may be less far around than eur, but that's OK).
	 * This does NOT change the edge geometry pointer.
	 */
	nmg_je(eu1, eu2);

	if (RTG.NMG_debug & DEBUG_MESH_EU) {
	    bu_log("After nmg_je(), faces around original_eu1 are:\n");
	    nmg_pr_fu_around_eu_vecs(original_eu1, xvec, yvec, zvec, tol);
	}

	/* Proceed to the next source edgeuse */
	eu2 = nexteu;
    }
    if (iteration1 >= 10000) bu_bomb("nmg_radial_join_eu:  infinite loop (1)\n");

    NMG_CK_EDGEUSE(original_eu1);

    /*
     * Make another pass, ensuring that all edgeuses are using the
     * "best_eg" line.
     */
    eu1 = original_eu1;
    for (;;) {
	if (eu1->g.lseg_p != best_eg) {
	    nmg_use_edge_g(eu1, &best_eg->l.magic);
	}

	eu1 = eu1->eumate_p->radial_p;
	if (eu1 == original_eu1) break;
    }

    if (RTG.NMG_debug & DEBUG_MESH_EU) bu_log("nmg_radial_join_eu: END\n");
#endif
}
示例#23
0
/*
 * 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;
}
示例#24
0
文件: g-dxf.c 项目: kanzure/brlcad
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");
    }

}