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();
	}
    }
}
示例#2
0
文件: nmg-bot.c 项目: kanzure/brlcad
static void
nmg_conv(struct rt_db_internal *intern, const char *name)
{
    struct model *m;
    struct nmgregion *r;
    struct shell *s;

    RT_CK_DB_INTERNAL(intern);
    m = (struct model *)intern->idb_ptr;
    NMG_CK_MODEL(m);
    r = BU_LIST_FIRST(nmgregion, &m->r_hd);
    if (r && BU_LIST_NEXT(nmgregion, &r->l) !=  (struct nmgregion *)&m->r_hd)
	bu_exit(1, "ERROR: this code works only for NMG models with one region!\n");

    s = BU_LIST_FIRST(shell, &r->s_hd);
    if (s && BU_LIST_NEXT(shell, &s->l) != (struct shell *)&r->s_hd)
	bu_exit(1, "ERROR: this code works only for NMG models with one shell!\n");

    if (!s) {
	bu_log("WARNING: NMG has no shells\n");
	return;
    }

    if (!BU_SETJUMP) {
	/* try */
	mk_bot_from_nmg(fdout, name, s);
    } else {
	/* catch */
	BU_UNSETJUMP;
	bu_log("Failed to convert %s\n", name);
	return;
    } BU_UNSETJUMP;

    if (verbose) bu_log("Converted %s to a Bot solid\n", name);
}
示例#3
0
文件: bottess.c 项目: kanzure/brlcad
union tree *
gcv_bottess_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data)
{
    union tree *ret_tree = TREE_NULL;
    void (*write_region)(struct nmgregion *, const struct db_full_path *, int, int, float [3]);

    if (!tsp || !curtree || !pathp || !client_data) {
	bu_log("INTERNAL ERROR: gcv_region_end missing parameters\n");
	return TREE_NULL;
    }

    write_region = ((struct gcv_data *)client_data)->func;
    if (!write_region) {
	bu_log("INTERNAL ERROR: gcv_region_end missing conversion callback function\n");
	return TREE_NULL;
    }

    RT_CK_FULL_PATH(pathp);
    RT_CK_TREE(curtree);
    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    splitz=0;
    splitty=0;

    RT_CK_FULL_PATH(pathp);
    RT_CK_TREE(curtree);
    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    if (curtree->tr_op == OP_NOP)
	return curtree;

    ret_tree = evaluate(curtree, tsp->ts_ttol, tsp->ts_tol);

    lsplitz+=splitz;
    lsplitz+=splitz;
    lsplitty+=splitty;
    splitz=0;
    splitty=0;

    return ret_tree;
}
示例#4
0
文件: superell.c 项目: kanzure/brlcad
/**
 * Tesssuperellate an superellipsoid.
 *
 * The strategy is based upon the approach of Jon Leech 3/24/89, from
 * program "sphere", which generates a polygon mesh approximating a
 * sphere by recursive subdivision. First approximation is an
 * octahedron; each level of refinement increases the number of
 * polygons by a factor of 4.  Level 3 (128 polygons) is a good
 * tradeoff if gouraud shading is used to render the database.
 *
 * At the start, points ABC lie on surface of the unit sphere.  Pick
 * DEF as the midpoints of the three edges of ABC.  Normalize the new
 * points to lie on surface of the unit sphere.
 *
 *	  1
 *	  B
 *	 /\
 *   3  /  \  4
 *   D /____\ E
 *    /\    /\
 *   /	\  /  \
 *  /____\/____\
 * A      F     C
 * 0      5     2
 *
 * Returns -
 * -1 failure
 * 0 OK.  *r points to nmgregion that holds this tesssuperellation.
 */
int
rt_superell_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol))
{
    if (r) NMG_CK_REGION(*r);
    if (m) NMG_CK_MODEL(m);
    if (ip) RT_CK_DB_INTERNAL(ip);

    bu_log("called rt_superell_tess()\n");
    return -1;
}
示例#5
0
/*
 * Call parse_args to handle command line arguments first, then
 * process input.
 */
int
main(int ac, char *av[])
{
    struct bn_tol tol;
    FILE *fdplot;
    struct rt_wdb *fdmodel;

    parse_args(ac, av);
    if (ac==1) usage((char *)NULL,0);
    if (!manifold[0] && !manifold[1] && !manifold[2] && !manifold[3])
	usage("No manifolds selected\n",1);


    m = nmg_mm();
    r = nmg_mrsv(m);
    s = BU_LIST_FIRST(shell, &r->s_hd);

    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.01;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 0.001;
    tol.para = 0.999;

    if (manifold[3]) make_3manifold_bits(&tol);
    if (manifold[2]) make_2manifold_bits(&tol);
    if (manifold[1]) make_1manifold_bits();
    if (manifold[0]) make_0manifold_bits();

    NMG_CK_MODEL(m);

    /* write a plot file */
    if ((fdplot = fopen(plotfilename, "w")) == (FILE *)NULL)
	perror(plotfilename);
    else {
	nmg_pl_m(fdplot, m);
	fclose(fdplot);
    }

    /* write the database */
    if ((fdmodel = wdb_fopen(mfilename)) == NULL)
	perror(mfilename);
    else {
	mk_id(fdmodel, "hairy NMG");
	mk_nmg(fdmodel, "s.NMG",  m); /* releases m, boo */

	/* build a database region mentioning the solid */
	mk_comb1(fdmodel, "r.NMG", "s.NMG", 1);

	wdb_close(fdmodel);
    }


    return 0;
}
示例#6
0
文件: xxx.c 项目: kanzure/brlcad
/**
 * Returns -
 * -1 failure
 * 0 OK.  *r points to nmgregion that holds this tessellation.
 */
int
rt_xxx_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol))
{
    struct rt_xxx_internal *xxx_ip;

    if (r) NMG_CK_REGION(*r);
    if (m) NMG_CK_MODEL(m);
    RT_CK_DB_INTERNAL(ip);
    xxx_ip = (struct rt_xxx_internal *)ip->idb_ptr;
    RT_XXX_CK_MAGIC(xxx_ip);

    return -1;
}
示例#7
0
文件: nmg_copy.c 项目: kanzure/brlcad
/**
 * Makes a deep copy of a NMG model structure.
 */
struct model *
nmg_clone_model(const struct model *original)
{
    struct model           *ret;
    void *              *structArray;
    const struct nmgregion *originalRegion;
    struct bn_tol           tolerance;

    NMG_CK_MODEL(original);

    structArray = (void **)bu_calloc(original->maxindex, sizeof(void *), "nmg_clone_model() structArray");

    ret = nmg_mm();
    ret->index    = original->index;
    ret->maxindex = original->maxindex;

    structArray[ret->index] = ret;

    tolerance.magic   = BN_TOL_MAGIC;
    tolerance.dist    = 0.0005;
    tolerance.dist_sq = tolerance.dist * tolerance.dist;
    tolerance.perp    = 1e-6;
    tolerance.para    = 1 - tolerance.perp;

    for (BU_LIST_FOR(originalRegion, nmgregion, &original->r_hd)) {
	struct nmgregion *newRegion = (struct nmgregion *)structArray[originalRegion->index];

	if (newRegion == NULL) {
	    const struct shell *originalShell;

	    newRegion = nmg_construct_region(ret, originalRegion, structArray);

	    for (BU_LIST_FOR(originalShell, shell, &originalRegion->s_hd)) {
		struct shell *newShell = (struct shell *)structArray[originalShell->index];

		if (newShell == NULL)
		    newShell = nmg_construct_shell(newRegion, originalShell, structArray);

		BU_LIST_INSERT(&newRegion->s_hd, &newShell->l);
	    }

	    BU_LIST_INSERT(&ret->r_hd, &newRegion->l);
	}
    }

    bu_free(structArray, "nmg_clone_model() structArray");

    return ret;
}
void
nmg_visit_model(struct model *model, const struct nmg_visit_handlers *htab, void *state)


/* Handler's private state */
{
    struct nmgregion *r;

    NMG_CK_MODEL(model);

    if (htab->bef_model) htab->bef_model((uint32_t *)model, state, 0);

    for (BU_LIST_FOR(r, nmgregion, &model->r_hd)) {
	nmg_visit_region(r, htab, state);
    }

    if (htab->aft_model) htab->aft_model((uint32_t *)model, state, 1);
}
示例#9
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" );
		}
	    }
	}
    }
/*
 * Called from db_walk_tree().
 *
 * This routine must be prepared to run in parallel.
 */
union tree *
do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data))
{
    union tree *ret_tree = NULL;
    struct bu_list vhead;
    /* static due to longjmp */
    static struct nmgregion *r = NULL;

    RT_CK_FULL_PATH(pathp);
    RT_CK_TREE(curtree);
    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char *sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_converted * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    regions_tried++;

    /* do the deed */
    ret_tree = process_region(pathp, curtree, tsp);

    if (ret_tree)
	r = ret_tree->tr_d.td_r;
    else {
	if (verbose) {
	    printf("\tNothing left of this region after Boolean evaluation\n");
	    fprintf(fpe, "WARNING: Nothing left after Boolean evaluation: %s\n",
		    db_path_to_string(pathp));
	    fflush(fpe);
	}
	regions_written++; /* don't count as a failure */
	r = (struct nmgregion *)NULL;
    }

    regions_converted++;

    if (r != (struct nmgregion *)NULL) {
	struct shell *s;
	int empty_region=0;
	int empty_model=0;

	/* Kill cracks */
	s = BU_LIST_FIRST(shell, &r->s_hd);
	while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) {
	    struct shell *next_s;

	    next_s = BU_LIST_PNEXT(shell, &s->l);
	    if (nmg_kill_cracks(s)) {
		if (nmg_ks(s)) {
		    empty_region = 1;
		    break;
		}
	    }
	    s = next_s;
	}

	/* kill zero length edgeuses */
	if (!empty_region) {
	    empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m);
	}

	if (!empty_region && !empty_model) {
	    if (!BU_SETJUMP) {
		/* try */

		/* Write the region to the TANKILL file */
		nmg_to_acad(r, pathp, tsp->ts_regionid);
		regions_written++;

	    } else {
		/* catch */

		char *sofar;

		BU_UNSETJUMP;

		sofar = db_path_to_string(pathp);
		bu_free((char *)sofar, "sofar");

		/* Sometimes the NMG library adds debugging bits when
		 * it detects an internal error, before bombing out.
		 */
		RTG.NMG_debug = NMG_debug;	/* restore mode */

		/* Release any intersector 2d tables */
		nmg_isect2d_final_cleanup();

		/* Get rid of (m)any other intermediate structures */
		if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) {
		    nmg_km(*tsp->ts_m);
		} else {
		    bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n");
		}

		/* Now, make a new, clean model structure for next pass. */
		*tsp->ts_m = nmg_mm();

		/* FIXME: leaking memory with curtree */

		return TREE_NULL;
	    } BU_UNSETJUMP;
	}

	if (!empty_model)
	    nmg_kr(r);
    }

    /*
     * Dispose of original tree, so that all associated dynamic
     * memory is released now, not at the end of all regions.
     * A return of TREE_NULL from this routine signals an error,
     * and there is no point to adding _another_ message to our output,
     * so we need to cons up an OP_NOP node to return.
     */

    if (regions_tried>0) {
	float npercent, tpercent;

	npercent = (float)(regions_converted * 100) / regions_tried;
	tpercent = (float)(regions_written * 100) / regions_tried;
	printf("Tried %d regions, %d conv. to NMG's %d conv. to tri. nmgper = %.2f%% triper = %.2f%% \n",
	       regions_tried, regions_converted, regions_written, npercent, tpercent);
    }

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;

    return curtree;
}
示例#11
0
int
main(int argc, char **argv) 			/* really has no arguments */

{
    struct nmgregion *r;
    char * id_name = "BRL-CAD t-NURBS NMG Example";
    char * tea_name = "UtahTeapot";
    char * uplot_name = "teapot.pl";
    struct bu_list vhead;
    FILE *fp;
    int i;

    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;

    BU_LIST_INIT( &rt_g.rtg_vlfree );

    outfp = wdb_fopen( "tea_nmg.g" );

    rt_g.debug |= DEBUG_ALLRAYS;	/* Cause core dumps on bu_bomb(), but no extra messages */

    while ((i=bu_getopt(argc, argv, "d")) != EOF) {
        switch (i) {
        case 'd' :
            rt_g.debug |= DEBUG_MEM | DEBUG_MEM_FULL;
            break;
        default	:
            (void)fprintf(stderr,
                          "Usage: %s [-d] > database.g\n", *argv);
            return(-1);
        }
    }

    mk_id( outfp, id_name);

    m = nmg_mm();
    NMG_CK_MODEL( m );
    r = nmg_mrsv( m );
    NMG_CK_REGION( r );
    s = BU_LIST_FIRST( shell, &r->s_hd );
    NMG_CK_SHELL( s );

    /* Step through each patch and create a NMG TNURB face
     * representing the patch then dump them out.
     */

    for ( i = 0; i < PATCH_COUNT; i++)
    {
        dump_patch( patches[i] );
    }

    /* Connect up the coincident vertexuses and edges */
    (void)nmg_model_fuse( m, &tol );

    /* write NMG to output file */
    (void)mk_nmg( outfp, tea_name, m );
    wdb_close(outfp);

    /* Make a vlist drawing of the model */
    BU_LIST_INIT( &vhead );
    nmg_m_to_vlist( &vhead, m, 0 );

    /* Make a UNIX plot file from this vlist */
    if ( (fp=fopen( uplot_name, "w" )) == NULL )
    {
        bu_log( "Cannot open plot file: %s\n", uplot_name );
        perror( "teapot_nmg" );
    }
    else
        rt_vlist_to_uplot( fp, &vhead );

    return(0);
}
示例#12
0
文件: g-off.c 项目: cogitokat/brlcad
/*
 *			D O _ R E G I O N _ E N D
 *
 *  Called from db_walk_tree().
 *
 *  This routine must be prepared to run in parallel.
 */
union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, genptr_t UNUSED(client_data))
{
    union tree		*ret_tree;
    struct nmgregion	*r;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char	*sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_done * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    regions_tried++;

    ret_tree = process_boolean(curtree, tsp, pathp);

    if ( ret_tree )
	r = ret_tree->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;

    regions_done++;

    if (r != 0) {
	FILE	*fp_psurf;
	size_t	i;
	struct bu_vls	file_base = BU_VLS_INIT_ZERO;
	struct bu_vls	file = BU_VLS_INIT_ZERO;

	bu_vls_strcpy(&file_base, prefix);
	bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
	/* Dots confuse Jack's Peabody language.  Change to '_'. */
	for (i = 0; i < file_base.vls_len; i++)
	    if (file_base.vls_str[i] == '.')
		file_base.vls_str[i] = '_';

	/* Write color attribute to .fig figure file. */
	if (tsp->ts_mater.ma_color_valid != 0) {
	    fprintf(fp_fig, "\tattribute %s {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n",
		    V3ARGS(tsp->ts_mater.ma_color));
	    fprintf(fp_fig, "\t\tambient = 0.18;\n");
	    fprintf(fp_fig, "\t\tdiffuse = 0.72;\n");
	    fprintf(fp_fig, "\t}\n");
	}

	/* Write segment attributes to .fig figure file. */
	fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base));
	if (tsp->ts_mater.ma_color_valid != 0)
	    fprintf(fp_fig,
		    "\t\tattribute=%s;\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n");
	fprintf(fp_fig, "\t}\n");

	if ( bu_vls_strlen(&base_seg) <= 0 )  {
	    bu_vls_vlscat( &base_seg, &file_base );
	} else {
	    fprintf(fp_fig, "\tjoint %s_jt {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig,
		    "\t\tconnect %s_seg.base to %s_seg.base;\n",
		    bu_vls_addr(&file_base),
		    bu_vls_addr(&base_seg) );
	    fprintf(fp_fig, "\t}\n");
	}

	bu_vls_vlscat(&file, &file_base);
	bu_vls_strcat(&file, ".pss");	/* Required Jack suffix. */

	/* Write psurf to .pss file. */
	if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL)
	    perror(bu_vls_addr(&file));
	else {
	    nmg_to_psurf(r, fp_psurf);
	    fclose(fp_psurf);
	    if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	}
	bu_vls_free(&file);

	/* Also write as UNIX-plot file, if desired */
	if ( debug_plots )  {
	    FILE	*fp;
	    bu_vls_vlscat(&file, &file_base);
	    bu_vls_strcat(&file, ".pl");

	    if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL)
		perror(bu_vls_addr(&file));
	    else {
		struct bu_list	vhead;
		pl_color( fp,
			  (int)(tsp->ts_mater.ma_color[0] * 255),
			  (int)(tsp->ts_mater.ma_color[1] * 255),
			  (int)(tsp->ts_mater.ma_color[2] * 255) );
		/* nmg_pl_r( fp, r ); */
		BU_LIST_INIT( &vhead );
		nmg_r_to_vlist( &vhead, r, 0 );
		rt_vlist_to_uplot( fp, &vhead );
		fclose(fp);
		if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	    }
	    bu_vls_free(&file);
	}

	/* NMG region is no longer necessary */
	nmg_kr(r);
    }

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;
    return curtree;
}
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;
}
union tree *
nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data))
{
    struct nmgregion	*r;
    struct bu_list		vhead;
    union tree		*ret_tree;
    char			*name;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BARRIER_CHECK;
    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	bu_log("\nConverted %d%% so far (%d of %d)\n",
	       regions_tried>0 ? (regions_converted * 100) / regions_tried : 0,
	       regions_converted, regions_tried );
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    name = db_path_to_string( pathp );
    bu_log( "Attempting %s\n", name );

    regions_tried++;

    ret_tree = process_boolean(curtree, tsp, pathp);

    if ( ret_tree )
	r = ret_tree->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;

    bu_free( name, "db_path_to_string" );
    regions_converted++;
    if (r != (struct nmgregion *)NULL)
    {
	struct shell *s;
	int empty_region=0;
	int empty_model=0;

	/* Kill cracks */
	s = BU_LIST_FIRST( shell, &r->s_hd );
	while ( BU_LIST_NOT_HEAD( &s->l, &r->s_hd ) )
	{
	    struct shell *next_s;

	    next_s = BU_LIST_PNEXT( shell, &s->l );
	    if ( nmg_kill_cracks( s ) )
	    {
		if ( nmg_ks( s ) )
		{
		    empty_region = 1;
		    break;
		}
	    }
	    s = next_s;
	}

	/* kill zero length edgeuses */
	if ( !empty_region )
	{
	    empty_model = nmg_kill_zero_length_edgeuses( *tsp->ts_m );
	}

	if ( !empty_region && !empty_model )
	{
	    /* Write the nmgregion to the output file */
	    nmg_2_vrml( outfp, pathp, r->m_p, &tsp->ts_mater );
	}

	/* NMG region is no longer necessary */
	if ( !empty_model )
	    nmg_kr(r);

    }
    else
	bu_log( "WARNING: Nothing left after Boolean evaluation of %s\n",
		db_path_to_string( pathp ) );

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;
    BARRIER_CHECK;
    return curtree;
}
/**
 * This routine must be prepared to run in parallel.
 */
static union tree *
draw_nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data)
{
    struct nmgregion *r;
    struct bu_list vhead;
    int failed;
    struct _ged_client_data *dgcdp = (struct _ged_client_data *)client_data;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);
    RT_CK_RESOURCE(tsp->ts_resp);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK) {
	char *sofar = db_path_to_string(pathp);

	bu_vls_printf(dgcdp->gedp->ged_result_str, "nmg_region_end() path='%s'\n", sofar);
	bu_free((void *)sofar, "path string");
    } else {
	char *sofar = db_path_to_string(pathp);

	bu_vls_printf(dgcdp->gedp->ged_result_str, "%s:\n", sofar);
	bu_free((void *)sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP) return curtree;

    failed = 1;
    if (!dgcdp->draw_nmg_only) {

	failed = process_boolean(curtree, tsp, pathp, dgcdp);
	if (failed) {
	    db_free_tree(curtree, tsp->ts_resp);
	    return (union tree *)NULL;
	}

    } else if (curtree->tr_op != OP_NMG_TESS) {
	bu_vls_printf(dgcdp->gedp->ged_result_str, "Cannot use '-d' option when Boolean evaluation is required\n");
	db_free_tree(curtree, tsp->ts_resp);
	return (union tree *)NULL;
    }
    r = curtree->tr_d.td_r;
    NMG_CK_REGION(r);

    if (dgcdp->do_not_draw_nmg_solids_during_debugging && r) {
	db_free_tree(curtree, tsp->ts_resp);
	return (union tree *)NULL;
    }

    if (dgcdp->nmg_triangulate) {
	failed = process_triangulation(tsp, pathp, dgcdp);
	if (failed) {
	    db_free_tree(curtree, tsp->ts_resp);
	    return (union tree *)NULL;
	}
    }

    if (r != 0) {
	int style;
	/* Convert NMG to vlist */
	NMG_CK_REGION(r);

	if (dgcdp->draw_wireframes) {
	    /* Draw in vector form */
	    style = NMG_VLIST_STYLE_VECTOR;
	} else {
	    /* Default -- draw polygons */
	    style = NMG_VLIST_STYLE_POLYGON;
	}
	if (dgcdp->draw_normals) {
	    style |= NMG_VLIST_STYLE_VISUALIZE_NORMALS;
	}
	if (dgcdp->shade_per_vertex_normals) {
	    style |= NMG_VLIST_STYLE_USE_VU_NORMALS;
	}
	if (dgcdp->draw_no_surfaces) {
	    style |= NMG_VLIST_STYLE_NO_SURFACES;
	}
	nmg_r_to_vlist(&vhead, r, style);

	_ged_drawH_part2(0, &vhead, pathp, tsp, dgcdp);

	if (dgcdp->draw_edge_uses) {
	    nmg_vlblock_r(dgcdp->draw_edge_uses_vbp, r, 1);
	}
	/* NMG region is no longer necessary, only vlist remains */
	db_free_tree(curtree, tsp->ts_resp);
	return (union tree *)NULL;
    }

    /* Return tree -- it needs to be freed (by caller) */
    return curtree;
}
示例#16
0
/*
 *  Called from db_walk_tree().
 *
 *  This routine must be prepared to run in parallel.
 */
union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data))
{
    union tree		*ret_tree;
    struct bu_list		vhead;
    struct nmgregion	*r;

    RT_CK_FULL_PATH(pathp);
    RT_CK_TREE(curtree);
    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    {
	char	*sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_converted * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    regions_tried++;

    if (verbose)
	bu_log("Attempting to process region %s\n", db_path_to_string(pathp));

    ret_tree= process_boolean(curtree, tsp, pathp);

    if (ret_tree)
	r = ret_tree->tr_d.td_r;
    else
    {
	if (verbose)
	    bu_log("\tNothing left of this region after Boolean evaluation\n");
	regions_written++; /* don't count as a failure */
	r = (struct nmgregion *)NULL;
    }

    regions_converted++;

    if (r != (struct nmgregion *)NULL)
    {
	struct shell *s;
	int empty_region=0;
	int empty_model=0;

	/* Kill cracks */
	s = BU_LIST_FIRST(shell, &r->s_hd);
	while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd))
	{
	    struct shell *next_s;

	    next_s = BU_LIST_PNEXT(shell, &s->l);
	    if (nmg_kill_cracks(s))
	    {
		if (nmg_ks(s))
		{
		    empty_region = 1;
		    break;
		}
	    }
	    s = next_s;
	}

	/* kill zero length edgeuses */
	if (!empty_region) {
	    empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m);
	}

	if (!empty_region && !empty_model) {
	    process_triangulation(r, pathp, tsp);

	    regions_written++;
	}

	if (!empty_model)
	    nmg_kr(r);
    }

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  and there is no point to adding _another_ message to our output,
     *  so we need to cons up an OP_NOP node to return.
     */


    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;
    return curtree;
}
示例#17
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[]");
}
示例#18
0
文件: g-off.c 项目: cciechad/brlcad
/*
 *			D O _ R E G I O N _ E N D
 *
 *  Called from db_walk_tree().
 *
 *  This routine must be prepared to run in parallel.
 */
union tree *do_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
{
    union tree		*ret_tree;
    struct nmgregion	*r;
    struct bu_list		vhead;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char	*sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_done * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return  curtree;

    regions_tried++;

    /* Begin bomb protection */
    if ( ncpu == 1 ) {
	if ( BU_SETJUMP )  {
	    /* Error, bail out */
	    BU_UNSETJUMP;		/* Relinquish the protection */

	    /* Sometimes the NMG library adds debugging bits when
	     * it detects an internal error, before bombing out.
	     */
	    rt_g.NMG_debug = NMG_debug;	/* restore mode */

	    /* Release the tree memory & input regions */
	    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

	    /* Get rid of (m)any other intermediate structures */
	    if ( (*tsp->ts_m)->magic != -1L )
		nmg_km(*tsp->ts_m);

	    /* Now, make a new, clean model structure for next pass. */
	    *tsp->ts_m = nmg_mm();
	    goto out;
	}
    }
    (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol);
    ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource);	/* librt/nmg_bool.c */
    BU_UNSETJUMP;		/* Relinquish the protection */
    if ( ret_tree )
	r = ret_tree->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;
    regions_done++;
    if (r != 0) {
	FILE	*fp_psurf;
	int	i;
	struct bu_vls	file_base;
	struct bu_vls	file;

	bu_vls_init(&file_base);
	bu_vls_init(&file);
	bu_vls_strcpy(&file_base, prefix);
	bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
	/* Dots confuse Jack's Peabody language.  Change to '_'. */
	for (i = 0; i < file_base.vls_len; i++)
	    if (file_base.vls_str[i] == '.')
		file_base.vls_str[i] = '_';

	/* Write color attribute to .fig figure file. */
	if (tsp->ts_mater.ma_color_valid != 0) {
	    fprintf(fp_fig, "\tattribute %s {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n",
		    V3ARGS(tsp->ts_mater.ma_color));
	    fprintf(fp_fig, "\t\tambient = 0.18;\n");
	    fprintf(fp_fig, "\t\tdiffuse = 0.72;\n");
	    fprintf(fp_fig, "\t}\n");
	}

	/* Write segment attributes to .fig figure file. */
	fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base));
	if (tsp->ts_mater.ma_color_valid != 0)
	    fprintf(fp_fig,
		    "\t\tattribute=%s;\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n");
	fprintf(fp_fig, "\t}\n");

	if ( bu_vls_strlen(&base_seg) <= 0 )  {
	    bu_vls_vlscat( &base_seg, &file_base );
	} else {
	    fprintf(fp_fig, "\tjoint %s_jt {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig,
		    "\t\tconnect %s_seg.base to %s_seg.base;\n",
		    bu_vls_addr(&file_base),
		    bu_vls_addr(&base_seg) );
	    fprintf(fp_fig, "\t}\n");
	}

	bu_vls_vlscat(&file, &file_base);
	bu_vls_strcat(&file, ".pss");	/* Required Jack suffix. */

	/* Write psurf to .pss file. */
	if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL)
	    perror(bu_vls_addr(&file));
	else {
	    nmg_to_psurf(r, fp_psurf);
	    fclose(fp_psurf);
	    if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	}
	bu_vls_free(&file);

	/* Also write as UNIX-plot file, if desired */
	if ( debug_plots )  {
	    FILE	*fp;
	    bu_vls_vlscat(&file, &file_base);
	    bu_vls_strcat(&file, ".pl");

	    if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL)
		perror(bu_vls_addr(&file));
	    else {
		struct bu_list	vhead;
		pl_color( fp,
			  (int)(tsp->ts_mater.ma_color[0] * 255),
			  (int)(tsp->ts_mater.ma_color[1] * 255),
			  (int)(tsp->ts_mater.ma_color[2] * 255) );
		/* nmg_pl_r( fp, r ); */
		BU_LIST_INIT( &vhead );
		nmg_r_to_vlist( &vhead, r, 0 );
		rt_vlist_to_uplot( fp, &vhead );
		fclose(fp);
		if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	    }
	    bu_vls_free(&file);
	}

	/* NMG region is no longer necessary */
	nmg_kr(r);
    }

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

 out:
    BU_GETUNION(curtree, tree);
    curtree->magic = RT_TREE_MAGIC;
    curtree->tr_op = OP_NOP;
    return(curtree);
}
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");
}
示例#20
0
文件: g-iges.c 项目: kanzure/brlcad
/*
 * Called from db_walk_tree().
 *
 * This routine must be prepared to run in parallel.
 */
union tree *
do_nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data))
{
    union tree *result;
    struct nmgregion *r;
    struct bu_list vhead;
    struct directory *dp;
    int dependent;
    size_t i;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char *sofar = db_path_to_string(pathp);
	bu_log("\ndo_nmg_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_done * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    regions_tried++;

    if (verbose)
	bu_log("\ndoing boolean tree evaluate...\n");

    /* evaluate the boolean */
    result = process_boolean(tsp, curtree, pathp);

    if (result)
	r = result->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;

    if (verbose)
	bu_log("\nfinished boolean tree evaluate...\n");

    regions_done++;
    if (r != NULL) {

	dp = DB_FULL_PATH_CUR_DIR(pathp);

	if (multi_file) {
	    /* Open the output file */
	    if (output_file == NULL)
		fp_dir = stdout;
	    else {
		char *multi_name;
		size_t len;
		int unique = 0;
		char suffix[SUFFIX_LEN+1];

		/* construct a unique file name */
		len = strlen(output_file) + strlen(dp->d_namep) + 6 + SUFFIX_LEN;
		multi_name = (char *)bu_malloc(sizeof(char)*len, "multi_name");
		snprintf(multi_name, len, "%s/%s.igs", output_file, dp->d_namep);
		bu_strlcpy(suffix, "a", sizeof(suffix));
		suffix[0]--;
		while (!unique) {
		    if (bu_file_readable(multi_name)) {
			unique = 1;
			break;
		    }

		    /* not unique, try adding a suffix */
		    len = strlen(suffix);
		    i = len - 1;
		    suffix[i]++;
		    while (suffix[i] > 'z' && i > 0) {
			suffix[i] = 'a';
			i--;
			suffix[i]++;
		    }

		    if (suffix[0] > 'z' && len < SUFFIX_LEN) {
			for (i = 0; i <= len; i++)
			    suffix[i] = 'a';
		    } else if (suffix[0] > 'z' && len >= SUFFIX_LEN) {
			bu_log("too many files with the same name (%s)\n", dp->d_namep);
			bu_exit(1, "Cannot create a unique filename, \n");
		    }
		    snprintf(multi_name, len, "%s/%s%s.igs", output_file, dp->d_namep, suffix);
		}
		if ((fp_dir = fopen(multi_name, "wb")) == NULL) {
		    perror("g-iges");
		    bu_exit(1, "Cannot open output file: %s\n", multi_name);
		}
	    }

	    /* Open the temporary file for the parameter section */
	    if ((fp_param = bu_temp_file(NULL, 0)) == NULL) {
		perror("g-iges");
		bu_exit(1, "Cannot open temporary file\n");
	    }

	    /* let the IGES routines know the selected tolerances and the database pointer */
	    iges_init(&tol, &ttol, verbose, DBIP);

	    /* Write start and global sections of the IGES file */
	    w_start_global(fp_dir, fp_param, db_name, prog_name, output_file, __DATE__, brlcad_version());
	}

	if (mode == FACET_MODE) {
	    dependent = 1;
	    for (i = 0; i < no_of_indeps; i++) {
		if (!bu_strncmp(dp->d_namep, independent[i], NAMESIZE+1)) {
		    dependent = 0;
		    break;
		}
	    }

	    dp->d_uses = (-nmgregion_to_iges(dp->d_namep, r, dependent, fp_dir, fp_param));
	} else if (mode == TRIMMED_SURF_MODE)
	    dp->d_uses = (-nmgregion_to_tsurf(dp->d_namep, r, fp_dir, fp_param));

	/* NMG region is no longer necessary */
	nmg_kr(r);

	if (multi_file) {
	    char copy_buffer[CP_BUF_SIZE] = {0};

	    /* Copy the parameter section from the temporary file to the output file */
	    if ((bu_fseek(fp_param, 0, 0))) {
		perror("g-iges");
		bu_exit(1, "Cannot seek to start of temporary file\n");
	    }

	    while ((i = fread(copy_buffer, 1, CP_BUF_SIZE, fp_param)))
		if (fwrite(copy_buffer, 1, i, fp_dir) != i) {
		    perror("g-iges");
		    bu_exit(1, "Error in copying parameter data to %s\n", output_file);
		}

	    /* Write the terminate section */
	    w_terminate(fp_dir);
	    fclose(fp_dir);
	    fclose(fp_param);
	}
    }

    /*
     * Dispose of original tree, so that all associated dynamic
     * memory is released now, not at the end of all regions.
     * A return of TREE_NULL from this routine signals an error,
     * so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;
    return curtree;
}
示例#21
0
union tree *
gcv_region_end_mc(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data)
{
    union tree *tp = NULL;
    struct model *m = NULL;
    struct nmgregion *r = NULL;
    struct shell *s = NULL;
    struct bu_list vhead;

    int empty_region = 0;
    int empty_model = 0;
    int NMG_debug_state = 0;
    int count = 0;

    void (*write_region)(struct nmgregion *, const struct db_full_path *, int, int, float [3]);

    if (!tsp || !pathp || !client_data) {
	bu_log("INTERNAL ERROR: gcv_region_end_mc missing parameters\n");
	return TREE_NULL;
    }

    write_region = ((struct gcv_data *)client_data)->func;
    if (!write_region) {
	bu_log("INTERNAL ERROR: gcv_region_end missing conversion callback function\n");
	return TREE_NULL;
    }

    RT_CK_FULL_PATH(pathp);
    RT_CK_TREE(curtree);
    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    /*
      if (curtree->tr_op == OP_NOP)
      return 0;
    */


    /* get a copy to play with as the parameters might get clobbered
     * by a longjmp.  FIXME: db_dup_subtree() doesn't create real copies
     */
    tp = db_dup_subtree(curtree, &rt_uniresource);

    /* FIXME: we can't free curtree until we get a "real" copy form
     * db_dup_subtree().  right now we get a fake copy just so we can
     * keep the compiler quiet about clobbering curtree during longjmp
     */
    /* db_free_tree(curtree, &rt_uniresource); */

    /* Sometimes the NMG library adds debugging bits when it detects
     * an internal error, before bombing.  Stash.
     */
    NMG_debug_state = RTG.NMG_debug;

    m = nmg_mmr();
    r = nmg_mrsv(m);
    s = BU_LIST_FIRST(shell, &r->s_hd);

    if (tsp->ts_rtip == NULL)
	tsp->ts_rtip = rt_new_rti(tsp->ts_dbip);

    count += nmg_mc_evaluate (s, tsp->ts_rtip, pathp, tsp->ts_ttol, tsp->ts_tol);

    /* empty region? */
    if (count == 0) {
	bu_log("Region %s appears to be empty.\n", db_path_to_string(pathp));
	return TREE_NULL;
    }

    /*
      bu_log("Target is shot, %d triangles seen.\n", count);

      bu_log("Fusing\n"); fflush(stdout);
      nmg_model_fuse(m, tsp->ts_tol);
      bu_log("Done\n"); fflush(stdout);
    */

    /* Kill cracks */
    while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) {
	struct shell *next_s;

	next_s = BU_LIST_PNEXT(shell, &s->l);
	if (nmg_kill_cracks(s)) {
	    if (nmg_ks(s)) {
		empty_region = 1;
		break;
	    }
	}
	/*
	  nmg_shell_coplanar_face_merge(s, tsp->ts_tol, 42);
	*/
	s = next_s;
    }
    if (empty_region)
	return _gcv_cleanup(NMG_debug_state, tp);

    /* kill zero length edgeuses */
    empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m);
    if (empty_model)
	return _gcv_cleanup(NMG_debug_state, tp);

    if (BU_SETJUMP) {
	/* Error, bail out */
	char *sofar;

	/* Relinquish bomb protection */
	BU_UNSETJUMP;

	sofar = db_path_to_string(pathp);
	bu_log("FAILED in triangulator: %s\n", sofar);
	bu_free((char *)sofar, "sofar");

	/* Release any intersector 2d tables */
	nmg_isect2d_final_cleanup();

	/* Get rid of (m)any other intermediate structures */
	if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC)
	    nmg_km(*tsp->ts_m);
	else
	    bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n");

	/* Now, make a new, clean model structure for next pass. */
	*tsp->ts_m = nmg_mm();
	nmg_kr(r);

	return _gcv_cleanup(NMG_debug_state, tp);
    } else {
	/* Write the region out */
	write_region(r, pathp, tsp->ts_regionid, tsp->ts_gmater, tsp->ts_mater.ma_color);

    } BU_UNSETJUMP; /* Relinquish bomb protection */

    nmg_kr(r);

    return _gcv_cleanup(NMG_debug_state, tp);
}
示例#22
0
int
ged_nmg_collapse(struct ged *gedp, int argc, const char *argv[])
{
    char *new_name;
    struct model *m;
    struct rt_db_internal intern;
    struct directory *dp;
    struct bu_ptbl faces;
    struct face *fp;
    size_t count;
    fastf_t tol_coll;
    fastf_t min_angle;
    static const char *usage = "nmg_prim new_prim max_err_dist [min_angle]";

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_READ_ONLY(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_HELP;
    }

    if (argc < 4) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    if (strchr(argv[2], '/')) {
	bu_vls_printf(gedp->ged_result_str, "Do not use '/' in solid names: %s\n", argv[2]);
	return GED_ERROR;
    }

    new_name = (char *)argv[2];

    if (db_lookup(gedp->ged_wdbp->dbip, new_name, LOOKUP_QUIET) != RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "%s already exists\n", new_name);
	return GED_ERROR;
    }

    if ((dp=db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_NOISY)) == RT_DIR_NULL)
	return GED_ERROR;

    if (dp->d_flags & RT_DIR_COMB) {
	bu_vls_printf(gedp->ged_result_str, "%s is a combination, only NMG primitives are allowed here\n", argv[1]);
	return GED_ERROR;
    }

    if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (matp_t)NULL, &rt_uniresource) < 0) {
	bu_vls_printf(gedp->ged_result_str, "Failed to get internal form of %s!!!!\n", argv[1]);
	return GED_ERROR;
    }

    if (intern.idb_type != ID_NMG) {
	bu_vls_printf(gedp->ged_result_str, "%s is not an NMG solid!!!!\n", argv[1]);
	rt_db_free_internal(&intern);
	return GED_ERROR;
    }

    tol_coll = atof(argv[3]) * gedp->ged_wdbp->dbip->dbi_local2base;
    if (tol_coll <= 0.0) {
	bu_vls_printf(gedp->ged_result_str, "tolerance distance too small\n");
	return GED_ERROR;
    }

    if (argc == 5) {
	min_angle = atof(argv[4]);
	if (min_angle < 0.0) {
	    bu_vls_printf(gedp->ged_result_str, "Minimum angle cannot be less than zero\n");
	    return GED_ERROR;
	}
    } else
	min_angle = 0.0;

    m = (struct model *)intern.idb_ptr;
    NMG_CK_MODEL(m);

    /* check that all faces are planar */
    nmg_face_tabulate(&faces, &m->magic);
    for (BU_PTBL_FOR(fp, (struct face *), &faces)) {
	if (fp->g.magic_p != NULL && *(fp->g.magic_p) != NMG_FACE_G_PLANE_MAGIC) {
	    bu_log("\tnot planar\n");
	    bu_ptbl_free(&faces);
	    bu_vls_printf(gedp->ged_result_str,
			  "nmg_collapse can only be applied to NMG primitives with planar faces\n");
	    return GED_ERROR;
	}
    }
    bu_ptbl_free(&faces);

    /* triangulate model */
    nmg_triangulate_model(m, &gedp->ged_wdbp->wdb_tol);

    count = (size_t)nmg_edge_collapse(m, &gedp->ged_wdbp->wdb_tol, tol_coll, min_angle);

    dp=db_diradd(gedp->ged_wdbp->dbip, new_name, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type);
    if (dp == RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", new_name);
	rt_db_free_internal(&intern);
	return GED_ERROR;
    }

    if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) {
	rt_db_free_internal(&intern);
	bu_vls_printf(gedp->ged_result_str, "Database write error, aborting.\n");
	return GED_ERROR;
    }

    rt_db_free_internal(&intern);

    bu_vls_printf(gedp->ged_result_str, "%zu edges collapsed\n", count);

    return GED_OK;
}
static void
nmg_to_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");
}
示例#24
0
文件: shells.c 项目: kanzure/brlcad
int
ged_shells(struct ged *gedp, int argc, const char *argv[])
{
    struct directory *old_dp, *new_dp;
    struct rt_db_internal old_intern, new_intern;
    struct model *m_tmp, *m;
    struct nmgregion *r_tmp, *r;
    struct shell *s_tmp, *s;
    int shell_count=0;
    struct bu_vls shell_name = BU_VLS_INIT_ZERO;
    long **trans_tbl;
    static const char *usage = "nmg_model";

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_READ_ONLY(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_HELP;
    }

    if (argc != 2) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    if ((old_dp = db_lookup(gedp->ged_wdbp->dbip,  argv[1], LOOKUP_NOISY)) == RT_DIR_NULL)
	return GED_ERROR;

    if (rt_db_get_internal(&old_intern, old_dp, gedp->ged_wdbp->dbip, bn_mat_identity, &rt_uniresource) < 0) {
	bu_vls_printf(gedp->ged_result_str, "rt_db_get_internal() error\n");
	return GED_ERROR;
    }

    if (old_intern.idb_type != ID_NMG) {
	bu_vls_printf(gedp->ged_result_str, "Object is not an NMG!!!\n");
	return GED_ERROR;
    }

    m = (struct model *)old_intern.idb_ptr;
    NMG_CK_MODEL(m);

    for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
	for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	    s_tmp = nmg_dup_shell(s, &trans_tbl, &gedp->ged_wdbp->wdb_tol);
	    bu_free((void *)trans_tbl, "trans_tbl");

	    m_tmp = nmg_mmr();
	    r_tmp = BU_LIST_FIRST(nmgregion, &m_tmp->r_hd);

	    BU_LIST_DEQUEUE(&s_tmp->l);
	    BU_LIST_APPEND(&r_tmp->s_hd, &s_tmp->l);
	    s_tmp->r_p = r_tmp;
	    nmg_m_reindex(m_tmp, 0);
	    nmg_m_reindex(m, 0);

	    bu_vls_printf(&shell_name, "shell.%d", shell_count);
	    while (db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), 0) != RT_DIR_NULL) {
		bu_vls_trunc(&shell_name, 0);
		shell_count++;
		bu_vls_printf(&shell_name, "shell.%d", shell_count);
	    }

	    /* Export NMG as a new solid */
	    RT_DB_INTERNAL_INIT(&new_intern);
	    new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	    new_intern.idb_type = ID_NMG;
	    new_intern.idb_meth = &OBJ[ID_NMG];
	    new_intern.idb_ptr = (void *)m_tmp;

	    new_dp=db_diradd(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&new_intern.idb_type);
	    if (new_dp == RT_DIR_NULL) {
		bu_vls_printf(gedp->ged_result_str, "An error has occurred while adding a new object to the database.\n");
		return GED_ERROR;
	    }

	    /* make sure the geometry/bounding boxes are up to date */
	    nmg_rebound(m_tmp, &gedp->ged_wdbp->wdb_tol);

	    if (rt_db_put_internal(new_dp, gedp->ged_wdbp->dbip, &new_intern, &rt_uniresource) < 0) {
		/* Free memory */
		nmg_km(m_tmp);
		bu_vls_printf(gedp->ged_result_str, "rt_db_put_internal() failure\n");
		return GED_ERROR;
	    }
	    /* Internal representation has been freed by rt_db_put_internal */
	    new_intern.idb_ptr = (void *)NULL;
	}
    }
    bu_vls_free(&shell_name);

    return GED_OK;
}
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 {
示例#26
0
/**
 * R T _ M E T A B A L L _ T E S S
 *
 * Tessellate a metaball.
 */
int
rt_metaball_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
{
    struct rt_metaball_internal *mb;
    fastf_t mtol, radius;
    point_t center, min, max;
    fastf_t i, j, k, finalstep = +INFINITY;
    struct bu_vls times = BU_VLS_INIT_ZERO;
    struct wdb_metaballpt *mbpt;
    struct shell *s;
    int numtri = 0;

    if (r == NULL || m == NULL)
	return -1;
    *r = NULL;

    NMG_CK_MODEL(m);

    RT_CK_DB_INTERNAL(ip);
    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);

    rt_prep_timer();

    /* since this geometry isn't necessarily prepped, we have to figure out the
     * finalstep and bounding box manually. */
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
	V_MIN(finalstep, mbpt->fldstr);
    finalstep /= (fastf_t)1e5;

    radius = rt_metaball_get_bounding_sphere(&center, mb->threshold, mb);
    if(radius < 0) {	/* no control points */
	bu_log("Attempting to tesselate metaball with no control points");
	return -1;
    }
    rt_metaball_bbox(ip, &min, &max, tol);

    /* TODO: get better sampling tolerance, unless this is "good enough" */
    mtol = ttol->abs;
    V_MAX(mtol, ttol->rel * radius * 10);
    V_MAX(mtol, tol->dist);

    *r = nmg_mrsv(m);	/* new empty nmg */
    s = BU_LIST_FIRST(shell, &(*r)->s_hd);

    /* the incredibly naïve approach. Time could be cut in half by simply
     * caching 4 point values, more by actually marching or doing active
     * refinement. This is the simplest pattern for now.
     */
    for (i = min[X]; i < max[X]; i += mtol)
	for (j = min[Y]; j < max[Y]; j += mtol)
	    for (k = min[Z]; k < max[Z]; k += mtol) {
		point_t p[8];
		int pv = 0;

		/* generate the vertex values */
#define MEH(c,di,dj,dk) VSET(p[c], i+di, j+dj, k+dk); pv |= rt_metaball_point_inside((const point_t *)&p[c], mb) << c;
		MEH(0, 0, 0, mtol);
		MEH(1, mtol, 0, mtol);
		MEH(2, mtol, 0, 0);
		MEH(3, 0, 0, 0);
		MEH(4, 0, mtol, mtol);
		MEH(5, mtol, mtol, mtol);
		MEH(6, mtol, mtol, 0);
		MEH(7, 0, mtol, 0);
#undef MEH

		if ( pv != 0 && pv != 255 ) {	/* entire cube is either inside or outside */
		    point_t edges[12];
		    int rval;

		    /* compute the edge values (if needed) */
#define MEH(a,b,c) if(!(pv&(1<<b)&&pv&(1<<c))) { \
    rt_metaball_find_intersection(edges+a, mb, (const point_t *)(p+b), (const point_t *)(p+c), mtol, finalstep); \
}

		    /* magic numbers! an edge, then the two attached vertices.
		     * For edge/vertex mapping, refer to the awesome ascii art
		     * at the beginning of this file. */
		    MEH(0 ,0,1);
		    MEH(1 ,1,2);
		    MEH(2 ,2,3);
		    MEH(3 ,0,3);
		    MEH(4 ,4,5);
		    MEH(5 ,5,6);
		    MEH(6 ,6,7);
		    MEH(7 ,4,7);
		    MEH(8 ,0,4);
		    MEH(9 ,1,5);
		    MEH(10,2,6);
		    MEH(11,3,7);
#undef MEH

		    rval = nmg_mc_realize_cube(s, pv, (point_t *)edges, tol);
		    numtri += rval;
		    if(rval < 0) {
			bu_log("Error attempting to realize a cube O.o\n");
			return rval;
		    }
		}
	    }

    nmg_mark_edges_real(&s->l.magic);
    nmg_region_a(*r, tol);

    nmg_model_fuse(m, tol);

    rt_get_timer(&times, NULL);
    bu_log("metaball tesselate (%d triangles): %s\n", numtri, bu_vls_addr(&times));

    return 0;
}
示例#27
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");
}
示例#28
0
文件: g-euclid.c 项目: kanzure/brlcad
/*
 *  Called from db_walk_tree().
 *
 *  This routine must be prepared to run in parallel.
 */
union tree *
do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data))
{
    struct nmgregion	*r;
    struct bu_list	vhead;
    union tree		*ret_tree;

    if (verbose)
	bu_log("do_region_end: regionid = %d\n", tsp->ts_regionid);

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char	*sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_converted * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    regions_tried++;

    if (verbose)
	bu_log("\tEvaluating region\n");

    ret_tree = process_boolean(curtree, tsp, pathp);

    if (ret_tree)
	r = ret_tree->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;

    regions_converted++;
    if (r != (struct nmgregion *)NULL) {
	struct shell *s;
	int empty_region = 0;
	int empty_model = 0;

	/* Kill cracks */
	s = BU_LIST_FIRST(shell, &r->s_hd);
	while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) {
	    struct shell *next_s;

	    next_s = BU_LIST_PNEXT(shell, &s->l);
	    if (nmg_kill_cracks(s)) {
		if (nmg_ks(s)) {
		    empty_region = 1;
		    break;
		}
	    }
	    s = next_s;
	}

	/* kill zero length edgeuses */
	if (!empty_region) {
	    empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m);
	}

	if (!empty_region && !empty_model) {
	    /* Write the region to the EUCLID file */
	    Write_euclid_region(r, tsp);
	}

	if (!empty_model)
	    nmg_kr(r);
    }

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;
    return curtree;
}
示例#29
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;
}
示例#30
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");
    }

}