Beispiel #1
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;
}
/*
 *	Convert an ascii nmg description into a BRL-CAD data base.
 */
static int
ascii_to_brlcad(FILE *fpin, struct rt_wdb *fpout, char *reg_name, char *grp_name)
{
    struct model	*m;
    struct nmgregion	*r;
    struct bn_tol	tol;
    struct shell	*s;
    vect_t		Ext;
    struct faceuse *fu;
    plane_t		pl;

    VSETALL(Ext, 0.);

    m = nmg_mm();		/* Make nmg model. */
    r = nmg_mrsv(m);	/* Make region, empty shell, vertex */
    s = BU_LIST_FIRST(shell, &r->s_hd);
    descr_to_nmg(s, fpin, Ext);	/* Convert ascii description to nmg. */

    /* Copied from proc-db/nmgmodel.c */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.01;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 0.001;
    tol.para = 0.999;

    /* Associate the face geometry. */
    fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
    if (nmg_loop_plane_area(BU_LIST_FIRST(loopuse, &fu->lu_hd), pl) < 0.0)
	return -1;
    else
	nmg_face_g( fu, pl );

    if (!NEAR_ZERO(MAGNITUDE(Ext), 0.001))
	nmg_extrude_face(BU_LIST_FIRST(faceuse, &s->fu_hd), Ext, &tol);

    nmg_region_a(r, &tol);	/* Calculate geometry for region and shell. */

    nmg_fix_normals( s, &tol ); /* insure that faces have outward pointing normals */

    create_brlcad_db(fpout, m, reg_name, grp_name);

    return 0;
}
Beispiel #3
0
/**
 * R T _ P G _ T E S S
 */
int
rt_pg_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol)
{
    size_t i;
    struct shell *s;
    struct vertex **verts;	/* dynamic array of pointers */
    struct vertex ***vertp;/* dynamic array of ptrs to pointers */
    struct faceuse *fu;
    size_t p;	/* current polygon number */
    struct rt_pg_internal *pgp;

    RT_CK_DB_INTERNAL(ip);
    pgp = (struct rt_pg_internal *)ip->idb_ptr;
    RT_PG_CK_MAGIC(pgp);

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

    verts = (struct vertex **)bu_malloc(
	pgp->max_npts * sizeof(struct vertex *), "pg_tess verts[]");
    vertp = (struct vertex ***)bu_malloc(
	pgp->max_npts * sizeof(struct vertex **), "pg_tess vertp[]");
    for (i=0; i < pgp->max_npts; i++)
	vertp[i] = &verts[i];

    for (p = 0; p < pgp->npoly; p++) {
	struct rt_pg_face_internal *pp;

	pp = &pgp->poly[p];

	/* Locate these points, if previously mentioned */
	for (i=0; i < pp->npts; i++) {
	    verts[i] = nmg_find_pt_in_shell(s,
					    &pp->verts[3*i], tol);
	}

	/* Construct the face.  Verts should be in CCW order */
	if ((fu = nmg_cmface(s, vertp, pp->npts)) == (struct faceuse *)0) {
	    bu_log("rt_pg_tess() nmg_cmface failed, skipping face %zu\n",
		   p);
	}

	/* Associate vertex geometry, where none existed before */
	for (i=0; i < pp->npts; i++) {
	    if (verts[i]->vg_p) continue;
	    nmg_vertex_gv(verts[i], &pp->verts[3*i]);
	}

	/* Associate face geometry */
	if (nmg_calc_face_g(fu)) {
	    nmg_pr_fu_briefly(fu, "");
	    bu_free((char *)verts, "pg_tess verts[]");
	    bu_free((char *)vertp, "pg_tess vertp[]");
	    return -1;			/* FAIL */
	}
    }

    /* Compute "geometry" for region and shell */
    nmg_region_a(*r, tol);

    /* Polysolids are often built with incorrect face normals.
     * Don't depend on them here.
     */
    nmg_fix_normals(s, tol);
    bu_free((char *)verts, "pg_tess verts[]");
    bu_free((char *)vertp, "pg_tess vertp[]");

    return 0;		/* OK */
}
Beispiel #4
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);
}
Beispiel #5
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;
}
int
psurf_to_nmg(struct model *m, FILE *fp, char *jfile)
/* Input/output, nmg model. */
/* Input, pointer to psurf data file. */
/* Name of Jack data base file. */
{
    int		face, fail, i, lst[MAX_NUM_PTS], nf, nv;
    struct faceuse	*outfaceuses[MAX_NUM_PTS];
    struct nmgregion *r;
    struct shell	*s;
    struct vertex	*vertlist[MAX_NUM_PTS];
    struct vlist	vert;

    /* Copied from proc-db/nmgmodel.c */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.01;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 0.001;
    tol.para = 0.999;

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

    while ((nv = read_psurf_vertices(fp, &vert)) != 0) {
	size_t ret;

	while ((nf = read_psurf_face(fp, lst)) != 0) {

	    /* Make face out of vertices in lst (ccw ordered). */
	    for (i = 0; i < nf; i++)
		vertlist[i] = vert.vt[lst[i]-1];
	    outfaceuses[face] = nmg_cface(s, vertlist, nf);
	    face++;

	    /* Save (possibly) newly created vertex structs. */
	    for (i = 0; i < nf; i++)
		vert.vt[lst[i]-1] = vertlist[i];
	}
	ret = fscanf(fp, ";;");
	if (ret > 0)
	    bu_log("unknown parsing error\n");

	/* Associate the vertex geometry, ccw. */
	for (i = 0; i < nv; i++)
	    if (vert.vt[i])
		nmg_vertex_gv(vert.vt[i], &vert.pt[3*i]);
	    else
		fprintf(stderr, "%s, vertex %d is unused\n",
			jfile, i+1);
    }

    nmg_vertex_fuse(&m->magic, &tol);

    /* Associate the face geometry. */
    for (i = 0, fail = 0; i < face; i++)
    {
	struct loopuse *lu;
	plane_t pl;

	lu = BU_LIST_FIRST(loopuse, &outfaceuses[i]->lu_hd);
	if (nmg_loop_plane_area(lu, pl) < 0.0)
	{
	    fail = 1;
	    nmg_kfu(outfaceuses[i]);
	}
	else
	    nmg_face_g(outfaceuses[i], pl);
    }
    if (fail)
	return -1;

    if (face)
    {
	int empty_model;
	empty_model = nmg_kill_zero_length_edgeuses(m);
	if (!empty_model) {

	  /* Compute "geometry" for region and shell */
	  nmg_region_a(r, &tol);

	  nmg_break_e_on_v(&m->magic, &tol);
	  empty_model = nmg_kill_zero_length_edgeuses(m);

	  /* Glue edges of outward pointing face uses together. */
	  if (!empty_model) nmg_edge_fuse(&m->magic, &tol);
	}
    }

    return 0;
}
Beispiel #7
0
int
extrude(int entityno)
{

    fastf_t length;			/* extrusion length */
    vect_t edir;			/* a unit vector (direction of extrusion */
    vect_t evect;			/* Scaled vector for extrusion */
    int sol_num;		/* IGES solid type number */
    int curve;			/* pointer to directory entry for base curve */
    struct ptlist *curv_pts;		/* List of points along curve */
    int i;

    /* Default values */
    VSET(edir, 0.0, 0.0, 1.0);


    /* Acquiring Data */

    if (dir[entityno]->param <= pstart) {
	bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	return 0;
    }
    Readrec(dir[entityno]->param);
    Readint(&sol_num, "");

    /* Read pointer to directory entry for curve to be extruded */

    Readint(&curve, "");

    /* Convert this to a "dir" index */

    curve = (curve-1)/2;

    Readcnv(&length, "");
    Readflt(&edir[X], "");
    Readflt(&edir[Y], "");
    Readflt(&edir[Z], "");

    if (length <= 0.0) {
	bu_log("Illegal parameters for entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	return 0;
    }

    /*
     * Unitize direction vector
     */

    VUNITIZE(edir);

    /* Scale vector */

    VSCALE(evect, edir, length);

    /* Switch based on type of curve to be extruded */

    switch (dir[curve]->type) {
	case 100:	/* circular arc */
	    return Extrudcirc(entityno, curve, evect);
	case 104:	/* conic arc */
	    return Extrudcon(entityno, curve, evect);
	case 102:	/* composite curve */
	case 106:	/* copius data */
	case 112:	/* parametric spline */
	case 126: {
	    /* B-spline */
	    int npts;
	    struct model *m;
	    struct nmgregion *r;
	    struct shell *s;
	    struct faceuse *fu;
	    struct loopuse *lu;
	    struct edgeuse *eu;
	    struct ptlist *pt_ptr;

	    npts = Getcurve(curve, &curv_pts);
	    if (npts < 3)
		return 0;


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

	    fu = nmg_cface(s, (struct vertex **)NULL, npts-1);
	    pt_ptr = curv_pts;
	    lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
	    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
		struct vertex *v;

		v = eu->vu_p->v_p;
		nmg_vertex_gv(v, pt_ptr->pt);
		pt_ptr = pt_ptr->next;
	    }

	    if (nmg_calc_face_g(fu)) {
		bu_log("Extrude: Failed to calculate face geometry\n");
		nmg_km(m);
		bu_free((char *)curv_pts, "curve_pts");
		return 0;
	    }

	    if (nmg_extrude_face(fu, evect, &tol)) {
		bu_log("Extrude: extrusion failed\n");
		nmg_km(m);
		bu_free((char *)curv_pts, "curve_pts");
		return 0;
	    }

	    mk_bot_from_nmg(fdout, dir[entityno]->name, s);
	    nmg_km(m);
	    bu_free((char *)curv_pts, "curve_pts");

	    return 1;
	}
	default:
	    i = (-1);
	    while (dir[curve]->type != typecount[++i].type && i < ntypes);
	    bu_log("Extrusions of %s are not allowed\n", typecount[i].name);
	    break;
    }
    return 0;


}
Beispiel #8
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);
}
Beispiel #9
0
int read_faces(struct model *m, FILE *fgeom)
{
    int 		   nverts, nfaces, nedges;
    int 	   i, j, fail=0;
    fastf_t 	  *pts;
    struct vertex 	 **verts;
    struct faceuse 	 **outfaceuses;
    struct nmgregion  *r;
    struct shell 	  *s;
    size_t ret;

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

    }

    if (fail) return -1;

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

    bu_free((char *)pts, "points list");
    return 0;
}
Beispiel #10
0
HIDDEN void
get_ctria3(void)
{
    int pid;
    int g1, g2, g3;
    int gin1, gin2, gin3;
    point_t pt1, pt2, pt3;
    struct vertex **v[3];
    struct faceuse *fu;
    struct shell *s;
    struct pshell *psh;
    int pid_index=0;

    pid = atoi(curr_rec[2]);

    pid_index = get_pid_index(pid);

    g1 = atoi(curr_rec[3]);

    g2 = atoi(curr_rec[4]);

    g3 = atoi(curr_rec[5]);

    gin1 = get_gridi(g1);
    gin2 = get_gridi(g2);
    gin3 = get_gridi(g3);

    v[0] = &g_pts[gin1].v[pid_index];
    v[1] = &g_pts[gin2].v[pid_index];
    v[2] = &g_pts[gin3].v[pid_index];

    VSCALE(pt1, g_pts[gin1].pt, conv[units]);
    VSCALE(pt2, g_pts[gin2].pt, conv[units]);
    VSCALE(pt3, g_pts[gin3].pt, conv[units]);

    if (!nmg_model && !pid) {
	struct nmgregion *r;

	nmg_model = nmg_mm();
	r = nmg_mrsv(nmg_model);
	nmg_shell = BU_LIST_FIRST(shell, &r->s_hd);
    }

    if (!pid)
	s = nmg_shell;
    else {
	int found=0;

	/* find pshell entry for this pid */
	for (BU_LIST_FOR(psh, pshell, &pshell_head.l)) {
	    if (psh->pid == pid) {
		found = 1;
		break;
	    }
	}

	if (!found) {
	    bu_log("Cannot find PSHELL entry for a CTRIA3 element (ignoring)!\n");
	    write_fields();
	    return;
	}

	if (psh->s)
	    s = psh->s;
	else {
	    struct model *m;
	    struct nmgregion *r;

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

    fu = nmg_cmface(s, v, 3);

    if (!g_pts[gin1].v[pid_index]->vg_p)
	nmg_vertex_gv(g_pts[gin1].v[pid_index], pt1);
    if (!g_pts[gin2].v[pid_index]->vg_p)
	nmg_vertex_gv(g_pts[gin2].v[pid_index], pt2);
    if (!g_pts[gin3].v[pid_index]->vg_p)
	nmg_vertex_gv(g_pts[gin3].v[pid_index], pt3);

    nmg_calc_face_g(fu);
}
Beispiel #11
0
/**
 * "Tessellate" an ARB into an NMG data structure.
 * Purely a mechanical transformation of one faceted object
 * into another.
 *
 * Returns -
 * -1 failure
 *  0 OK.  *r points to nmgregion that holds this tessellation.
 */
int
rt_arbn_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol)
{
    struct rt_arbn_internal *aip;
    struct shell *s;
    struct faceuse **fu;		/* array of faceuses */
    size_t nverts;		/* maximum possible number of vertices = neqn!/(3!(neqn-3)! */
    size_t point_count = 0;	/* actual number of vertices */
    size_t face_count = 0;	/* actual number of faces built */
    size_t i, j, k, l, n;
    struct arbn_pts *pts;
    struct arbn_edges *edges;		/* A list of edges for each plane eqn (each face) */
    size_t *edge_count;	/* number of edges for each face */
    size_t max_edge_count; /* maximum number of edges for any face */
    struct vertex **verts;	/* Array of pointers to vertex structs */
    struct vertex ***loop_verts;	/* Array of pointers to vertex structs to pass to nmg_cmface */

    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    /* Allocate memory for the vertices */
    nverts = aip->neqn * (aip->neqn-1) * (aip->neqn-2) / 6;
    pts = (struct arbn_pts *)bu_calloc(nverts, sizeof(struct arbn_pts), "rt_arbn_tess: pts");

    /* Allocate memory for arbn_edges */
    edges = (struct arbn_edges *)bu_calloc(aip->neqn*aip->neqn, sizeof(struct arbn_edges) ,
					   "rt_arbn_tess: edges");
    edge_count = (size_t *)bu_calloc(aip->neqn, sizeof(size_t), "rt_arbn_tess: edge_count");

    /* Allocate memory for faceuses */
    fu = (struct faceuse **)bu_calloc(aip->neqn, sizeof(struct faceuse *), "rt_arbn_tess: fu");

    /* Calculate all vertices */
    for (i = 0; i < aip->neqn; i++) {
	for (j = i + 1; j < aip->neqn; j++) {
	    for (k = j + 1; k < aip->neqn; k++) {
		int keep_point = 1;

		if (bn_mkpoint_3planes(pts[point_count].pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]))
		    continue;

		for (l = 0; l < aip->neqn; l++) {
		    if (l == i || l == j || l == k)
			continue;
		    if (DIST_PT_PLANE(pts[point_count].pt, aip->eqn[l]) > tol->dist) {
			keep_point = 0;
			break;
		    }
		}
		if (keep_point) {
		    pts[point_count].plane_no[0] = i;
		    pts[point_count].plane_no[1] = j;
		    pts[point_count].plane_no[2] = k;
		    point_count++;
		}
	    }
	}
    }

    /* Allocate memory for the NMG vertex pointers */
    verts = (struct vertex **)bu_calloc(point_count, sizeof(struct vertex *) ,
					"rt_arbn_tess: verts");

    /* Associate points with vertices */
    for (i = 0; i < point_count; i++)
	pts[i].vp = &verts[i];

    /* Check for duplicate points */
    for (i = 0; i < point_count; i++) {
	for (j = i + 1; j < point_count; j++) {
	    if (DIST_PT_PT_SQ(pts[i].pt, pts[j].pt) < tol->dist_sq) {
		/* These two points should point to the same vertex */
		pts[j].vp = pts[i].vp;
	    }
	}
    }

    /* Make list of edges for each face */
    for (i = 0; i < aip->neqn; i++) {
	/* look for a point that lies in this face */
	for (j = 0; j < point_count; j++) {
	    if (pts[j].plane_no[0] != (int)i
		&& pts[j].plane_no[1] != (int)i
		&& pts[j].plane_no[2] != (int)i)
		continue;

	    /* look for another point that shares plane "i" and another with this one */
	    for (k = j + 1; k < point_count; k++) {
		size_t match = (size_t)-1;
		size_t pt1, pt2;
		int duplicate = 0;

		/* skip points not on plane "i" */
		if (pts[k].plane_no[0] != (int)i
		    && pts[k].plane_no[1] != (int)i
		    && pts[k].plane_no[2] != (int)i)
		    continue;

		for (l = 0; l < 3; l++) {
		    for (n = 0; n < 3; n++) {
			if (pts[j].plane_no[l] == pts[k].plane_no[n]
			    && pts[j].plane_no[l] != (int)i) {
			    match = pts[j].plane_no[l];
			    break;
			}
		    }
		    if (match != (size_t)-1)
			break;
		}

		if (match == (size_t)-1)
		    continue;

		/* convert equivalent points to lowest point number */
		pt1 = j;
		pt2 = k;
		for (l = 0; l < pt1; l++) {
		    if (pts[pt1].vp == pts[l].vp) {
			pt1 = l;
			break;
		    }
		}
		for (l = 0; l < pt2; l++) {
		    if (pts[pt2].vp == pts[l].vp) {
			pt2 = l;
			break;
		    }
		}

		/* skip null edges */
		if (pt1 == pt2)
		    continue;

		/* check for duplicate edge */
		for (l = 0; l < edge_count[i]; l++) {
		    if ((edges[LOC(i, l)].v1_no == (int)pt1
			 && edges[LOC(i, l)].v2_no == (int)pt2)
			|| (edges[LOC(i, l)].v2_no == (int)pt1
			    && edges[LOC(i, l)].v1_no == (int)pt2))
		    {
			duplicate = 1;
			break;
		    }
		}
		if (duplicate)
		    continue;

		/* found an edge belonging to faces "i" and "match" */
		if (edge_count[i] == aip->neqn) {
		    bu_log("Too many edges found for one face\n");
		    goto fail;
		}
		edges[LOC(i, edge_count[i])].v1_no = pt1;
		edges[LOC(i, edge_count[i])].v2_no = pt2;
		edge_count[i]++;
	    }
	}
    }

    /* for each face, sort the list of edges into a loop */
    Sort_edges(edges, edge_count, aip);

    /* Get max number of edges for any face */
    max_edge_count = 0;
    for (i = 0; i < aip->neqn; i++)
	if (edge_count[i] > max_edge_count)
	    max_edge_count = edge_count[i];

    /* Allocate memory for array to pass to nmg_cmface */
    loop_verts = (struct vertex ***) bu_calloc(max_edge_count, sizeof(struct vertex **) ,
					       "rt_arbn_tess: loop_verts");

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

    /* Make the faces */
    for (i = 0; i < aip->neqn; i++) {
	int loop_length = 0;

	for (j = 0; j < edge_count[i]; j++) {
	    /* skip zero length edges */
	    if (pts[edges[LOC(i, j)].v1_no].vp == pts[edges[LOC(i, j)].v2_no].vp)
		continue;

	    /* put vertex pointers into loop_verts array */
	    loop_verts[loop_length] = pts[edges[LOC(i, j)].v2_no].vp;
	    loop_length++;
	}

	/* Make the face if there is are least 3 vertices */
	if (loop_length > 2)
	    fu[face_count++] = nmg_cmface(s, loop_verts, loop_length);
    }

    /* Associate vertex geometry */
    for (i = 0; i < point_count; i++) {
	if (!(*pts[i].vp))
	    continue;

	if ((*pts[i].vp)->vg_p)
	    continue;

	nmg_vertex_gv(*pts[i].vp, pts[i].pt);
    }

    bu_free((char *)pts, "rt_arbn_tess: pts");
    bu_free((char *)edges, "rt_arbn_tess: edges");
    bu_free((char *)edge_count, "rt_arbn_tess: edge_count");
    bu_free((char *)verts, "rt_arbn_tess: verts");
    bu_free((char *)loop_verts, "rt_arbn_tess: loop_verts");

    /* Associate face geometry */
    for (i = 0; i < face_count; i++) {
	if (nmg_fu_planeeqn(fu[i], tol)) {
	    bu_log("Failed to calculate face plane equation\n");
	    bu_free((char *)fu, "rt_arbn_tess: fu");
	    nmg_kr(*r);
	    *r = (struct nmgregion *)NULL;
	    return -1;
	}
    }

    bu_free((char *)fu, "rt_arbn_tess: fu");

    nmg_fix_normals(s, tol);

    (void)nmg_mark_edges_real(&s->l.magic);

    /* Compute "geometry" for region and shell */
    nmg_region_a(*r, tol);

    return 0;

fail:
    bu_free((char *)pts, "rt_arbn_tess: pts");
    bu_free((char *)edges, "rt_arbn_tess: edges");
    bu_free((char *)edge_count, "rt_arbn_tess: edge_count");
    bu_free((char *)verts, "rt_arbn_tess: verts");
    return -1;
}