Beispiel #1
0
/**
 * R T _ P G _ P L O T _ P O L Y
 *
 * Convert to vlist, draw as polygons.
 */
int
rt_pg_plot_poly(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol))
{
    size_t i;
    size_t p;	/* current polygon number */
    struct rt_pg_internal *pgp;

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

    for (p = 0; p < pgp->npoly; p++) {
	struct rt_pg_face_internal *pp;
	vect_t aa, bb, norm;

	pp = &pgp->poly[p];
	if (pp->npts < 3)
	    continue;
	VSUB2(aa, &pp->verts[3*(0)], &pp->verts[3*(1)]);
	VSUB2(bb, &pp->verts[3*(0)], &pp->verts[3*(2)]);
	VCROSS(norm, aa, bb);
	VUNITIZE(norm);
	RT_ADD_VLIST(vhead, norm, BN_VLIST_POLY_START);

	RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_MOVE);
	for (i=0; i < pp->npts-1; i++) {
	    RT_ADD_VLIST(vhead, &pp->verts[3*i], BN_VLIST_POLY_DRAW);
	}
	RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_END);
    }
    return 0;		/* OK */
}
Beispiel #2
0
HIDDEN int
add_operator(struct ged *gedp, struct bu_list *hp, char ch, short int *last_tok)
{
    char illegal[2];

    BU_CK_LIST_HEAD(hp);

    switch (ch) {
	case 'u':
	    append_union(hp);
	    *last_tok = TOK_UNION;
	    break;
	case '+':
	    append_inter(hp);
	    *last_tok = TOK_INTER;
	    break;
	case '-':
	    append_subtr(hp);
	    *last_tok = TOK_SUBTR;
	    break;
	default:
	    illegal[0] = ch;
	    illegal[1] = '\0';
	    bu_vls_printf(gedp->ged_result_str, "Illegal operator: %s, aborting\n", illegal);
	    free_tokens(hp);
	    return GED_ERROR;
    }
    return GED_OK;
}
Beispiel #3
0
int
rt_superell_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    int i;
    struct rt_superell_internal *eip;
    fastf_t top[16*3];
    fastf_t middle[16*3];
    fastf_t bottom[16*3];

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    eip = (struct rt_superell_internal *)ip->idb_ptr;
    RT_SUPERELL_CK_MAGIC(eip);

    rt_superell_16pts(top, eip->v, eip->a, eip->b);
    rt_superell_16pts(bottom, eip->v, eip->b, eip->c);
    rt_superell_16pts(middle, eip->v, eip->a, eip->c);

    RT_ADD_VLIST(vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i=0; i<16; i++) {
        RT_ADD_VLIST(vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    }

    RT_ADD_VLIST(vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i=0; i<16; i++) {
        RT_ADD_VLIST(vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    }

    RT_ADD_VLIST(vhead, &middle[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i=0; i<16; i++) {
        RT_ADD_VLIST(vhead, &middle[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    }
    return 0;
}
Beispiel #4
0
int
rt_obj_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
{
    int id;
    const struct rt_functab *ft;

    if (!vhead || !ip)
	return -1;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    if (ttol) RT_CK_TESS_TOL(ttol);
    if (tol) BN_CK_TOL(tol);

    id = ip->idb_minor_type;
    if (id < 0)
	return -2;

    ft = &rt_functab[id];
    if (!ft)
	return -3;
    if (!ft->ft_plot)
	return -4;

    return ft->ft_plot(vhead, ip, ttol, tol, NULL);
}
Beispiel #5
0
HIDDEN int
wdb_add_operator(Tcl_Interp *interp, struct bu_list *hp, char ch, short int *last_tok)
{
    char illegal[2];

    BU_CK_LIST_HEAD(hp);

    switch (ch) {
	case 'u':
	    wdb_append_union(hp);
	    *last_tok = WDB_TOK_UNION;
	    break;
	case '+':
	    wdb_append_inter(hp);
	    *last_tok = WDB_TOK_INTER;
	    break;
	case '-':
	    wdb_append_subtr(hp);
	    *last_tok = WDB_TOK_SUBTR;
	    break;
	default:
	    illegal[0] = ch;
	    illegal[1] = '\0';
	    Tcl_AppendResult(interp, "Illegal operator: ", illegal,
			     ", aborting\n", (char *)NULL);
	    wdb_free_tokens(hp);
	    return TCL_ERROR;
    }
    return TCL_OK;
}
Beispiel #6
0
/**
 * R T _ P G _ P L O T
 */
int
rt_pg_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    size_t i;
    size_t p;	/* current polygon number */
    struct rt_pg_internal *pgp;

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

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

	pp = &pgp->poly[p];
	RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)],
		     BN_VLIST_LINE_MOVE);
	for (i=0; i < pp->npts; i++) {
	    RT_ADD_VLIST(vhead, &pp->verts[3*i],
			 BN_VLIST_LINE_DRAW);
	}
    }
    return 0;		/* OK */
}
Beispiel #7
0
HIDDEN int
wdb_add_operand(Tcl_Interp *interp, struct bu_list *hp, char *name)
{
    char *ptr_lparen;
    char *ptr_rparen;
    int name_len;
    union tree *node;
    struct tokens *tok;

    BU_CK_LIST_HEAD(hp);

    ptr_lparen = strchr(name, '(');
    ptr_rparen = strchr(name, ')');

    RT_GET_TREE( node, &rt_uniresource );
    node->magic = RT_TREE_MAGIC;
    node->tr_op = OP_DB_LEAF;
    node->tr_l.tl_mat = (matp_t)NULL;
    if (ptr_lparen || ptr_rparen) {
	int tmp1, tmp2;

	if (ptr_rparen)
	    tmp1 = ptr_rparen - name;
	else
	    tmp1 = (-1);
	if (ptr_lparen)
	    tmp2 = ptr_lparen - name;
	else
	    tmp2 = (-1);

	if (tmp2 == (-1) && tmp1 > 0)
	    name_len = tmp1;
	else if (tmp1 == (-1) && tmp2 > 0)
	    name_len = tmp2;
	else if (tmp1 > 0 && tmp2 > 0) {
	    if (tmp1 < tmp2)
		name_len = tmp1;
	    else
		name_len = tmp2;
	}
	else {
	    Tcl_AppendResult(interp, "Cannot determine length of operand name: ",
			     name, ", aborting\n", (char *)NULL);
	    return (0);
	}
    } else
	name_len = strlen( name );

    node->tr_l.tl_name = (char *)bu_malloc(name_len+1, "node name");
    bu_strlcpy(node->tr_l.tl_name, name, name_len+1);

    tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
    tok->type = WDB_TOK_TREE;
    tok->tp = node;
    BU_LIST_INSERT(hp, &tok->l);
    return (name_len);
}
Beispiel #8
0
HIDDEN int
add_operand(struct ged *gedp, struct bu_list *hp, char *name)
{
    char *ptr_lparen;
    char *ptr_rparen;
    int name_len;
    union tree *node;
    struct tokens *tok;

    BU_CK_LIST_HEAD(hp);

    ptr_lparen = strchr(name, '(');
    ptr_rparen = strchr(name, ')');

    RT_GET_TREE(node, &rt_uniresource);
    node->tr_op = OP_DB_LEAF;
    node->tr_l.tl_mat = (matp_t)NULL;
    if (ptr_lparen || ptr_rparen) {
	int tmp1, tmp2;

	if (ptr_rparen)
	    tmp1 = ptr_rparen - name;
	else
	    tmp1 = (-1);
	if (ptr_lparen)
	    tmp2 = ptr_lparen - name;
	else
	    tmp2 = (-1);

	if (tmp2 == (-1) && tmp1 > 0)
	    name_len = tmp1;
	else if (tmp1 == (-1) && tmp2 > 0)
	    name_len = tmp2;
	else if (tmp1 > 0 && tmp2 > 0) {
	    if (tmp1 < tmp2)
		name_len = tmp1;
	    else
		name_len = tmp2;
	} else {
	    bu_vls_printf(gedp->ged_result_str, "Cannot determine length of operand name: %s, aborting\n", name);
	    return 0;
	}
    } else
	name_len = (int)strlen(name);

    node->tr_l.tl_name = (char *)bu_malloc(name_len+1, "node name");
    bu_strlcpy(node->tr_l.tl_name, name, name_len+1);

    BU_ALLOC(tok, struct tokens);
    tok->type = TOK_TREE;
    tok->tp = node;
    BU_LIST_INSERT(hp, &tok->l);
    return name_len;
}
Beispiel #9
0
void show_sites (struct bu_list *sl)
{
    struct site *sp;

    BU_CK_LIST_HEAD(sl);

    for (BU_LIST_FOR(sp, site, sl)) {
	bu_log("I got a site (%g, %g, %g)\n",
	       sp->s_x, sp->s_y, sp->s_z);
    }
}
Beispiel #10
0
int
rt_xxx_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    struct rt_xxx_internal *xxx_ip;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    xxx_ip = (struct rt_xxx_internal *)ip->idb_ptr;
    RT_XXX_CK_MAGIC(xxx_ip);

    return -1;
}
Beispiel #11
0
HIDDEN void
wdb_append_inter(struct bu_list *hp)
{
    struct tokens *tok;

    BU_CK_LIST_HEAD(hp);

    tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
    tok->type = WDB_TOK_INTER;
    tok->tp = (union tree *)NULL;
    BU_LIST_INSERT( hp, &tok->l );
}
Beispiel #12
0
HIDDEN void
append_union(struct bu_list *hp)
{
    struct tokens *tok;

    BU_CK_LIST_HEAD(hp);

    BU_ALLOC(tok, struct tokens);
    tok->type = TOK_UNION;
    tok->tp = (union tree *)NULL;
    BU_LIST_INSERT(hp, &tok->l);
}
Beispiel #13
0
HIDDEN void
wdb_append_inter(struct bu_list *hp)
{
    struct tokens *tok;

    BU_CK_LIST_HEAD(hp);

    BU_ALLOC(tok, struct tokens);
    tok->type = WDB_TOK_INTER;
    tok->tp = (union tree *)NULL;
    BU_LIST_INSERT(hp, &tok->l);
}
Beispiel #14
0
void enqueue_site (struct bu_list *sl, fastf_t x, fastf_t y, fastf_t z)
{
    struct site	*sp;

    BU_CK_LIST_HEAD(sl);

    sp = (struct site *) bu_malloc(sizeof(struct site), "site structure");
    sp -> s_magic = SITE_MAGIC;
    sp -> s_x = x;
    sp -> s_y = y;
    sp -> s_z = z;

    BU_LIST_INSERT(sl, &(sp -> l));
}
Beispiel #15
0
void enqueue_site (struct bu_list *sl, fastf_t x, fastf_t y, fastf_t z)
{
    struct site *sp;

    BU_CK_LIST_HEAD(sl);

    BU_ALLOC(sp, struct site);
    sp->s_magic = SITE_MAGIC;
    sp->s_x = x;
    sp->s_y = y;
    sp->s_z = z;

    BU_LIST_INSERT(sl, &(sp->l));
}
Beispiel #16
0
HIDDEN void
wdb_free_tokens(struct bu_list *hp)
{
    struct tokens *tok;

    BU_CK_LIST_HEAD(hp);

    while (BU_LIST_WHILE(tok, tokens, hp)) {
	BU_LIST_DEQUEUE(&tok->l);
	if (tok->type == WDB_TOK_TREE) {
	    db_free_tree(tok->tp, &rt_uniresource);
	}
    }
}
/**
 * text is for the title line
 */
static void
show_scripts(struct bu_list *sl, char *text)
{
    int i;
    struct script_rec *srp;

    BU_CK_LIST_HEAD(sl);

    i = 0;
    bu_log("- - - - - - - The command-line scripts - - - - - - -\n%s\n", text);
    for (BU_LIST_FOR(srp, script_rec, sl)) {
	BU_CKMAG(srp, SCRIPT_REC_MAGIC, "script record");

	bu_log("%d. script %s '%s'\n",
	       ++i,
	       (srp->sr_type == READING_STRING) ? "string" :
	       (srp->sr_type == READING_FILE) ? "file" : "???",
	       bu_vls_addr(&(srp->sr_script)));
    }
    bu_log("- - - - - - - - - - - - - - - - - - - - - - - - - -\n");
}
/**
 * string is a literal or a file name
 */
static void
enqueue_script(struct bu_list *qp, int type, char *string)
{
    struct script_rec *srp;
    FILE *cfPtr;
    struct bu_vls str = BU_VLS_INIT_ZERO;

    BU_CK_LIST_HEAD(qp);

    BU_ALLOC(srp, struct script_rec);
    srp->sr_magic = SCRIPT_REC_MAGIC;
    srp->sr_type = type;
    bu_vls_init(&(srp->sr_script));

    /*Check if supplied file name is local or in brlcad's nirt data dir*/
    if (type == READING_FILE) {
	bu_vls_trunc(&str, 0);
	bu_vls_printf(&str, "%s", string);
	cfPtr = fopen(bu_vls_addr(&str), "rb");
	if (cfPtr == NULL) {
	    bu_vls_trunc(&str, 0);
	    bu_vls_printf(&str, "%s/%s.nrt", bu_brlcad_data("nirt", 0), string);
	    cfPtr = fopen(bu_vls_addr(&str), "rb");
	    if (cfPtr != NULL) {
		fclose(cfPtr);
	    } else {
		bu_vls_trunc(&str, 0);
		bu_vls_printf(&str, "%s", string);
	    }
	} else {
	    fclose(cfPtr);
	}
	bu_vls_printf(&(srp->sr_script), "%s", bu_vls_addr(&str));
    } else {
	bu_vls_strcat(&(srp->sr_script), string);
    }
    BU_LIST_INSERT(qp, &(srp->l));
    bu_vls_free(&str);
}
int
rt_metaball_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    struct rt_metaball_internal *mb;
    struct wdb_metaballpt *mbpt;
    point_t bsc;
    fastf_t rad;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);
    rad = rt_metaball_get_bounding_sphere(&bsc, mb->threshold, mb);
    /* cope with the case where 0 points are defined. */
    if (rad<0)
	return 0;
#if PLOT_THE_BIG_BOUNDING_SPHERE
    rt_metaball_plot_sph(vhead, &bsc, rad);
#endif
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
	rt_metaball_plot_sph(vhead, &mbpt->coord, mbpt->fldstr / mb->threshold);
    return 0;
}
void
rt_metaball_plot_sph(struct bu_list *vhead, point_t *center, fastf_t radius)
{
    fastf_t top[16*3], middle[16*3], bottom[16*3];
    point_t a, b, c;
    int i;

    BU_CK_LIST_HEAD(vhead);

    VSET(a, radius, 0, 0);
    VSET(b, 0, radius, 0);
    VSET(c, 0, 0, radius);
    rt_ell_16pts(top, *center, a, b);
    rt_ell_16pts(bottom, *center, b, c);
    rt_ell_16pts(middle, *center, a, c);

    RT_ADD_VLIST(vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    RT_ADD_VLIST(vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    RT_ADD_VLIST(vhead, &middle[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &middle[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
}
/**********************************************************
 *   Code for identifying semi-flat patches in bots
 *   and creating wireframe edges
 **********************************************************/
extern "C" int
rt_bot_adaptive_plot(struct rt_db_internal *ip, const struct rt_view_info *info)
{
    struct rt_bot_internal *bot;
    RT_CK_DB_INTERNAL(ip);
    BU_CK_LIST_HEAD(info->vhead);
    bot = (struct rt_bot_internal *)ip->idb_ptr;
    RT_BOT_CK_MAGIC(bot);
    vect_t gvects[6];
    VSET(gvects[0], -1,0,0);
    VSET(gvects[1], 0,-1,0);
    VSET(gvects[2], 0,0,-1);
    VSET(gvects[3], 1,0,0);
    VSET(gvects[4], 0,1,0);
    VSET(gvects[5], 0,0,1);

    if (bot->num_vertices <= 0 || !bot->vertices || bot->num_faces <= 0 || !bot->faces)
        return 0;

    /* Declare key containers */
    double *face_normals= (double *)bu_calloc(bot->num_faces * 3, sizeof(double), "normals");
    /* Stash all the initial categorization test results - can be re-used later */
//    unsigned int *categorization_results = (unsigned int *)bu_calloc(sizeof(unsigned int) * bot->num_faces * 6, "categorization results");
    /* Initial group assignments */
    unsigned int *groups = (unsigned int *)bu_calloc(bot->num_faces, sizeof(unsigned int), "groups");
    /* Initially, patch breakdown is made in a faces -> patch_id map */
    unsigned int *patches= (unsigned int *)bu_calloc(bot->num_faces, sizeof(unsigned int), "patch_id_numbers");
    /* Don't know yet how big these needs to be */
    unsigned int *vert_to_face = NULL;

    /* Sanity check vertex indices in face definitions */
    for (unsigned int i = 0; i < bot->num_faces; ++i) {
        if ((unsigned int)bot->faces[i*3+0] > (unsigned int)(bot->num_vertices)) return 0;
        if ((unsigned int)bot->faces[i*3+1] > (unsigned int)(bot->num_vertices)) return 0;
        if ((unsigned int)bot->faces[i*3+2] > (unsigned int)(bot->num_vertices)) return 0;
    }

    /* Pre-compute face normals once */
    for (unsigned int i = 0; i < bot->num_faces; i++) {
	vect_t a, b, norm_dir;
	VSUB2(a, &bot->vertices[bot->faces[i*3+1]*3], &bot->vertices[bot->faces[i*3]*3]);
	VSUB2(b, &bot->vertices[bot->faces[i*3+2]*3], &bot->vertices[bot->faces[i*3]*3]);
	VCROSS(norm_dir, a, b);
	VUNITIZE(norm_dir);
	face_normals[i*3]=norm_dir[0];
	face_normals[i*3+1]=norm_dir[1];
	face_normals[i*3+2]=norm_dir[2];
    }

    /* Calculate categorization results and assign groups */
    for (unsigned int i = 0; i < bot->num_faces; i++) {
	int result_max = 0;
	double result = 0.0;
	double vdot = 0.0;
	vect_t norm_dir;
	VSET(norm_dir, face_normals[i*3], face_normals[i*3+1], face_normals[i*3+2]);
	for (unsigned int j=0; j < 6; j++) {
	    vdot = VDOT(gvects[j],norm_dir);
	    //categorization_results[i*j] = vdot;
	    if (vdot > result) {
		result_max = j;
		result = vdot;
	    }
	}
        groups[i] = result_max;
    }
    bu_free(face_normals, "face_normals");

    /* Determine the maximum number of faces associated with any one vertex */
    unsigned int *vert_face_cnt = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "vert face cnt");
    for (unsigned int i = 0; i < bot->num_faces; i++) {
        vert_face_cnt[bot->faces[i*3+0]]++;
        vert_face_cnt[bot->faces[i*3+1]]++;
        vert_face_cnt[bot->faces[i*3+2]]++;
    }
    unsigned int max_face_cnt = 0;
    for (unsigned int i = 0; i < bot->num_vertices; i++) {
	if (vert_face_cnt[i] > max_face_cnt)
	    max_face_cnt = vert_face_cnt[i];
    }
    /* Now, allocate a 2D array that can hold the full vert->face map
     * and populate it */
    vert_to_face = (unsigned int *)bu_calloc(bot->num_vertices * max_face_cnt, sizeof(unsigned int), "map");
    unsigned int *vert_sizes = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "map");
    for (unsigned int i = 0; i < bot->num_faces; i++) {
	for (unsigned int j = 0; j < 3; j++) {
	    unsigned int vert = bot->faces[i*3+j];
            unsigned int k = vert_sizes[vert];
            /* rows are vertex indexes, columns hold the faces */
            /* Need to increment face index by one so we can reference
	     * the first face and still use the true/false test that 0 allows */
	    vert_to_face[max_face_cnt * vert + k] = i + 1;
            vert_sizes[vert]++;
            //bu_log("vert_to_face(%d,%d)[%d] = %d\n", vert, k, max_face_cnt * vert + k, i + 1);
	}
    }


    /* Order the groups by number of bots */
    /* Note - needed only when group boarders are not enforced in patch building */
//    unsigned int group_cnt[6] = {0};
    unsigned int ordered_groups[6] = {0,1,2,3,4,5};
/*    for (unsigned int i = 0; i < bot->num_faces; i++) {
        group_cnt[groups[i]]++;
    }
    for (unsigned int i = 0; i < 6; i++) {
        unsigned int more = 0;
	for (unsigned int j = 0; j < 6; j++) {
            if (group_cnt[j] > group_cnt[i]) more++;
	}
        ordered_groups[more] = i;
    }
*/


    // All faces must belong to some patch - continue until all faces are processed
    unsigned int patch_cnt = 0;
    for (unsigned int i = 0; i < 6; i++) {
	int unused = 0;
	while (unused != -1) {
            unsigned int face_stp = 0;
	    // Start a new patch
	    unused = -1;
	    patch_cnt++;
	    // Find remaining face in group
	    while (unused == -1 && face_stp < bot->num_faces) {
		if (ordered_groups[i] == groups[face_stp] && !patches[face_stp]) {
                   unused = face_stp;
		}
                face_stp++;
            }
	    if (unused != -1) {
		std::queue<unsigned int> face_queue;
		face_queue.push(unused);
		patches[unused] = patch_cnt;
		while (!face_queue.empty()) {
		    unsigned int face_num = face_queue.front();
		    face_queue.pop();
		    for (unsigned int k = 0; k < 3; k++) {
			unsigned int vert_id = bot->faces[face_num*3+k];
			for (unsigned int l = 0; l < vert_face_cnt[vert_id]; l++) {
			    unsigned int new_face = vert_to_face[max_face_cnt * vert_id  + l] - 1;
			    if (groups[new_face] == ordered_groups[i] && !patches[new_face]) {
				face_queue.push(new_face);
				patches[new_face] = patch_cnt;
			    }
			}
		    }
		}
	    }
	}
    }
    bu_free(groups, "groups");
    bu_free(vert_to_face, "vert_to_face");

    unsigned int *patch_vert_cnt = vert_sizes;
    memset(patch_vert_cnt, 0, bot->num_vertices * sizeof(unsigned int));
    unsigned int *vert_edge_status = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "vert status");
    for (unsigned int i = 0; i < patch_cnt; i++) {
        memset(patch_vert_cnt, 0, bot->num_vertices * sizeof(unsigned int));
	for (unsigned int j = 0; j < bot->num_faces; j++) {
	    if (patches[j] == i+1) {
		patch_vert_cnt[bot->faces[j*3+0]]++;
		patch_vert_cnt[bot->faces[j*3+1]]++;
		patch_vert_cnt[bot->faces[j*3+2]]++;
	    }
	}
	for (unsigned int j = 0; j < bot->num_vertices; j++) {
	    if (patch_vert_cnt[j] && patch_vert_cnt[j] != vert_face_cnt[j]) {
		vert_edge_status[j]++;
	    }
	}
    }
    bu_free(patches, "patches");
    bu_free(patch_vert_cnt, "patch_vert_cnt");
    bu_free(vert_face_cnt, "vert_face_cnt");

    for (unsigned int j = 0; j < bot->num_faces; j++) {
	if (vert_edge_status[bot->faces[j*3+0]] &&  vert_edge_status[bot->faces[j*3+1]]) {
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+0]*3]), BN_VLIST_LINE_MOVE);
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+1]*3]), BN_VLIST_LINE_DRAW);
	}
        if (vert_edge_status[bot->faces[j*3+1]] &&  vert_edge_status[bot->faces[j*3+2]]) {
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+1]*3]), BN_VLIST_LINE_MOVE);
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+2]*3]), BN_VLIST_LINE_DRAW);
	}
	if (vert_edge_status[bot->faces[j*3+2]] &&  vert_edge_status[bot->faces[j*3+0]]) {
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+2]*3]), BN_VLIST_LINE_MOVE);
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+0]*3]), BN_VLIST_LINE_DRAW);
	}
    }

    bu_free(vert_edge_status, "vert status");

    return 0;
}
Beispiel #22
0
int
rt_revolve_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    struct rt_revolve_internal *rip;

    size_t nvert, narc, nadd, nseg, i, j, k;
    point2d_t *verts;
    struct rt_curve *crv;

    vect_t ell[16], cir[16], ucir[16], height, xdir, ydir, ux, uy, uz, rEnd, xEnd, yEnd;
    fastf_t cos22_5 = 0.9238795325112867385;
    fastf_t cos67_5 = 0.3826834323650898373;
    int *endcount = NULL;
    point_t add, add2, add3;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    rip = (struct rt_revolve_internal *)ip->idb_ptr;
    RT_REVOLVE_CK_MAGIC(rip);

    nvert = rip->skt->vert_count;
    verts = rip->skt->verts;
    crv = &rip->skt->curve;

    if (rip->ang < M_2PI) {
	narc = ceil(rip->ang * 8 * M_1_PI);
    } else {
	narc = 16;
    }
    VSCALE(xEnd, rip->r, cos(rip->ang));
    VCROSS(rEnd, rip->axis3d, rip->r);	/* using rEnd for temp storage */
    VSCALE(yEnd, rEnd, sin(rip->ang));
    VADD2(rEnd, xEnd, yEnd);

    VMOVE(uz, rip->axis3d);
    VMOVE(ux, rip->r);
    VCROSS(uy, uz, ux);

    VUNITIZE(ux);
    VUNITIZE(uy);
    VUNITIZE(uz);

    /* setup unit circle to be scaled */
    VMOVE(ucir[ 0], ux);
    VREVERSE(ucir[ 8], ucir[0]);

    VSCALE(xdir, ux, cos22_5);
    VSCALE(ydir, uy, cos67_5);
    VADD2(ucir[ 1], xdir, ydir);
    VREVERSE(ucir[ 9], ucir[1]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 7], xdir, ydir);
    VREVERSE(ucir[15], ucir[7]);

    VSCALE(xdir, ux, M_SQRT1_2);
    VSCALE(ydir, uy, M_SQRT1_2);
    VADD2(ucir[ 2], xdir, ydir);
    VREVERSE(ucir[10], ucir[2]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 6], xdir, ydir);
    VREVERSE(ucir[14], ucir[6]);


    VSCALE(xdir, ux, cos67_5);
    VSCALE(ydir, uy, cos22_5);
    VADD2(ucir[ 3], xdir, ydir);
    VREVERSE(ucir[11], ucir[3]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 5], xdir, ydir);
    VREVERSE(ucir[13], ucir[5]);

    VMOVE(ucir[ 4], uy);
    VREVERSE(ucir[12], ucir[4]);

    /* find open endpoints, and determine which points are used */
    if (nvert)
	endcount = (int *)bu_calloc(nvert, sizeof(int), "endcount");

    nseg = rip->skt->curve.count;

    for (i=0; i<nseg; i++) {
	uint32_t *lng;
	struct line_seg *lsg;
	struct carc_seg *csg;
	struct nurb_seg *nsg;
	struct bezier_seg *bsg;

	lng = (uint32_t *)rip->skt->curve.segment[i];

	switch (*lng) {
	    case CURVE_LSEG_MAGIC:
		lsg = (struct line_seg *)lng;
		endcount[lsg->start]++;
		endcount[lsg->end]++;
		break;
	    case CURVE_CARC_MAGIC:
		csg = (struct carc_seg *)lng;
		if (csg->radius <= 0.0) break;
		endcount[csg->start]++;
		endcount[csg->end]++;
		break;
	    case CURVE_BEZIER_MAGIC:
		bsg = (struct bezier_seg *)lng;
		endcount[bsg->ctl_points[0]]++;
		endcount[bsg->ctl_points[bsg->degree]]++;
		break;
	    case CURVE_NURB_MAGIC:
		nsg = (struct nurb_seg *)lng;
		endcount[nsg->ctl_points[0]]++;
		endcount[nsg->ctl_points[nsg->c_size-1]]++;
		break;
	    default:
		bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
		break;
	}
    }

    /* draw circles */
    for (i=0; i<nvert; i++) {
	if (endcount[i] == 0) continue;
	VSCALE(height, uz, verts[i][Y]);
	for (j=0; j<narc; j++) {
	    VSCALE(cir[j], ucir[j], verts[i][X]);
	    VADD3(ell[j], rip->v3d, cir[j], height);
	}
	RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_MOVE);
	for (j=1; j<narc; j++) {
	    RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
	}
	if (narc < 16) {
	    VSCALE(cir[narc], rEnd, verts[i][X]);
	    VADD3(ell[narc], rip->v3d, cir[narc], height);
	    RT_ADD_VLIST(vhead, ell[narc], BN_VLIST_LINE_DRAW);
	} else {
	    RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_DRAW);
	}
    }

    /* convert endcounts to store which endpoints are odd */
    for (i=0, j=0; i<rip->skt->vert_count; i++) {
	if (endcount[i] % 2 != 0) {
	    /* add 'i' to list, insertion sort by vert[i][Y] */
	    for (k=j; k>0; k--) {
		if ((ZERO(verts[i][Y] - verts[endcount[k-1]][Y])
		     && verts[i][X] > verts[endcount[k-1]][X])
		    || (!ZERO(verts[i][Y] - verts[endcount[k-1]][Y])
			&& verts[i][Y] < verts[endcount[k-1]][Y])) {
		    endcount[k] = endcount[k-1];
		} else {
		    break;
		}
	    }
	    endcount[k] = i;
	    j++;
	}
    }
    nadd = j;
    while (j < rip->skt->vert_count) {
	endcount[j++] = -1;
    }

    /* draw sketch outlines */
    for (i=0; i<narc; i++) {
	curve_to_vlist(vhead, ttol, rip->v3d, ucir[i], uz, rip->skt, crv);
	for (j=0; j<nadd; j++) {
	    if (j+1 < nadd &&
		ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
		VJOIN1(add3, add, verts[endcount[j+1]][X], ucir[i]);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
		j++;
	    } else {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
    }
    if (narc < 16) {
	curve_to_vlist(vhead, ttol, rip->v3d, rEnd, uz, rip->skt, crv);
	for (j=0; j<nadd; j++) {
	    if (j+1 < nadd &&
		ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
		VJOIN1(add3, add, verts[endcount[j+1]][X], rEnd);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
		j++;
	    } else {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
	for (j=0; j<nadd; j+=2) {
	    if (!ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, rip->v3d, verts[endcount[j+1]][Y], rip->axis3d);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
    }

    if (nvert)
	bu_free(endcount, "endcount");
    return 0;
}
Beispiel #23
0
/**
 * Brute force through all possible plane intersections.
 * Generate all edge lines, then intersect the line with all
 * the other faces to find the vertices on that line.
 * If the geometry is correct, there will be no more than two.
 * While not the fastest strategy, this will produce an accurate
 * plot without requiring extra bookkeeping.
 * Note that the vectors will be drawn in no special order.
 */
int
rt_arbn_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol, const struct rt_view_info *UNUSED(info))
{
    struct rt_arbn_internal *aip;
    size_t i;
    size_t j;
    size_t k;

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

    for (i = 0; i < aip->neqn - 1; i++) {
	for (j = i + 1; j < aip->neqn; j++) {
	    double dot;
	    int point_count;	/* # points on this line */
	    point_t a, b;		/* start and end points */
	    vect_t dist;

	    VSETALL(a, 0);
	    VSETALL(b, 0);

	    /* If normals are parallel, no intersection */
	    dot = VDOT(aip->eqn[i], aip->eqn[j]);
	    if (BN_VECT_ARE_PARALLEL(dot, tol)) continue;

	    /* Have an edge line, isect with all other planes */
	    point_count = 0;
	    for (k = 0; k < aip->neqn; k++) {
		size_t m;
		point_t pt;
		size_t next_k;

		next_k = 0;

		if (k == i || k == j) continue;
		if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue;

		/* See if point is outside arb */
		for (m = 0; m < aip->neqn; m++) {
		    if (i == m || j == m || k == m) continue;
		    if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) {
			next_k = 1;
			break;
		    }
		}

		if (next_k != 0) continue;

		if (point_count <= 0) {
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE);
		    VMOVE(a, pt);
		} else if (point_count == 1) {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
		    VMOVE(b, pt);
		} else {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    VSUB2(dist, pt, b);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    bu_log("rt_arbn_plot() error, point_count=%d (>2) on edge %zu/%zu, non-convex\n",
			   point_count+1,
			   i, j);
		    VPRINT(" a", a);
		    VPRINT(" b", b);
		    VPRINT("pt", pt);
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);	/* draw it */
		}
		point_count++;
	    }
	    /* Point counts of 1 are (generally) not harmful,
	     * occurring on pyramid peaks and the like.
	     */
	}
    }
    return 0;
}
Beispiel #24
0
int
rt_hyp_plot(struct bu_list *vhead, struct rt_db_internal *incoming, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    int i, j;		/* loop indices */
    struct rt_hyp_internal *hyp_in;
    struct hyp_specific *hyp;
    vect_t majorAxis[8],	/* vector offsets along major axis */
	minorAxis[8],		/* vector offsets along minor axis */
	heightAxis[7],		/* vector offsets for layers */
	Bunit;			/* unit vector along semi-minor axis */
    vect_t ell[16];		/* stores 16 points to draw ellipses */
    vect_t ribs[16][7];		/* assume 7 layers for now */
    fastf_t scale;		/* used to calculate semi-major/minor axes for top/bottom */
    fastf_t cos22_5 = 0.9238795325112867385;
    fastf_t cos67_5 = 0.3826834323650898373;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(incoming);
    hyp_in = (struct rt_hyp_internal *)incoming->idb_ptr;
    RT_HYP_CK_MAGIC(hyp_in);

    hyp = hyp_internal_to_specific(hyp_in);

    VCROSS(Bunit, hyp->hyp_H, hyp->hyp_Au);
    VUNITIZE(Bunit);

    VMOVE(heightAxis[0], hyp->hyp_H);
    VSCALE(heightAxis[1], heightAxis[0], 0.5);
    VSCALE(heightAxis[2], heightAxis[0], 0.25);
    VSETALL(heightAxis[3], 0);
    VREVERSE(heightAxis[4], heightAxis[2]);
    VREVERSE(heightAxis[5], heightAxis[1]);
    VREVERSE(heightAxis[6], heightAxis[0]);

    for (i = 0; i < 7; i++) {
	/* determine Z height depending on i */
	scale = sqrt(MAGSQ(heightAxis[i])*(hyp->hyp_c * hyp->hyp_c)/(hyp->hyp_r1 * hyp->hyp_r1) + 1);

	/* calculate vectors for offset */
	VSCALE(majorAxis[0], hyp->hyp_Au, hyp->hyp_r1 * scale);
	VSCALE(majorAxis[1], majorAxis[0], cos22_5);
	VSCALE(majorAxis[2], majorAxis[0], M_SQRT1_2);
	VSCALE(majorAxis[3], majorAxis[0], cos67_5);
	VREVERSE(majorAxis[4], majorAxis[3]);
	VREVERSE(majorAxis[5], majorAxis[2]);
	VREVERSE(majorAxis[6], majorAxis[1]);
	VREVERSE(majorAxis[7], majorAxis[0]);

	VSCALE(minorAxis[0], Bunit, hyp->hyp_r2 * scale);
	VSCALE(minorAxis[1], minorAxis[0], cos22_5);
	VSCALE(minorAxis[2], minorAxis[0], M_SQRT1_2);
	VSCALE(minorAxis[3], minorAxis[0], cos67_5);
	VREVERSE(minorAxis[4], minorAxis[3]);
	VREVERSE(minorAxis[5], minorAxis[2]);
	VREVERSE(minorAxis[6], minorAxis[1]);
	VREVERSE(minorAxis[7], minorAxis[0]);

	/* calculate ellipse */
	VADD3(ell[ 0], hyp->hyp_V, heightAxis[i], majorAxis[0]);
	VADD4(ell[ 1], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[3]);
	VADD4(ell[ 2], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[2]);
	VADD4(ell[ 3], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[1]);
	VADD3(ell[ 4], hyp->hyp_V, heightAxis[i], minorAxis[0]);
	VADD4(ell[ 5], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[1]);
	VADD4(ell[ 6], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[2]);
	VADD4(ell[ 7], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[3]);
	VADD3(ell[ 8], hyp->hyp_V, heightAxis[i], majorAxis[7]);
	VADD4(ell[ 9], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[4]);
	VADD4(ell[10], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[5]);
	VADD4(ell[11], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[6]);
	VADD3(ell[12], hyp->hyp_V, heightAxis[i], minorAxis[7]);
	VADD4(ell[13], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[6]);
	VADD4(ell[14], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[5]);
	VADD4(ell[15], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[4]);

	/* draw ellipse */
	RT_ADD_VLIST(vhead, ell[15], BN_VLIST_LINE_MOVE);
	for (j = 0; j < 16; j++) {
	    RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
	}

	/* add ellipse's points to ribs */
	for (j = 0; j < 16; j++) {
	    VMOVE(ribs[j][i], ell[j]);
	}
    }

    /* draw ribs */
    for (i = 0; i < 16; i++) {
	RT_ADD_VLIST(vhead, ribs[i][0], BN_VLIST_LINE_MOVE);
	for (j = 1; j < 7; j++) {
	    RT_ADD_VLIST(vhead, ribs[i][j], BN_VLIST_LINE_DRAW);
	}

    }

    BU_PUT(hyp, struct hyp_specific);

    return 0;
}
Beispiel #25
0
/**
 * Make a list of all edgeuses which are at the same distance as the
 * first element on the list.  Toss out opposing pairs of edgeuses of the
 * same edge.
 *
 */
HIDDEN void make_near_list(struct edge_info *edge_list, struct bu_list *near1, const struct bn_tol *tol)
{
    struct edge_info *ei;
    struct edge_info *ei_p;
    struct edge_info *tmp;
    fastf_t dist;

    BU_CK_LIST_HEAD(&edge_list->l);
    BU_CK_LIST_HEAD(near1);

    /* toss opposing pairs of uses of the same edge from the list */
    ei = BU_LIST_FIRST(edge_info, &edge_list->l);
    while (BU_LIST_NOT_HEAD(&ei->l, &edge_list->l)) {
	NMG_CK_EI(ei);
	ei_p = BU_LIST_FIRST(edge_info, &edge_list->l);
	while (BU_LIST_NOT_HEAD(&ei_p->l, &edge_list->l)) {
	    NMG_CK_EI(ei_p);
	    NMG_CK_VED(ei_p->ved_p);

	    /* if we've found an opposing use of the same
	     * edge toss the pair of them
	     */
	    if (ei_p->ved_p->magic_p == ei->ved_p->magic_p &&
		ei_p->eu_p->eumate_p->vu_p->v_p == ei->eu_p->vu_p->v_p &&
		ei_p->eu_p->vu_p->v_p == ei->eu_p->eumate_p->vu_p->v_p) {
		if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) {
		    bu_log("tossing edgeuse pair:\n");
		    bu_log("(%g %g %g) -> (%g %g %g)\n",
			   V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord),
			   V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
		    bu_log("(%g %g %g) -> (%g %g %g)\n",
			   V3ARGS(ei_p->eu_p->vu_p->v_p->vg_p->coord),
			   V3ARGS(ei_p->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
		}

		tmp = ei_p;
		ei_p = BU_LIST_PLAST(edge_info, &ei_p->l);
		BU_LIST_DEQUEUE(&tmp->l);
		bu_free((char *)tmp, "edge info struct");
		tmp = ei;
		ei = BU_LIST_PLAST(edge_info, &ei->l);
		BU_LIST_DEQUEUE(&tmp->l);
		bu_free((char *)tmp, "edge info struct");
		break;
	    }
	    ei_p = BU_LIST_PNEXT(edge_info, &ei_p->l);
	}
	ei = BU_LIST_PNEXT(edge_info, &ei->l);
    }

    if (BU_LIST_IS_EMPTY(&edge_list->l))
	return;

    ei = BU_LIST_FIRST(edge_info, &edge_list->l);
    NMG_CK_EI(ei);
    NMG_CK_VED(ei->ved_p);
    dist = ei->ved_p->dist;

    /* create "near" list with all ei's at this dist */
    for (BU_LIST_FOR(ei, edge_info, &edge_list->l)) {
	NMG_CK_EI(ei);
	NMG_CK_VED(ei->ved_p);
	if (NEAR_EQUAL(ei->ved_p->dist, dist, tol->dist_sq)) {
	    ei_p = BU_LIST_PLAST(edge_info, &ei->l);
	    BU_LIST_DEQUEUE(&ei->l);
	    BU_LIST_APPEND(near1, &ei->l);
	    ei = ei_p;
	}
    }

    if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) {
	bu_log("dist %g near list\n", dist);
	for (BU_LIST_FOR(ei, edge_info, near1)) {
	    bu_log("\t(%g %g %g) -> (%g %g %g)\n",
		   V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord),
		   V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
	    bu_log("\tdist:%g class:%s status:%d\n\t\tv1(%g %g %g) v2(%g %g %g)\n",
		   ei->ved_p->dist, nmg_class_name(ei->nmg_class),
		   ei->ved_p->status,
		   V3ARGS(ei->ved_p->v1->vg_p->coord),
		   V3ARGS(ei->ved_p->v2->vg_p->coord));
	    bu_log("\tei->ved_p->magic_p=%p, ei->eu_p->vu_p=%p, ei->eu_p->eumate_p->vu_p=%p\n",
		   (void *)ei->ved_p->magic_p, (void *)ei->eu_p->vu_p, (void *)ei->eu_p->eumate_p->vu_p);
	}
    }
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 */
int
gauss_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)


/* defined in material.h */
/* ptr to the shader-specific struct */
{
    register struct gauss_specific *gauss_sp =
	(struct gauss_specific *)dp;
    struct seg *seg_p;
    struct reg_db_internals *dbint_p;
    double optical_density = 0.0;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_gauss_SP(gauss_sp);

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print("gauss_render Parameters:", gauss_print_tab, (char *)gauss_sp);

	bu_log("r_pt(%g %g %g) r_dir(%g %g %g)\n",
	       V3ARGS(ap->a_ray.r_pt),
	       V3ARGS(ap->a_ray.r_dir));
    }

    BU_CK_LIST_HEAD(&swp->sw_segs->l);
    BU_CK_LIST_HEAD(&gauss_sp->dbil);


    /* look at each segment that participated in the ray partition(s) */
    for (BU_LIST_FOR(seg_p, seg, &swp->sw_segs->l)) {

	if (rdebug&RDEBUG_SHADE) {
	    bu_log("seg %g -> %g\n",
		   seg_p->seg_in.hit_dist,
		   seg_p->seg_out.hit_dist);
	}
	RT_CK_SEG(seg_p);
	RT_CK_SOLTAB(seg_p->seg_stp);

	/* check to see if the seg/solid is in this partition */
	if (bu_ptbl_locate(&pp->pt_seglist, (long *)seg_p) != -1) {

	    /* XXX You might use a bu_ptbl list of the solid pointers... */
	    /* check to see if the solid is from this region */
	    for (BU_LIST_FOR(dbint_p, reg_db_internals,
			     &gauss_sp->dbil)) {

		CK_DBINT(dbint_p);

		if (dbint_p->st_p == seg_p->seg_stp) {
		    /* The solid from the region is
		     * the solid from the segment
		     * from the partition
		     */
		    optical_density +=
			eval_seg(ap, dbint_p, seg_p);
		    break;
		}
	    }
	} else {
	    if (rdebug&RDEBUG_SHADE)
		bu_log("gauss_render() bittest failed\n");
	}
    }