void
Docolor()
{

    int i, j;
    fastf_t a;

    for (i = 0; i < totentities; i++) {
	/* only set colors for regions, groups, or solid instances */
	if (dir[i]->type == 180 || dir[i]->type == 184 || dir[i]->type == 430) {
	    if (dir[i]->colorp > 0) {
		/* just use color table */
		dir[i]->rgb[0] = colortab[dir[i]->colorp][1];
		dir[i]->rgb[1] = colortab[dir[i]->colorp][2];
		dir[i]->rgb[2] = colortab[dir[i]->colorp][3];
	    } else if (dir[i]->colorp < 0) {
		/* Use color definition entity */
		Readrec(dir[-dir[i]->colorp]->param);
		Readint(&j, "");
		if (j != 314) {
		    bu_log("Incorrect color parameters for entity %d\n", i);
		    bu_log("\tcolor entity is #%d\n", -dir[i]->colorp);
		    continue;
		}
		Readflt(&a, "");
		dir[i]->rgb[0] = 2.55 * a + 0.5;
		Readflt(&a, "");
		dir[i]->rgb[1] = 2.55 * a + 0.5;
		Readflt(&a, "");
		dir[i]->rgb[2] = 2.55 * a + 0.5;
	    }
	}
    }
}
Beispiel #2
0
int
planar_nurb(int entityno)
{
    int sol_num = 0;		/* IGES solid type number */
    int k1 = 0, k2 = 0;		/* Upper index of sums */
    int m1 = 0, m2 = 0;		/* degree */

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

    Readrec(dir[entityno]->param);
    Readint(&sol_num, "");
    if (sol_num != 128) {
	bu_log("entity at D%07d is not a B-spline surface\n", entityno*2 + 1);
	return 0;
    }
    Readint(&k1, "");
    Readint(&k2, "");
    Readint(&m1, "");
    Readint(&m2, "");

    if (m1 == 1 && m2 == 1)
	return 1;
    else
	return 0;
}
Beispiel #3
0
/**
 * This routine loops through all the directory entries and looks at
 * attribute definition entities, searching for a BRL-CAD attribute
 * definition.
 */
void
Get_att()
{
    int i, j;
    char *str;

    for ( i=0; i<totentities; i++ )
    {
	/* Look for attribute definitions */
	if ( dir[i]->type == 322 )
	{
	    /* look for form 0 only */
	    if ( dir[i]->form )
		continue;

	    Readrec( dir[i]->param );
	    Readint( &j, "" );
	    if ( j != 322 )
	    {
		bu_log( "Parameters at sequence %d are not for entity at DE%d\n", dir[i]->param, (2*i+1) );
		continue;
	    }

	    Readname( &str, "" );
	    if ( !strncmp(str, "BRLCAD", 6) || !strncmp(str, "BRL-CAD", 7) )
	    {
		/* this is what we have been looking for */
		brlcad_att_de = 2*i+1;
		return;
	    }
	}
    }
}
Beispiel #4
0
void
Readdbl(double *inum, char *id)
{
    int i = (-1), done = 0, lencard;
    char num[80];

    if (card[counter] == eof) {
	/* This is an empty field */
	counter++;
	return;
    } else if (card[counter] == eor) /* Up against the end of record */
	return;

    if (card[72] == 'P')
	lencard = PARAMLEN;
    else
	lencard = CARDLEN;

    if (counter >= lencard)
	Readrec(++currec);

    while (!done) {
	while ((num[++i] = card[counter++]) != eof && num[i] != eor
	       && counter <= lencard)
	    if (num[i] == 'D')
		num[i] = 'e';

	if (counter > lencard && num[i] != eor && num[i] != eof)
	    Readrec(++currec);
	else
	    done = 1;
    }

    if (num[i] == eor)
	counter--;

    num[++i] = '\0';
    *inum = atof(num);
    if (*id != '\0')
	bu_log("%s%g\n", id, *inum);
}
struct shell *
Get_outer_shell(struct nmgregion *r, int entityno)
{

    int sol_num;		/* IGES solid type number */
    int no_of_faces;		/* Number of faces in shell */
    int face_count = 0;		/* Number of faces actually made */
    int *face_de;		/* Directory sequence numbers for faces */
    int *face_orient;		/* Orientation of faces */
    int face;
    struct shell *s;			/* NMG shell */
    struct faceuse **fu;			/* list of faceuses */

    /* 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, "");
    Readint(&no_of_faces, "");

    face_de = (int *)bu_calloc(no_of_faces, sizeof(int), "Get_outer_shell face DE's");
    face_orient = (int *)bu_calloc(no_of_faces, sizeof(int), "Get_outer_shell orients");
    fu = (struct faceuse **)bu_calloc(no_of_faces, sizeof(struct faceuse *), "Get_outer_shell faceuses ");

    for (face = 0; face < no_of_faces; face++) {
	Readint(&face_de[face], "");
	Readint(&face_orient[face], "");
    }

    s = nmg_msv(r);

    for (face = 0; face < no_of_faces; face++) {
	fu[face_count] = Add_face_to_shell(s, (face_de[face]-1)/2, face_orient[face]);
	if (fu[face_count] != (struct faceuse *)NULL)
	    face_count++;
    }

    nmg_gluefaces(fu, face_count, &tol);

    bu_free((char *)fu, "Get_outer_shell: faceuse list");
    bu_free((char *)face_de, "Get_outer_shell: face DE's");
    bu_free((char *)face_orient, "Get_outer_shell: face orients");
    return s;
}
Beispiel #6
0
int
sphere(int entityno)
{
    fastf_t radius = 0.0;
    point_t center;
    fastf_t x;
    fastf_t y;
    fastf_t z;
    int sol_num;		/* IGES solid type number */

    /* Set Defaults */

    x = 0.0;
    y = 0.0;
    z = 0.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, "");
    Readcnv(&radius, "");
    Readcnv(&x, "");
    Readcnv(&y, "");
    Readcnv(&z, "");

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


    /*
     * Making the necessaries. First an id is made for the new entity, then
     * the x, y, z coordinates for its vertices are converted to vectors with
     * VSET(), and finally the libwdb routine that makes an analogous BRL-CAD
     * solid is called.
     */

    VSET(center, x, y, z);
    mk_sph(fdout, dir[entityno]->name, center, radius);

    return 1;
}
int
Extrudcirc(int entityno, int curve, vect_t evect)
    /* extrusion entity number */
    /* circular arc entity number */
    /* extrusion vector */
{
    point_t base;		/* center of cylinder base */
    fastf_t radius;		/* radius of cylinder */
    fastf_t x_1, y_1;		/* Start point */
    fastf_t x_2, y_2;		/* Terminate point */
    int sol_num;	/* Solid number */

    /* Acquiring Data */

    if (dir[curve]->param <= pstart) {
	bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
	       dir[curve]->direct, dir[curve]->name);
	return 0;
    }
    Readrec(dir[curve]->param);
    Readint(&sol_num, "");
    Readcnv(&base[Z], "");
    Readcnv(&base[X], "");
    Readcnv(&base[Y], "");
    Readcnv(&x_1, "");
    Readcnv(&y_1, "");
    Readcnv(&x_2, "");
    Readcnv(&y_2, "");

    /* Check for closure */

    if (!ZERO(x_1 - x_2) || !ZERO(y_1 - y_2)) {
	bu_log("Circular arc for extrusion is not closed:\n");
	bu_log("\textrusion entity D%07d (%s)\n", dir[entityno]->direct ,
	       dir[entityno]->name);
	bu_log("\tarc entity D%07d (%s)\n", dir[curve]->direct, dir[curve]->name);
	return 0;
    }

    radius = sqrt((x_1 - base[X])*(x_1 - base[X]) + (y_1 - base[Y])*(y_1 - base[Y]));


    /* Make an rcc */

    mk_rcc(fdout, dir[entityno]->name, base, evect, radius);

    return 1;
}
Beispiel #8
0
void
Readstart()
{

    int i=0, done=0;

    while ( !done )
    {
	if ( Readrec( ++i ) )
	    bu_exit( 1, "End of file encountered\n" );

	if ( card[72] != 'S' )
	{
	    done = 1;
	    break;
	}
	card[72] = '\0';
	bu_log( "%s\n", card );
    }
    bu_log( "%c", '\n' );
}
void
Convassem()
{
    int i, j, k, comblen, conv = 0, totass = 0;
    struct solid_list *root, *ptr, *ptr_tmp;
    struct wmember head, *wmem;
    int no_of_assoc = 0;
    int no_of_props = 0;
    int att_de = 0;
    unsigned char *rgb;
    struct brlcad_att brl_att;
    fastf_t *flt;

    bu_log("\nConverting solid assembly entities:\n");

    ptr = NULL;
    root = NULL;
    BU_LIST_INIT(&head.l);

    for (i = 0; i < totentities; i++) {
	/* loop through all entities */
	if (dir[i]->type != 184)	/* This is not a solid assembly */
	    continue;

	/* Increment count of solid assemblies */
	totass++;

	if (dir[i]->param <= pstart) {
	    bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
		   dir[i]->direct, dir[i]->name);
	    continue;
	}
	Readrec(dir[i]->param); /* read first record into buffer */

	Readint(&j, "");	/* read entity type */
	if (j != 184) {
	    bu_log("Incorrect entity type in Parameter section for entity %d\n", i);
	    return;
	}

	Readint(&comblen, "");	/* read number of members in group */

	/* Read pointers to group members */
	for (j = 0; j < comblen; j++) {
	    if (ptr == NULL) {
		root = (struct solid_list *)bu_malloc(sizeof(struct solid_list),
						      "Convassem: root");
		ptr = root;
	    } else {
		ptr->next = (struct solid_list *)bu_malloc(sizeof(struct solid_list),
							   "Convassem: ptr->next");
		ptr = ptr->next;
	    }
	    ptr->next = NULL;

	    /* Read pointer to an object */
	    Readint(&ptr->item, "");
	    if (ptr->item < 0)
		ptr->item = (-ptr->item);

	    /* Convert pointer to a "dir" index */
	    ptr->item = (ptr->item-1)/2;

	    /* Save name of object */
	    ptr->name = dir[ptr->item]->name;

	    /* increment reference count */
	    dir[ptr->item]->referenced++;
	}

	/* Read pointer to transformation matrix for each member */
	ptr = root;
	for (j = 0; j < comblen; j++) {
	    ptr->matrix = 0;

	    /* Read pointer to a transformation */
	    Readint(&ptr->matrix, "");

	    if (ptr->matrix < 0)
		ptr->matrix = (-ptr->matrix);

	    /* Convert to a "dir" index */
	    if (ptr->matrix)
		ptr->matrix = (ptr->matrix-1)/2;
	    else
		ptr->matrix = (-1); /* flag to indicate "none" */

	    ptr = ptr->next;
	}

	/* skip over the associativities */
	Readint(&no_of_assoc, "");
	for (k = 0; k < no_of_assoc; k++)
	    Readint(&j, "");

	/* get property entity DE's */
	Readint(&no_of_props, "");
	for (k = 0; k < no_of_props; k++) {
	    Readint(&j, "");
	    if (dir[(j-1)/2]->type == 422 &&
		dir[(j-1)/2]->referenced == brlcad_att_de) {
		/* this is one of our attribute instances */
		att_de = j;
	    }
	}

	Read_att(att_de, &brl_att);

	/* Make the members */
	ptr = root;
	while (ptr != NULL) {
	    /* copy the members original transformation matrix */
	    for (j = 0; j < 16; j++)
		ptr->rot[j] = (*dir[ptr->item]->rot)[j];

	    /* Apply any matrix indicated for this group member */
	    if (ptr->matrix > (-1)) {
#if defined(USE_BN_MULT_)
		/* a <= a X b */
		bn_mat_mul2(ptr->rot, *(dir[ptr->matrix]->rot));
#else
		/* a X b => o */
		Matmult(ptr->rot, *(dir[ptr->matrix]->rot), ptr->rot);
#endif
	    }

	    wmem = mk_addmember(ptr->name, &head.l, NULL, operators[Union]);
	    flt = (fastf_t *)ptr->rot;
	    for (j = 0; j < 16; j++) {
		wmem->wm_mat[j] = (*flt);
		flt++;
	    }
	    ptr = ptr->next;
	}

	/* Make the object */
	if (dir[i]->colorp != 0)
	    rgb = (unsigned char*)dir[i]->rgb;
	else
	    rgb = (unsigned char *)0;

	mk_lrcomb(fdout ,
		  dir[i]->name,		/* name */
		  &head,			/* members */
		  brl_att.region_flag,	/* region flag */
		  brl_att.material_name,	/* material name */
		  brl_att.material_params, /* material parameters */
		  rgb,			/* color */
		  brl_att.ident,		/* ident */
		  brl_att.air_code,	/* air code */
		  brl_att.material_code,	/* GIFT material */
		  brl_att.los_density,	/* los density */
		  brl_att.inherit);	/* inherit */


	/* Increment the count of successful conversions */
	conv++;

	/* Free some memory */
	ptr = root;
	while (ptr != NULL) {
	    ptr_tmp = ptr->next;
	    bu_free((char *)ptr, "convassem: ptr");
	    ptr = ptr_tmp;
	}
    }
    bu_log("Converted %d solid assemblies successfully out of %d total assemblies\n", conv, totass);
}
Beispiel #10
0
struct edge_g_cnurb *
Get_cnurb_curve(int curve_de, int *linear)
{
    int i;
    int curve;
    struct edge_g_cnurb *crv;

    *linear = 0;

    curve = (curve_de - 1)/2;
    if (curve >= dirarraylen) {
	bu_log("Get_cnurb_curve: DE=%d is too large, dirarraylen = %d\n", curve_de, dirarraylen);
	return (struct edge_g_cnurb *)NULL;
    }

    switch (dir[curve]->type) {
	case 110: {
	    /* line */
	    int pt_type;
	    int type;
	    point_t pt1;
	    point_t start_pt, end_pt;

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Get_cnurb_curve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		return (struct edge_g_cnurb *)NULL;

	    }
	    /* Read first point */
	    for (i = 0; i < 3; i++)
		Readcnv(&pt1[i], "");
	    MAT4X3PNT(start_pt, *dir[curve]->rot, pt1);

	    /* Read second point */
	    for (i = 0; i < 3; i++)
		Readcnv(&pt1[i], "");
	    MAT4X3PNT(end_pt, *dir[curve]->rot, pt1);

	    /* pt_type for rational UVW coords */
	    pt_type = RT_NURB_MAKE_PT_TYPE(3, 3, 1);

	    /* make a linear edge_g_cnurb (order=2) */
	    crv = rt_nurb_new_cnurb(2, 4, 2, pt_type);

	    /* insert control mesh */
	    VMOVE(crv->ctl_points, start_pt);
	    VMOVE(&crv->ctl_points[3], end_pt);

	    /* insert knot values */
	    crv->k.knots[0] = 0.0;
	    crv->k.knots[1] = 0.0;
	    crv->k.knots[2] = 1.0;
	    crv->k.knots[3] = 1.0;

	    *linear = 1;

	    return crv;
	}
	case 126:	/* B-spline */
	    crv = Get_cnurb(curve);
	    if (crv->order < 3)
		*linear = 1;
	    return crv;
	default:
	    bu_log("Not yet handling curves of type: %s\n", iges_type(dir[curve]->type));
	    break;
    }

    return (struct edge_g_cnurb *)NULL;
}
void
Convtree()
{

    int conv = 0;
    int tottrees = 0;
    union tree *ptr;
    struct rt_comb_internal *comb;
    int no_of_assoc = 0;
    int no_of_props = 0;
    int att_de = 0;
    struct brlcad_att brl_att;
    int i, j, k;

    if (bu_debug & BU_DEBUG_MEM_CHECK)
	bu_log("Doing memory checking in Convtree()\n");
    MEMCHECK;

    bu_log("\nConverting boolean tree entities:\n");

    for (i = 0; i < totentities; i++) {
	/* loop through all entities */
	if (dir[i]->type != 180)	/* This is not a tree */
	    continue;

	att_de = 0;			/* For default if there is no attribute entity */

	tottrees++;

	if (dir[i]->param <= pstart) {
	    /* Illegal parameter address */
	    bu_log("Entity number %d (Boolean Tree) does not have a legal parameter pointer\n", i);
	    continue;
	}

	Readrec(dir[i]->param); /* read first record into buffer */

	MEMCHECK;

	ptr = Readtree(dir[i]->rot); /* construct the tree */

	MEMCHECK;

	if (!ptr) {
	    /* failure */
	    bu_log("\tFailed to convert Boolean tree at D%07d\n", dir[i]->direct);
	    continue;
	}

	/* skip over the associativities */
	Readint(&no_of_assoc, "");
	for (k = 0; k < no_of_assoc; k++)
	    Readint(&j, "");

	/* get property entity DE's */
	Readint(&no_of_props, "");
	for (k = 0; k < no_of_props; k++) {
	    Readint(&j, "");
	    if (dir[(j-1)/2]->type == 422 &&
		dir[(j-1)/2]->referenced == brlcad_att_de) {
		/* this is one of our attribute instances */
		att_de = j;
	    }
	}

	Read_att(att_de, &brl_att);
	/* Read_att will supply defaults if att_de is 0 */
	if (att_de == 0)
	    brl_att.region_flag = 1;

	BU_ALLOC(comb, struct rt_comb_internal);
	RT_COMB_INTERNAL_INIT(comb);

	comb->tree = ptr;

	if (brl_att.region_flag) {
	    comb->region_flag = 1;
	    comb->region_id = brl_att.ident;
	    comb->aircode = brl_att.air_code;
	    comb->GIFTmater = brl_att.material_code;
	    comb->los = brl_att.los_density;
	}
	if (dir[i]->colorp != 0) {
	    comb->rgb_valid = 1;
	    comb->rgb[0] = dir[i]->rgb[0];
	    comb->rgb[1] = dir[i]->rgb[1];
	    comb->rgb[2] = dir[i]->rgb[2];
	}
	comb->inherit = brl_att.inherit;
	bu_vls_init(&comb->shader);
	if (brl_att.material_name) {
	    bu_vls_strcpy(&comb->shader, brl_att.material_name);
	    if (brl_att.material_params) {
		bu_vls_putc(&comb->shader, ' ');
		bu_vls_strcat(&comb->shader, brl_att.material_params);
	    }
	}
	bu_vls_init(&comb->material);

	MEMCHECK;
	if (wdb_export(fdout, dir[i]->name, (void *)comb, ID_COMBINATION, mk_conv2mm))
	    bu_exit(1, "mk_export_fwrite() failed for combination (%s)\n", dir[i]->name);

	conv++;

	MEMCHECK;
    }

    bu_log("Converted %d trees successfully out of %d total trees\n", conv, tottrees);
    MEMCHECK;
}
int
Getcurve(int curve, struct ptlist **curv_pts)
{
    int type;
    int npts = 0;
    int i, j;
    double pi;
    struct ptlist *ptr, *prev;

    pi = atan2(0.0, -1.0);

    (*curv_pts) = NULL;
    prev = NULL;

    switch (dir[curve]->type) {
	case 110: {
	    /* line */
	    point_t pt1;

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Getcurve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		npts = 0;
		break;
	    }

	    BU_ALLOC((*curv_pts), struct ptlist);
	    ptr = (*curv_pts);

	    /* Read first point */
	    for (i = 0; i < 3; i++)
		Readcnv(&pt1[i], "");
	    MAT4X3PNT(ptr->pt, *dir[curve]->rot, pt1);

	    ptr->prev = NULL;
	    prev = ptr;

	    BU_ALLOC(ptr->next, struct ptlist);
	    ptr = ptr->next;

	    /* Read second point */
	    for (i = 0; i < 3; i++)
		Readcnv(&pt1[i], "");
	    MAT4X3PNT(ptr->pt, *dir[curve]->rot, pt1);
	    ptr->next = NULL;
	    ptr->prev = prev;

	    npts = 2;
	    break;
	}
	case 100: {
	    /* circular arc */
	    point_t center, start, stop, tmp;
	    fastf_t common_z, ang1, ang2, delta;
	    double cosdel, sindel, rx, ry;

	    delta = (2.0*pi)/ARCSEGS;

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Getcurve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		npts = 0;
		break;
	    }

	    /* Read common Z coordinate */
	    Readcnv(&common_z, "");

	    /* Read center point */
	    Readcnv(&center[X], "");
	    Readcnv(&center[Y], "");
	    center[Z] = common_z;

	    /* Read start point */
	    Readcnv(&start[X], "");
	    Readcnv(&start[Y], "");
	    start[Z] = common_z;

	    /* Read stop point */
	    Readcnv(&stop[X], "");
	    Readcnv(&stop[Y], "");
	    stop[Z] = common_z;

	    ang1 = atan2(start[Y] - center[Y], start[X] - center[X]);
	    ang2 = atan2(stop[Y] - center[Y], stop[X] - center[X]);
	    while (ang2 <= ang1)
		ang2 += (2.0*pi);

	    npts = (ang2 - ang1)/delta;
	    npts++;
	    V_MAX(npts, 3);

	    delta = (ang2 - ang1)/(npts-1);
	    cosdel = cos(delta);
	    sindel = sin(delta);

	    /* Calculate points on curve */
	    BU_ALLOC((*curv_pts), struct ptlist);
	    ptr = (*curv_pts);
	    prev = NULL;

	    MAT4X3PNT(ptr->pt, *dir[curve]->rot, start);

	    ptr->prev = prev;
	    prev = ptr;

	    BU_ALLOC(ptr->next, struct ptlist);
	    ptr = ptr->next;
	    ptr->prev = prev;

	    VMOVE(tmp, start);
	    for (i = 1; i < npts; i++) {
		rx = tmp[X] - center[X];
		ry = tmp[Y] - center[Y];
		tmp[X] = center[X] + rx*cosdel - ry*sindel;
		tmp[Y] = center[Y] + rx*sindel + ry*cosdel;
		MAT4X3PNT(ptr->pt, *dir[curve]->rot, tmp);
		prev = ptr;

		BU_ALLOC(ptr->next, struct ptlist);
		ptr = ptr->next;
		ptr->prev = prev;
	    }
	    ptr = prev;
	    bu_free((char *)ptr->next, "Getcurve: ptr->next");
	    ptr->next = NULL;
	    break;
	}
	case 106: {
	    /* copius data */
	    int interpflag;	/* interpretation flag
				   1 => x, y pairs (common z-coord)
				   2 => x, y, z coords
				   3 => x, y, z coords and i, j, k vectors */
	    int ntuples;	/* number of points */
	    fastf_t common_z;	/* common z-coordinate */
	    point_t pt1;		/* temporary storage for incoming point */

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Getcurve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		npts = 0;
		break;
	    }

	    Readint(&interpflag, "");
	    Readint(&ntuples, "");

	    switch (dir[curve]->form) {
		case 1:
		case 11:
		case 40:
		case 63: {
		    /* data are coordinate pairs with common z */
		    if (interpflag != 1) {
			bu_log("Error in Getcurve for copius data entity D%07d, IP=%d, should be 1\n",
			       dir[curve]->direct, interpflag);
			npts = 0;
			break;
		    }
		    Readcnv(&common_z, "");

		    BU_ALLOC((*curv_pts), struct ptlist);
		    ptr = (*curv_pts);
		    ptr->prev = NULL;

		    for (i = 0; i < ntuples; i++) {
			Readcnv(&pt1[X], "");
			Readcnv(&pt1[Y], "");
			pt1[Z] = common_z;
			MAT4X3PNT(ptr->pt, *dir[curve]->rot, pt1);
			prev = ptr;

			BU_ALLOC(ptr->next, struct ptlist);
			ptr = ptr->next;
			ptr->prev = prev;
			ptr->next = NULL;
		    }
		    ptr = ptr->prev;
		    bu_free((char *)ptr->next, "Getcurve: ptr->next");
		    ptr->next = NULL;
		    npts = ntuples;
		    break;
		}
		case 2:
		case 12: {
		    /* data are coordinate triples */
		    if (interpflag != 2) {
			bu_log("Error in Getcurve for copius data entity D%07d, IP=%d, should be 2\n",
			       dir[curve]->direct, interpflag);
			npts = 0;
			break;
		    }
		    BU_ALLOC((*curv_pts), struct ptlist);
		    ptr = (*curv_pts);
		    ptr->prev = NULL;

		    for (i = 0; i < ntuples; i++) {
			Readcnv(&pt1[X], "");
			Readcnv(&pt1[Y], "");
			Readcnv(&pt1[Z], "");
			MAT4X3PNT(ptr->pt, *dir[curve]->rot, pt1);
			prev = ptr;

			BU_ALLOC(ptr->next, struct ptlist);
			ptr = ptr->next;
			ptr->prev = prev;
		    }
		    ptr = ptr->prev;
		    bu_free((char *)ptr->next, "Getcurve: ptr->next");
		    ptr->next = NULL;
		    npts = ntuples;
		    break;
		}
		default: {
		    bu_log("Error in Getcurve for copius data entity D%07d, form %d is not a legal choice\n",
			   dir[curve]->direct, dir[curve]->form);
		    npts = 0;
		    break;
		}
	    }
	    break;
	}
	case 112: {
	    /* parametric spline */
	    struct spline *splroot;
	    struct segment *seg, *seg1;
	    vect_t tmp;
	    double a;

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Getcurve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		npts = 0;
		break;
	    }
	    Readint(&i, "");	/* Skip over type */
	    Readint(&i, "");	/* Skip over continuity */

	    BU_ALLOC(splroot, struct spline);
	    splroot->start = NULL;

	    Readint(&splroot->ndim, ""); /* 2->planar, 3->3d */
	    Readint(&splroot->nsegs, ""); /* Number of segments */
	    Readdbl(&a, "");	/* first breakpoint */

	    /* start a linked list of segments */
	    seg = splroot->start;
	    for (i = 0; i < splroot->nsegs; i++) {
		if (seg == NULL) {
		    BU_ALLOC(seg, struct segment);
		    splroot->start = seg;
		} else {
		    BU_ALLOC(seg->next, struct segment);
		    seg = seg->next;
		}
		seg->segno = i+1;
		seg->next = NULL;
		seg->tmin = a; /* set minimum T for this segment */
		Readflt(&seg->tmax, ""); /* get maximum T for segment */
		a = seg->tmax;
	    }

	    /* read coefficients for polynomials */
	    seg = splroot->start;
	    for (i = 0; i < splroot->nsegs; i++) {
		for (j = 0; j < 4; j++)
		    Readflt(&seg->cx[j], ""); /* x coeff's */
		for (j = 0; j < 4; j++)
		    Readflt(&seg->cy[j], ""); /* y coeff's */
		for (j = 0; j < 4; j++)
		    Readflt(&seg->cz[j], ""); /* z coeff's */
		seg = seg->next;
	    }

	    /* Calculate points */

	    BU_ALLOC((*curv_pts), struct ptlist);
	    ptr = (*curv_pts);
	    prev = NULL;
	    ptr->prev = NULL;

	    npts = 0;
	    seg = splroot->start;
	    while (seg != NULL) {
		/* plot 9 points per segment (This should
		   be replaced by some logic) */
		for (i = 0; i < 9; i++) {
		    a = (fastf_t)i/(8.0)*(seg->tmax-seg->tmin);
		    tmp[0] = splinef(seg->cx, a);
		    tmp[1] = splinef(seg->cy, a);
		    if (splroot->ndim == 3)
			tmp[2] = splinef(seg->cz, a);
		    else
			tmp[2] = seg->cz[0];
		    MAT4X3PNT(ptr->pt, *dir[curve]->rot, tmp);
		    for (j = 0; j < 3; j++)
			ptr->pt[j] *= conv_factor;
		    npts++;
		    prev = ptr;

		    BU_ALLOC(ptr->next, struct ptlist);
		    ptr = ptr->next;
		    ptr->prev = prev;
		}
		seg = seg->next;
	    }
	    ptr = ptr->prev;
	    bu_free((char *)ptr->next, "Getcurve: ptr->next");
	    ptr->next = NULL;

	    /* free the used memory */
	    seg = splroot->start;
	    while (seg != NULL) {
		seg1 = seg;
		seg = seg->next;
		bu_free((char *)seg1, "Getcurve: seg1");
	    }
	    bu_free((char *)splroot, "Getcurve: splroot");
	    splroot = NULL;

	    break;
	}
	case 104: {
	    /* conic arc */
	    double A, B, C, D, E, F, a, b, c, del, I, theta, dpi, t1, t2, xc, yc;
	    point_t v1, v2, tmp;
	    mat_t rot1;
	    int num_points;

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Getcurve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		npts = 0;
		break;
	    }

	    /* read coefficients */
	    Readdbl(&A, "");
	    Readdbl(&B, "");
	    Readdbl(&C, "");
	    Readdbl(&D, "");
	    Readdbl(&E, "");
	    Readdbl(&F, "");

	    /* read common z-coordinate */
	    Readflt(&v1[2], "");
	    v2[2] = v1[2];

	    /* read start point */
	    Readflt(&v1[0], "");
	    Readflt(&v1[1], "");

	    /* read terminate point */
	    Readflt(&v2[0], "");
	    Readflt(&v2[1], "");

	    type = 0;
	    if (dir[curve]->form == 1) {
		/* Ellipse */
		if (fabs(E) < SMALL)
		    E = 0.0;
		if (fabs(B) < SMALL)
		    B = 0.0;
		if (fabs(D) < SMALL)
		    D = 0.0;

		if (ZERO(B) && ZERO(D) && ZERO(E))
		    type = 1;
		else
		    bu_log("Entity #%d is an incorrectly formatted ellipse\n", curve);
	    }

	    /* make coeff of X**2 equal to 1.0 */
	    a = A*C - B*B/4.0;
	    if (fabs(a) < 1.0  && fabs(a) > TOL) {
		a = fabs(A);
		if (fabs(B) < a && !ZERO(B))
		    a = fabs(B);
		V_MIN(a, fabs(C));

		A = A/a;
		B = B/a;
		C = C/a;
		D = D/a;
		E = E/a;
		F = F/a;
		a = A*C - B*B/4.0;
	    }

	    if (!type) {
		/* check for type of conic */
		del = A*(C*F-E*E/4.0)-0.5*B*(B*F/2.0-D*E/4.0)+0.5*D*(B*E/4.0-C*D/2.0);
		I = A+C;
		if (ZERO(del)) {
		    /* not a conic */
		    bu_log("Entity #%d, claims to be conic arc, but isn't\n", curve);
		    break;
		} else if (a > 0.0 && del*I < 0.0)
		    type = 1; /* ellipse */
		else if (a < 0.0)
		    type = 2; /* hyperbola */
		else if (ZERO(a))
		    type = 3; /* parabola */
		else {
		    /* imaginary ellipse */
		    bu_log("Entity #%d is an imaginary ellipse!!\n", curve);
		    break;
		}
	    }

	    switch (type) {

		double p, r1;

		case 3:	/* parabola */

			/* make A+C == 1.0 */
		    if (!EQUAL(A+C, 1.0)) {
			b = A+C;
			A = A/b;
			B = B/b;
			C = C/b;
			D = D/b;
			E = E/b;
			F = F/b;
		    }

		    /* theta is the angle that the parabola axis is rotated
		       about the origin from the x-axis */
		    theta = 0.5*atan2(B, C-A);

		    /* p is the distance from vertex to directrix */
		    p = (-E*sin(theta) - D*cos(theta))/4.0;
		    if (fabs(p) < TOL) {
			bu_log("Cannot plot entity %d, p=%g\n", curve, p);
			break;
		    }

		    /* calculate vertex (xc, yc). This is based on the
		       parametric representation:
		       x = xc + a*t*t*cos(theta) - t*sin(theta)
		       y = yc + a*t*t*sin(theta) + t*cos(theta)
		       and the fact that v1 and v2 are on the curve
		    */
		    a = 1.0/(4.0*p);
		    b = ((v1[0]-v2[0])*cos(theta) + (v1[1]-v2[1])*sin(theta))/a;
		    c = ((v1[1]-v2[1])*cos(theta) - (v1[0]-v2[0])*sin(theta));
		    if (fabs(c) < TOL*TOL) {
			bu_log("Cannot plot entity %d\n", curve);
			break;
		    }
		    b = b/c;
		    t1 = (b + c)/2.0; /* value of 't' at v1 */
		    t2 = (b - c)/2.0; /* value of 't' at v2 */
		    xc = v1[0] - a*t1*t1*cos(theta) + t1*sin(theta);
		    yc = v1[1] - a*t1*t1*sin(theta) - t1*cos(theta);

		    /* Calculate points */

		    BU_ALLOC((*curv_pts), struct ptlist);
		    ptr = (*curv_pts);
		    ptr->prev = NULL;
		    prev = NULL;

		    npts = 0;
		    num_points = ARCSEGS+1;
		    dpi = (t2-t1)/(double)num_points; /* parameter increment */

		    /* start point */
		    VSET(tmp, xc, yc, v1[2]);
		    MAT4X3PNT(ptr->pt, *dir[curve]->rot, tmp);
		    VSCALE(ptr->pt, ptr->pt, conv_factor);
		    npts++;
		    prev = ptr;

		    BU_ALLOC(ptr->next, struct ptlist);
		    ptr = ptr->next;
		    ptr->prev = prev;

		    /* middle points */
		    b = cos(theta);
		    c = sin(theta);
		    for (i = 1; i < num_points-1; i++) {
			r1 = t1 + dpi*i;
			tmp[0] = xc + a*r1*r1*b - r1*c;
			tmp[1] = yc + a*r1*r1*c + r1*b;
			MAT4X3PNT(ptr->pt, *dir[curve]->rot, tmp);
			VSCALE(ptr->pt, ptr->pt, conv_factor);
			npts++;
			prev = ptr;

			BU_ALLOC(ptr->next, struct ptlist);
			ptr = ptr->next;
			ptr->prev = prev;
		    }

		    /* plot terminate point */
		    tmp[0] = v2[0];
		    tmp[1] = v2[1];
		    MAT4X3PNT(ptr->pt, *dir[curve]->rot, tmp);
		    for (j = 0; j < 3; j++)
			ptr->pt[j] *= conv_factor;
		    npts++;
		    ptr->next = NULL;
		    break;

		case 1:	/* ellipse */
		case 2: {
		    /* hyperbola */
		    double A1, C1, F1, alpha, beta;
		    mat_t rot2;
		    point_t v3;

		    /* calculate center of ellipse or hyperbola */
		    xc = (B*E/4.0 - D*C/2.0)/a;
		    yc = (B*D/4.0 - A*E/2.0)/a;

		    /* theta is angle that the curve axis is rotated about
		       the origin from the x-axis */
		    if (!ZERO(B))
			theta = 0.5*atan2(B, A-C);
		    else
			theta = 0.0;

		    /* calculate coeff's for same curve, but with
		       vertex at origin and theta = 0.0 */
		    A1 = A + 0.5*B*tan(theta);
		    C1 = C - 0.5*B*tan(theta);
		    F1 = F - A*xc*xc - B*xc*yc - C*yc*yc;


		    if (type == 2 && F1/A1 > 0.0)
			theta += pi/2.0;

		    /* set-up matrix to translate and rotate
		       the start and terminate points to match
		       the simpler curve (A1, C1, and F1 coeff's)	*/

		    for (i = 0; i < 16; i++)
			rot1[i] = idn[i];
		    MAT_DELTAS(rot1, -xc, -yc, 0.0);
		    MAT4X3PNT(tmp, rot1, v1);
		    VMOVE(v1, tmp);
		    MAT4X3PNT(tmp, rot1, v2);
		    VMOVE(v2, tmp);
		    MAT_DELTAS(rot1, 0.0, 0.0, 0.0);
		    rot1[0] = cos(theta);
		    rot1[1] = sin(theta);
		    rot1[4] = (-rot1[1]);
		    rot1[5] = rot1[0];
		    MAT4X3PNT(tmp, rot1, v1);
		    VMOVE(v1, tmp);
		    MAT4X3PNT(tmp, rot1, v2);
		    VMOVE(v2, tmp);
		    MAT_DELTAS(rot1, 0.0, 0.0, 0.0);

		    /* calculate:
		       alpha = start angle
		       beta = terminate angle
		    */
		    beta = 0.0;
		    if (EQUAL(v2[0], v1[0]) && EQUAL(v2[1], v1[1])) {
			/* full circle */
			alpha = 0.0;
			beta = 2.0*pi;
		    }
		    a = sqrt(fabs(F1/A1)); /* semi-axis length */
		    b = sqrt(fabs(F1/C1)); /* semi-axis length */

		    if (type == 1) {
			/* ellipse */
			alpha = atan2(a*v1[1], b*v1[0]);
			if (ZERO(beta)) {
			    beta = atan2(a*v2[1], b*v2[0]);
			    beta = beta - alpha;
			}
		    } else {
			/* hyperbola */
			alpha = myarcsinh(v1[1]/b);
			beta = myarcsinh(v2[1]/b);
			if (fabs(a*cosh(beta) - v2[0]) > 0.01)
			    a = (-a);
			beta = beta - alpha;
		    }
		    num_points = ARCSEGS;

		    /* set-up matrix to translate and rotate
		       the simpler curve back to the original
		       position */

		    MAT_DELTAS(rot1, xc, yc, 0.0);
		    rot1[1] = (-rot1[1]);
		    rot1[4] = (-rot1[4]);
#if defined(USE_BN_MULT_)
		    /* o <= a X b */
		    bn_mat_mul(rot2, *(dir[curve]->rot), rot1);
#else
		    /* a X b => o */
		    Matmult(*(dir[curve]->rot), rot1, rot2);
#endif

		    /* calculate start point */
		    BU_ALLOC((*curv_pts), struct ptlist);
		    ptr = (*curv_pts);
		    prev = NULL;
		    ptr->prev = NULL;

		    npts = 0;
		    VSCALE(v3, v1, conv_factor);
		    MAT4X3PNT(ptr->pt, rot2, v3);
		    npts++;
		    prev = ptr;

		    BU_ALLOC(ptr->next, struct ptlist);
		    ptr = ptr->next;
		    ptr->prev = prev;

		    /* middle points */
		    for (i = 1; i < num_points; i++) {
			point_t tmp2 = {0.0, 0.0, 0.0};

			theta = alpha + (double)i/(double)num_points*beta;
			if (type == 2) {
			    tmp2[0] = a*cosh(theta);
			    tmp2[1] = b*sinh(theta);
			} else {
			    tmp2[0] = a*cos(theta);
			    tmp2[1] = b*sin(theta);
			}
			VSCALE(tmp2, tmp2, conv_factor);
			MAT4X3PNT(ptr->pt, rot2, tmp2);
			npts++;
			prev = ptr;

			BU_ALLOC(ptr->next, struct ptlist);
			ptr = ptr->next;
			ptr->prev = prev;
		    }

		    /* terminate point */
		    VSCALE(v2, v2, conv_factor);
		    MAT4X3PNT(ptr->pt, rot2, v2);
		    npts++;
		    ptr->next = NULL;
		    break;
		}
	    }
	    break;
	}
	case 102:	/* composite curve */ {

	    int ncurves, *curvptr;
	    struct ptlist *tmp_ptr;

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Getcurve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		npts = 0;
		break;
	    }

	    Readint(&ncurves, "");
	    curvptr = (int *)bu_calloc(ncurves, sizeof(int), "Getcurve: curvptr");
	    for (i = 0; i < ncurves; i++) {
		Readint(&curvptr[i], "");
		curvptr[i] = (curvptr[i]-1)/2;
	    }

	    npts = 0;
	    (*curv_pts) = NULL;
	    for (i = 0; i < ncurves; i++) {
		npts += Getcurve(curvptr[i], &tmp_ptr);
		if ((*curv_pts) == NULL)
		    (*curv_pts) = tmp_ptr;
		else {
		    ptr = (*curv_pts);
		    while (ptr->next != NULL)
			ptr = ptr->next;
		    ptr->next = tmp_ptr;
		    ptr->next->prev = ptr;
		    if (NEAR_EQUAL(ptr->pt[X], tmp_ptr->pt[X], TOL) &&
			NEAR_EQUAL(ptr->pt[Y], tmp_ptr->pt[Y], TOL) &&
			NEAR_EQUAL(ptr->pt[Z], tmp_ptr->pt[Z], TOL)) {
			ptr->next = ptr->next->next;
			if (ptr->next != NULL)
			    ptr->next->prev = ptr;
			bu_free((char *)tmp_ptr, "Getcurve: tmp_ptr");
			npts--;
		    }
		}
	    }
	    break;
	}
	case 126: {
	    /* rational B-spline */
	    int k, m, n, a, prop1, prop2, prop3, prop4;
	    fastf_t *t;	/* knot values */
	    fastf_t *w;	/* weights */
	    point_t *cntrl_pts;	/* control points */
	    fastf_t v0, v1;	/* starting and stopping parameter values */
	    fastf_t v;	/* current parameter value */
	    fastf_t delv;	/* parameter increment */

	    Readrec(dir[curve]->param);
	    Readint(&type, "");
	    if (type != dir[curve]->type) {
		bu_log("Error in Getcurve, looking for curve type %d, found %d\n" ,
		       dir[curve]->type, type);
		npts = 0;
		break;
	    }

	    Readint(&k, "");
	    Readint(&m, "");
	    Readint(&prop1, "");
	    Readint(&prop2, "");
	    Readint(&prop3, "");
	    Readint(&prop4, "");

	    n = k - m + 1;
	    a = n + 2 * m;

	    t = (fastf_t *)bu_calloc(a+1, sizeof(fastf_t), "Getcurve: spline t");
	    for (i = 0; i < a+1; i++)
		Readflt(&t[i], "");
	    Knot(a+1, t);

	    w = (fastf_t *)bu_calloc(k+1, sizeof(fastf_t), "Getcurve: spline w");
	    for (i = 0; i < k+1; i++)
		Readflt(&w[i], "");

	    cntrl_pts = (point_t *)bu_calloc(k+1, sizeof(point_t), "Getcurve: spline cntrl_pts");
	    for (i = 0; i < k+1; i++) {
		fastf_t tmp;

		for (j = 0; j < 3; j++) {
		    Readcnv(&tmp, "");
		    cntrl_pts[i][j] = tmp;
		}
	    }

	    Readflt(&v0, "");
	    Readflt(&v1, "");

	    delv = (v1 - v0)/((fastf_t)(3*k));

	    /* Calculate points */

	    BU_ALLOC((*curv_pts), struct ptlist);
	    ptr = (*curv_pts);
	    ptr->prev = NULL;
	    prev = NULL;

	    npts = 0;
	    v = v0;
	    while (v < v1) {
		point_t tmp;

		B_spline(v, k, m+1, cntrl_pts, w, tmp);
		MAT4X3PNT(ptr->pt, *dir[curve]->rot, tmp);
		npts++;
		prev = ptr;

		BU_ALLOC(ptr->next, struct ptlist);
		ptr = ptr->next;
		ptr->prev = prev;

		v += delv;
	    }
	    VMOVE(ptr->pt, cntrl_pts[k]);
	    npts++;
	    ptr->next = NULL;

	    /* Free memory */
	    Freeknots();
	    bu_free((char *)cntrl_pts, "Getcurve: spline cntrl_pts");
	    bu_free((char *)w, "Getcurve: spline w");
	    bu_free((char *)t, "Getcurve: spline t");

	    break;
	}
    }
    return npts;
}
void
Do_subfigs()
{
    int i, j;
    int entity_type;
    struct wmember head1;
    struct wmember *wmem;

    if (RT_G_DEBUG & DEBUG_MEM_FULL)
	bu_mem_barriercheck();

    BU_LIST_INIT(&head1.l);

    for (i = 0; i < totentities; i++) {
	int subfigdef_de;
	int subfigdef_index;
	int no_of_members;
	int *members;
	char *name = NULL;
	struct wmember head2;
	double mat_scale[3];
	int non_unit;

	if (dir[i]->type != 408)
	    continue;

	if (RT_G_DEBUG & DEBUG_MEM_FULL)
	    bu_mem_barriercheck();

	if (dir[i]->param <= pstart) {
	    bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
		   dir[i]->direct, dir[i]->name);
	    continue;
	}

	Readrec(dir[i]->param);
	Readint(&entity_type, "");
	if (entity_type != 408) {
	    bu_log("Expected Singular Subfigure Instance Entity, found %s\n",
		   iges_type(entity_type));
	    continue;
	}

	Readint(&subfigdef_de, "");
	subfigdef_index = (subfigdef_de - 1)/2;
	if (subfigdef_index >= totentities) {
	    bu_log("Singular Subfigure Instance Entity gives Subfigure Definition");
	    bu_log("\tEntity DE of %d, largest DE in file is %d\n",
		   subfigdef_de, (totentities * 2) - 1);
	    continue;
	}
	if (dir[subfigdef_index]->type != 308) {
	    bu_log("Expected Subfigure Definition Entity, found %s\n",
		   iges_type(dir[subfigdef_index]->type));
	    continue;
	}

	if (dir[subfigdef_index]->param <= pstart) {
	    bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
		   dir[subfigdef_index]->direct, dir[subfigdef_index]->name);
	    continue;
	}
	Readrec(dir[subfigdef_index]->param);
	Readint(&entity_type, "");
	if (entity_type != 308) {
	    bu_log("Expected Subfigure Definition Entity, found %s\n",
		   iges_type(entity_type));
	    continue;
	}

	Readint(&j, "");	/* ignore depth */
	Readstrg("");		/* ignore subfigure name */

	wmem = mk_addmember(dir[subfigdef_index]->name, &head1.l, NULL, WMOP_UNION);
	non_unit = 0;
	for (j = 0; j < 3; j++) {
	    double mag_sq;

	    mat_scale[j] = 1.0;
	    mag_sq = MAGSQ(&(*dir[i]->rot)[j*4]);

	    /* FIXME: arbitrary undefined tolerance */
	    if (!NEAR_EQUAL(mag_sq, 1.0, 100.0*SQRT_SMALL_FASTF)) {
		mat_scale[j] = 1.0/sqrt(mag_sq);
		non_unit = 1;
	    }
	}

	if (non_unit) {
	    bu_log("Illegal transformation matrix in %s for member %s\n",
		   curr_file->obj_name, wmem->wm_name);
	    bu_log(" row vector magnitudes are %g, %g, and %g\n",
		   1.0/mat_scale[0], 1.0/mat_scale[1], 1.0/mat_scale[2]);
	    bn_mat_print("", *dir[i]->rot);
	    for (j = 0; j < 11; j++) {
		if ((j+1)%4 == 0)
		    continue;
		(*dir[i]->rot)[j] *= mat_scale[0];
	    }
	    bn_mat_print("After scaling:", *dir[i]->rot);

	}
	memcpy(wmem->wm_mat, *dir[i]->rot, sizeof(mat_t));

	Readint(&no_of_members, "");	/* get number of members */
	members = (int *)bu_calloc(no_of_members, sizeof(int), "Do_subfigs: members");
	for (j = 0; j < no_of_members; j++)
	    Readint(&members[j], "");

	BU_LIST_INIT(&head2.l);
	for (j = 0; j < no_of_members; j++) {
	    int idx;

	    idx = (members[j] - 1)/2;

	    if (idx >= totentities) {
		bu_log("Subfigure Definition Entity gives Member Entity");
		bu_log("\tDE of %d, largest DE in file is %d\n",
		       members[j], (totentities * 2) - 1);
		continue;
	    }
	    if (dir[idx]->param <= pstart) {
		bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
		       dir[idx]->direct, dir[idx]->name);
		continue;
	    }

	    if (dir[idx]->type == 416) {
		struct file_list *list_ptr;
		char *file_name;
		int found = 0;

		/* external reference */

		Readrec(dir[idx]->param);
		Readint(&entity_type, "");

		if (entity_type != 416) {
		    bu_log("Expected External reference Entity, found %s\n",
			   iges_type(entity_type));
		    continue;
		}

		if (dir[idx]->form != 1) {
		    bu_log("External Reference Entity of form #%d found\n",
			   dir[idx]->form);
		    bu_log("\tOnly form #1 is currently handled\n");
		    continue;
		}

		Readname(&file_name, "");

		/* Check if this external reference is already on the list */
		for (BU_LIST_FOR(list_ptr, file_list, &iges_list.l)) {
		    if (BU_STR_EQUAL(file_name, list_ptr->file_name)) {
			found = 1;
			name = list_ptr->obj_name;
			break;
		    }
		}

		if (!found) {
		    /* Need to add this one to the list */
		    BU_ALLOC(list_ptr, struct file_list);

		    list_ptr->file_name = file_name;
		    if (no_of_members == 1)
			bu_strlcpy(list_ptr->obj_name, dir[subfigdef_index]->name, NAMESIZE+1);
		    else {
			bu_strlcpy(list_ptr->obj_name, "subfig", NAMESIZE+1);
			(void) Make_unique_brl_name(list_ptr->obj_name);
		    }


		    BU_LIST_APPEND(&curr_file->l, &list_ptr->l);

		    name = list_ptr->obj_name;
		} else
		    bu_free((char *)file_name, "Do_subfigs: file_name");

	    } else
		name = dir[idx]->name;

	    if (no_of_members > 1) {
		wmem = mk_addmember(name, &head2.l, NULL, WMOP_UNION);
		memcpy(wmem->wm_mat, dir[idx]->rot, sizeof(mat_t));
	    }
	}

	if (no_of_members > 1)
	    (void)mk_lcomb(fdout, dir[subfigdef_index]->name, &head2, 0,
			   (char *)NULL, (char *)NULL, (unsigned char *)NULL, 0);
    }
int
brep(int entityno)
{

    int sol_num;		/* IGES solid type number */
    int shell_de;		/* Directory sequence number for a shell */
    int orient;			/* Orientation of shell */
    int *void_shell_de;		/* Directory sequence number for an void shell */
    int *void_orient;		/* Orientation of void shell */
    int num_of_voids;		/* Number of inner void shells */
    struct model *m;			/* NMG model */
    struct nmgregion *r;			/* NMG region */
    struct shell **void_shells;		/* List of void shells */
    struct shell *s_outer;		/* Outer shell */
    struct iges_vertex_list *v_list;
    struct iges_edge_list *e_list;
    int i;

    /* 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 , "");
    Readint(&shell_de , "");
    Readint(&orient , "");
    Readint(&num_of_voids , "");

    if (num_of_voids) {
	void_shell_de = (int *)bu_calloc(num_of_voids , sizeof(int) , "BREP: void shell DE's");
	void_orient = (int *)bu_calloc(num_of_voids , sizeof(int) , "BREP: void shell orients");
	void_shells = (struct shell **)bu_calloc(num_of_voids , sizeof(struct shell *) , "BREP: void shell pointers");
	for (i = 0; i < num_of_voids; i++) {
	    Readint(&void_shell_de[i] , "");
	    Readint(&void_orient[i] , "");
	}
    } else {
	void_shell_de = NULL;
	void_orient = NULL;
	void_shells = NULL;
    }

    /* start building */
    m = nmg_mmr();
    r = BU_LIST_FIRST(nmgregion, &m->r_hd);

    /* Put outer shell in region */
    if ((s_outer = Get_outer_shell(r , (shell_de - 1)/2)) == (struct shell *)NULL)
	goto err;

    ON_Brep* outer = ON_Brep::New();
    if (Get_outer_brep(outer, (shell_de - 1)/2, orient))
	goto err;


    /* Put voids in */
    for (i = 0; i < num_of_voids; i++) {
	if ((void_shells[i] = Add_inner_shell(r, (void_shell_de[i] - 1)/2))
	    == (struct shell *)NULL)
	    goto err;
    }

    /* orient loops */
    Orient_loops(r);

    /* orient shells */
    nmg_fix_normals(s_outer , &tol);
    for (i = 0; i < num_of_voids; i++) {
	nmg_fix_normals(void_shells[i] , &tol);
	nmg_invert_shell(void_shells[i]);
    }

    if (do_bots) {
	/* Merge all shells into one */
	for (i = 0; i < num_of_voids; i++)
	    nmg_js(s_outer, void_shells[i], &tol);

	/* write out BOT */
	if (mk_bot_from_nmg(fdout, dir[entityno]->name, s_outer))
	    goto err;
    } else {
	/* Compute "geometry" for region and shell */
	nmg_region_a(r , &tol);

	/* Write NMG solid */
	if (mk_nmg(fdout , dir[entityno]->name , m))
	    goto err;
    }

    if (num_of_voids) {
	bu_free((char *)void_shell_de , "BREP: void shell DE's");
	bu_free((char *)void_orient , "BREP: void shell orients");
	bu_free((char *)void_shells , "brep: void shell list");
    }

    v_list = vertex_root;
    while (v_list != NULL) {
	bu_free((char *)v_list->i_verts , "brep: iges_vertex");
	bu_free((char *)v_list , "brep: vertex list");
	v_list = v_list->next;
    }
    vertex_root = NULL;

    e_list = edge_root;
    while (e_list != NULL) {
	bu_free((char *)e_list->i_edge , "brep:iges_edge");
	bu_free((char *)e_list , "brep: edge list");
	e_list = e_list->next;
    }
    edge_root = NULL;
    return 1;

    err :
	if (num_of_voids) {
	    bu_free((char *)void_shell_de , "BREP: void shell DE's");
	    bu_free((char *)void_orient , "BREP: void shell orients");
	    bu_free((char *)void_shells , "brep: void shell list");
	}
    nmg_km(m);
    return 0;
}
int
block(int entityno)
{

    fastf_t xscale = 0.0;
    fastf_t yscale = 0.0;
    fastf_t zscale = 0.0;
    fastf_t x_1, y_1, z_1;		/* First vertex components */
    fastf_t x_2, y_2, z_2;		/* xdir vector components */
    fastf_t x_3, y_3, z_3;		/* zdir vector components */
    point_t v;			/* the first vertex */
    vect_t xdir;			/* a unit vector */
    vect_t xvec;			/* vector along x-axis */
    vect_t ydir;			/* a unit vector */
    vect_t yvec;			/* vector along y-axis */
    vect_t zdir;			/* a unit vector */
    vect_t zvec;			/* vector along z-axis */
    point_t pts[9];			/* array of points */
    int sol_num;		/* IGES solid type number */

    /* Default values */
    x_1 = 0.0;
    y_1 = 0.0;
    z_1 = 0.0;
    x_2 = 1.0;
    y_2 = 0.0;
    z_2 = 0.0;
    x_3 = 0.0;
    y_3 = 0.0;
    z_3 = 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, "");
    Readcnv(&xscale, "");
    Readcnv(&yscale, "");
    Readcnv(&zscale, "");
    Readcnv(&x_1, "");
    Readcnv(&y_1, "");
    Readcnv(&z_1, "");
    Readflt(&x_2, "");
    Readflt(&y_2, "");
    Readflt(&z_2, "");
    Readflt(&x_3, "");
    Readflt(&y_3, "");
    Readflt(&z_3, "");

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

    /*
     * Making the necessaries. First an id is made for the new entity.
     * Then the vertices for the bottom and top faces are found.  Point
     * is located in the lower left corner of the solid, and the vertices are
     * counted in the counter-clockwise direction, around the bottom face.
     * Next these vertices are extruded to form the top face.  The points
     * thus made are loaded into an array of points and handed off to mk_arb8().
     * Make and unitize necessary vectors.
     */

    VSET(xdir, x_2, y_2, z_2);			/* Makes x-dir vector */
    VUNITIZE(xdir);
    VSET(zdir, x_3, y_3, z_3);			/* Make z-dir vector */
    VUNITIZE(zdir);
    VCROSS(ydir, zdir, xdir);		/* Make y-dir vector */

    /* Scale all vectors */

    VSCALE(xvec, xdir, xscale);
    VSCALE(zvec, zdir, zscale);
    VSCALE(yvec, ydir, yscale);

    /* Make the bottom face. */

    VSET(v, x_1, y_1, z_1);			/* Yields first vertex */
    VMOVE(pts[0], v);			/* put first vertex into array */
    VADD2(pts[1], v, xvec);			/* Finds second vertex */
    VADD3(pts[2], v, xvec, yvec);		/* Finds third vertex */
    VADD2(pts[3], v, yvec);			/* Finds fourth vertex */

    /* Now extrude the bottom face to make the top.
     */

    VADD2(pts[4], v, zvec);			/* Finds fifth vertex */
    VADD2(pts[5], pts[1], zvec);		/* Finds sixth vertex */
    VADD2(pts[6], pts[2], zvec);		/* Finds seventh vertex */
    VADD2(pts[7], pts[3], zvec);		/* Find eighth vertex */


    /* Now the information is handed off to mk_arb8(). */

    mk_arb8(fdout, dir[entityno]->name, &pts[0][X]);

    return 1;


}
int
cyl(int entityno)
{
    fastf_t radius = 0.0;
    point_t base;		/* center point of base */
    vect_t height;
    vect_t hdir;		/* direction in which to grow height */
    fastf_t scale_height = 0.0;
    fastf_t x_1;
    fastf_t y_1;
    fastf_t z_1;
    fastf_t x_2;
    fastf_t y_2;
    fastf_t z_2;
    int sol_num;		/* IGES solid type number */

    /* Default values */
    x_1 = 0.0;
    y_1 = 0.0;
    z_1 = 0.0;
    x_2 = 0.0;
    y_2 = 0.0;
    z_2 = 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, "");
    Readcnv(&scale_height, "");
    Readcnv(&radius, "");
    Readcnv(&x_1, "");
    Readcnv(&y_1, "");
    Readcnv(&z_1, "");
    Readcnv(&x_2, "");
    Readcnv(&y_2, "");
    Readcnv(&z_2, "");

    if (radius < SMALL_FASTF || scale_height < SMALL_FASTF) {
	bu_log("Illegal parameters for entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	if (ZERO(radius)) {
	    bu_log("\tradius of cylinder is zero!!!\n");
	    return 0;
	}
	if (ZERO(scale_height)) {
	    bu_log("\theight of cylinder is zero!!!\n");
	    return 0;
	}

	if (radius < 0.0) {
	    bu_log("\tUsing the absolute value of a negative radius\n");
	    radius = (-radius);
	}

	if (scale_height < 0.0) {
	    bu_log("\tUsing absolute value of a negative height and reversing axis direction\n");
	    scale_height = (-scale_height);
	    x_2 = (-x_2);
	    y_2 = (-y_2);
	    z_2 = (-z_2);
	}

    }


    /*
     * Making the necessaries. First an id is made for the new entity, then
     * the x, y, z coordinates for its vertices are converted to vectors with
     * VSET(), and finally the libwdb routine that makes an analogous BRL-CAD
     * solid is called.
     */

    VSET(base, x_1, y_1, z_1);
    VSET(hdir, x_2, y_2, z_2);
    VUNITIZE(hdir);

    /* Multiply the hdir * scale_height to obtain height. */

    VSCALE(height, hdir, scale_height);

    if (mk_rcc(fdout, dir[entityno]->name, base, height, radius) < 0) {
	bu_log("Unable to write entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	return 0;
    }
    return 1;

}
Beispiel #17
0
int
spline(int entityno, struct face_g_snurb **b_patch)
{
    int k1;	/* upper index of first sum */
    int k2;	/* upper index of second sum */
    int m1;	/* degree of 1st set of basis functions */
    int m2;	/* degree of 2nd set of basis functions */
    int prop1;	/* !0 if closed in first direction */
    int prop2;	/* !0 if closed in second direction */
    int prop3;	/* !0 if polynomial (else rational) */
    int prop4;	/* !0 if periodic in first direction */
    int prop5;	/* !0 if periodic in second direction */
    int sol_num; /* IGES solid type number */
    int n1, n2;
    int i, j, k;
    int count = 0;
    int point_size;
    fastf_t min_knot;
    double max_wt;
    double scan;

    /* 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, "");
    Readint(&k1, "");
    Readint(&k2, "");
    Readint(&m1, "");
    Readint(&m2, "");
    Readint(&prop1, "");
    Readint(&prop2, "");
    Readint(&prop3, "");
    Readint(&prop4, "");
    Readint(&prop5, "");

    n1 = k1 - m1 + 1;
    n2 = k2 - m2 + 1;

    /* spl_new: Creates a spline surface data structure
     * u_order (e.g. cubic = order 4)
     * v_order
     * num_u (e.g. num control points + order)
     * num_v
     * num_rows num control points in V direction
     * num_cols num control points in U direction
     * point_size number of values in a point (e.g. 3 or 4)
     */

    if (prop3 == 0) {
	point_size = 4;
    } else {
	point_size = 3;
    }

    (*b_patch) = rt_nurb_new_snurb(
	m1+1, m2+1,
	n1+2*m1+1, n2+2*m2+1,
	k2+1, k1+1,
	RT_NURB_MAKE_PT_TYPE(point_size, 2,
			     (prop3 == 0 ? RT_NURB_PT_RATIONAL : RT_NURB_PT_NONRAT)),
	(struct resource *)NULL);

    /* U knot vector */
    min_knot = 0.0;
    for (i = 0; i <= n1+2*m1; i++) {
	Readdbl(&scan, "");
	(*b_patch)->u.knots[i] = scan; /* double to fastf_t */
	if ((*b_patch)->u.knots[i] < min_knot)
	    min_knot = (*b_patch)->u.knots[i];
    }

    if (min_knot < 0.0) {
	for (i = 0; i <= n1+2*m1; i++) {
	    (*b_patch)->u.knots[i] -= min_knot;
	}
    }

    min_knot = 0.0;
    /* V knot vector */
    for (i = 0; i <= n2+2*m2; i++) {
	Readdbl(&scan, "");
	(*b_patch)->v.knots[i] = scan; /* double to fastf_t */
	if ((*b_patch)->v.knots[i] < min_knot)
	    min_knot = (*b_patch)->v.knots[i];
    }
    if (min_knot < 0.0) {
	for (i = 0; i <= n2+2*m2; i++) {
	    (*b_patch)->v.knots[i] -= min_knot;
	}
    }


    /* weights */
    max_wt = 0.0;
    count = 0;
    for (i = 0; i <= k2; i++) {
	for (j = 0; j <= k1; j++) {
	    if (point_size == 4) {
		Readdbl(&scan, "");
		(*b_patch)->ctl_points[count*4 + 3] = scan; /* double to fastf_t */
		if ((*b_patch)->ctl_points[count*4 + 3] > max_wt)
		    max_wt = (*b_patch)->ctl_points[count*4 + 3];
	    } else {
		Readdbl(&max_wt, "");
	    }
	    count++;
	}
    }

    /* control points */
    count = 0;
    for (i = 0; i <= k2; i++) {
	for (j = 0; j <= k1; j++) {
	    Readcnv(&(*b_patch)->ctl_points[count*point_size], "");
	    Readcnv(&(*b_patch)->ctl_points[count*point_size + 1], "");
	    Readcnv(&(*b_patch)->ctl_points[count*point_size + 2], "");
	    count++;
	}
    }

    if (point_size == 4) {
	/* apply weights */
	count = 0;
	for (i = 0; i <= k2; i++) {
	    for (j = 0; j <= k1; j++) {
		for (k = 0; k < 3; k++)
		    (*b_patch)->ctl_points[count*4 + k] *= (*b_patch)->ctl_points[count*4 + 3];
		count++;
	    }
	}
    }

    return 1;
}
Beispiel #18
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;


}
struct faceuse *
Make_planar_face(struct shell *s, int entityno, int face_orient)
{

    int sol_num;	/* IGES solid type number */
    int no_of_edges;	/* edge count for this loop */
    int no_of_param_curves;
    int vert_count = 0;	/* Actual number of vertices used to make face */
    struct iges_edge_use *edge_list;	/* list of edgeuses from iges loop entity */
    struct faceuse *fu = NULL;	/* NMG face use */
    struct loopuse *lu;		/* NMG loop use */
    struct vertex ***verts;	/* list of vertices */
    struct iges_vertex_list *v_list;
    int done;
    int i, j, k;

    /* Acquiring Data */

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

    Readrec(dir[entityno]->param);
    Readint(&sol_num, "");
    if (sol_num != 508) {
	bu_exit(1, "ERROR: Entity #%d is not a loop (it's a %s)\n", entityno, iges_type(sol_num));
    }

    Readint(&no_of_edges, "");
    edge_list = (struct iges_edge_use *)bu_calloc(no_of_edges, sizeof(struct iges_edge_use) ,
						  "Make_face (edge_list)");
    for (i = 0; i < no_of_edges; i++) {
	Readint(&edge_list[i].edge_is_vertex, "");
	Readint(&edge_list[i].edge_de, "");
	Readint(&edge_list[i].index, "");
	Readint(&edge_list[i].orient, "");
	if (!face_orient) {
	    /* need opposite orientation of edge */
	    if (edge_list[i].orient)
		edge_list[i].orient = 0;
	    else
		edge_list[i].orient = 1;
	}
	edge_list[i].root = (struct iges_param_curve *)NULL;
	Readint(&no_of_param_curves, "");
	for (j = 0; j < no_of_param_curves; j++) {
	    struct iges_param_curve *new_crv;
	    struct iges_param_curve *crv;

	    Readint(&k, "");	/* ignore iso-parametric flag */

	    BU_ALLOC(new_crv, struct iges_param_curve);
	    if (edge_list[i].root == (struct iges_param_curve *)NULL)
		edge_list[i].root = new_crv;
	    else {
		crv = edge_list[i].root;
		while (crv->next != (struct iges_param_curve *)NULL)
		    crv = crv->next;
		crv->next = new_crv;
	    }
	    Readint(&new_crv->curve_de, "");
	    new_crv->next = (struct iges_param_curve *)NULL;
	}
    }

    verts = (struct vertex ***)bu_calloc(no_of_edges, sizeof(struct vertex **) ,
					 "Make_face: vertex_list **");

    for (i = 0; i < no_of_edges; i++) {
	if (face_orient)
	    verts[i] = Get_vertex(&edge_list[i]);
	else
	    verts[no_of_edges-1-i] = Get_vertex(&edge_list[i]);
    }

    /* eliminate zero length edges */
    vert_count = no_of_edges;
    done = 0;
    while (!done) {
	done = 1;
	for (i = 0; i < vert_count; i++) {
	    k = i + 1;
	    if (k == vert_count)
		k = 0;

	    if (verts[i] == verts[k]) {
		bu_log("Ignoring zero length edge\n");
		done = 0;
		vert_count--;
		for (j = i; j < vert_count; j++)
		    verts[j] = verts[j+1];
	    }
	}
    }

    if (vert_count) {
	plane_t pl;		/* Plane equation for face */
	fastf_t area;		/* area of loop */
	fastf_t dist;
	vect_t min2max;
	point_t outside_pt;

	fu = nmg_cmface(s, verts, vert_count);

	/* associate geometry */
	v_list = vertex_root;
	while (v_list != NULL) {
	    for (i = 0; i < v_list->no_of_verts; i++) {
		if (v_list->i_verts[i].v != NULL && v_list->i_verts[i].v->vg_p == NULL) {
		    NMG_CK_VERTEX(v_list->i_verts[i].v);
		    nmg_vertex_gv(v_list->i_verts[i].v ,
				  v_list->i_verts[i].pt);
		}
	    }
	    v_list = v_list->next;
	}

	lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
	NMG_CK_LOOPUSE(lu);

	area = nmg_loop_plane_area(lu, pl);
	if (area < 0.0) {
	    bu_log("Could not calculate area for face (entityno = %d)\n", entityno);
	    nmg_pr_fu_briefly(fu, "");
	    nmg_kfu(fu);
	    fu = (struct faceuse *)NULL;
	    goto err;
	}

	nmg_face_g(fu, pl);
	nmg_face_bb(fu->f_p, &tol);

	/* find a point that is surely outside the loop */
	VSUB2(min2max, fu->f_p->max_pt, fu->f_p->min_pt);
	VADD2(outside_pt, fu->f_p->max_pt, min2max);

	/* move it to the plane of the face */
	dist = DIST_PT_PLANE(outside_pt, pl);
	VJOIN1(outside_pt, outside_pt, -dist, pl);

	if (nmg_class_pt_lu_except(outside_pt, lu, (struct edge *)NULL, &tol) != NMG_CLASS_AoutB) {
	    nmg_reverse_face(fu);
	    if (fu->orientation != OT_SAME) {
		fu = fu->fumate_p;
		if (fu->orientation != OT_SAME)
		    bu_exit(1, "ERROR: no OT_SAME use for a face!\n");
	    }
	}
    } else
	bu_log("No edges left!\n");

err:
    bu_free((char *)edge_list, "Make_face (edge_list)");
    bu_free((char *)verts, "Make_face (vertexlist)");
    return fu;
}