Example #1
0
void
make_2manifold_bits(struct bn_tol *tol)
{
    struct vertex *f2_vertl[8];


    /* make a non-dangling internal face */
    f2_vertl[0] = vertl[1];
    f2_vertl[1] = vertl[2];
    f2_vertl[2] = vertl[7];
    f2_vertl[3] = vertl[5];
    fu = nmg_cface(s, f2_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);

    /*
     * we need to make the 2-manifolds share edge topology
     */
    nmg_mesh_faces(tc_fu, fu, tol);
    nmg_mesh_faces(fl_fu, fu, tol);
    nmg_mesh_faces(bl_fu, fu, tol);
    nmg_mesh_faces(ul_fu, fu, tol);

    /* make a dangling internal face */
    f2_vertl[0] = vertl[9];
    f2_vertl[1] = vertl[10];
    f2_vertl[2] = vertl[11];
    f2_vertl[3] = vertl[8];
    fu = nmg_cface(s, f2_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);

    /* make faces share edge topology */
    nmg_mesh_faces(tc_fu, fu, tol);
    nmg_mesh_faces(fl_fu, fu, tol);
    nmg_mesh_faces(bl_fu, fu, tol);


    /* make an exterior, connected dangling face */
    f2_vertl[0] = vertl[0];
    f2_vertl[1] = vertl[3];
    f2_vertl[2] = vertl[31];
    f2_vertl[3] = vertl[30];
    fu = nmg_cface(s, f2_vertl, 4);
    vertl[30] = f2_vertl[3];
    vertl[31] = f2_vertl[2];
    nmg_vertex_g(vertl[30],  150.0, 100.0, 150.0);
    nmg_vertex_g(vertl[31],  150.0,   0.0, 150.0);
    (void)nmg_fu_planeeqn(fu, tol);
    nmg_mesh_faces(fr_fu, fu, tol);


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    nmg_fix_normals(s, tol);

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

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

    return 0;

fail:
    bu_free((char *)pts, "rt_arbn_tess: pts");
    bu_free((char *)edges, "rt_arbn_tess: edges");
    bu_free((char *)edge_count, "rt_arbn_tess: edge_count");
    bu_free((char *)verts, "rt_arbn_tess: verts");
    return -1;
}
Example #3
0
void
make_3manifold_bits(struct bn_tol *tol)
{
    plane_t plane;
    struct faceuse *fu_end;

    memset((char *)vertl, 0, sizeof(vertl));
    memset((char *)f_vertl, 0, sizeof(f_vertl));

    /* front right */
    f_vertl[0] = &vertl[0];
    f_vertl[1] = &vertl[1];
    f_vertl[2] = &vertl[2];
    f_vertl[3] = &vertl[3];
    fr_fu = fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[0],  100.0, 100.0, 100.0);
    nmg_vertex_g(vertl[1],   50.0, 100.0, 100.0);
    nmg_vertex_g(vertl[2],   50.0,   0.0, 100.0);
    nmg_vertex_g(vertl[3],  100.0,   0.0, 100.0);
    (void)nmg_fu_planeeqn(fu, tol);

    /* make top right */
    f_vertl[0] = &vertl[0];
    f_vertl[1] = &vertl[4];
    f_vertl[2] = &vertl[5];
    f_vertl[3] = &vertl[1];
    fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[4],  100.0, 100.0,   0.0);
    nmg_vertex_g(vertl[5],   50.0, 100.0,   0.0);
    (void)nmg_fu_planeeqn(fu, tol);


    /* back right */
    f_vertl[0] = &vertl[5];
    f_vertl[1] = &vertl[4];
    f_vertl[2] = &vertl[6];
    f_vertl[3] = &vertl[7];
    fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[6],  100.0,   0.0,   0.0);
    nmg_vertex_g(vertl[7],   50.0,   0.0,   0.0);
    (void)nmg_fu_planeeqn(fu, tol);

    /* bottom right */
    f_vertl[0] = &vertl[7];
    f_vertl[1] = &vertl[6];
    f_vertl[2] = &vertl[3];
    f_vertl[3] = &vertl[2];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);

    /* right end */
    f_vertl[0] = &vertl[3];
    f_vertl[1] = &vertl[6];
    f_vertl[2] = &vertl[4];
    f_vertl[3] = &vertl[0];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);


    /* make split top */
    f_vertl[0] = &vertl[1];
    f_vertl[1] = &vertl[5];
    f_vertl[2] = &vertl[8];
    f_vertl[3] = &vertl[9];
    tc_fu = fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[8],   25.0, 100.0,   0.0);
    nmg_vertex_g(vertl[9],   25.0, 100.0, 100.0);
    (void)nmg_fu_planeeqn(fu, tol);

    f_vertl[0] = &vertl[9];
    f_vertl[1] = &vertl[8];
    f_vertl[2] = &vertl[12];
    f_vertl[3] = &vertl[13];
    fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[12],   0.0, 100.0,   0.0);
    nmg_vertex_g(vertl[13],   0.0, 100.0, 100.0);
    (void)nmg_fu_planeeqn(fu, tol);


    /* make split & funky front side
     * we make the convex face first, make the second (non-convex) portion
     * after the face normal has been computed.
     */
    f_vertl[0] = &vertl[14];
    f_vertl[1] = &vertl[18];
    f_vertl[2] = &vertl[15];
    f_vertl[3] = &vertl[16];
    fl_fu = fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[14],   0.0,  25.0, 100.0);
    nmg_vertex_g(vertl[15],  25.0,   0.0, 100.0);
    nmg_vertex_g(vertl[16],  25.0,  25.0, 100.0);
    nmg_vertex_g(vertl[18],   0.0,   0.0, 100.0);
    (void)nmg_fu_planeeqn(fu, tol);

    f_vertl[0] = &vertl[1];
    f_vertl[1] = &vertl[9];
    f_vertl[2] = &vertl[10];
    f_vertl[3] = &vertl[9];
    f_vertl[4] = &vertl[13];
    f_vertl[5] = &vertl[14];
    f_vertl[6] = &vertl[16];
    f_vertl[7] = &vertl[15];
    f_vertl[8] = &vertl[2];
    nmg_jf(fu, nmg_cmface(s, f_vertl, 9));
    nmg_vertex_g(vertl[10],  25.0,  75.0, 100.0);


    /* make split back side */
    f_vertl[0] = &vertl[5];
    f_vertl[1] = &vertl[7];
    f_vertl[2] = &vertl[17];
    f_vertl[3] = &vertl[12];
    f_vertl[4] = &vertl[8];
    f_vertl[5] = &vertl[11];
    f_vertl[6] = &vertl[8];
    bl_fu = fu = nmg_cmface(s, f_vertl, 7);
    nmg_vertex_g(vertl[11],  25.0,  75.0,   0.0);
    nmg_vertex_g(vertl[17],   0.0,   0.0,   0.0);

    /* this face isn't strictly convex, so we have to make the plane
     * equation the old-fashioned way.
     */
    bn_mk_plane_3pts(plane,
		     vertl[7]->vg_p->coord,
		     vertl[17]->vg_p->coord,
		     vertl[12]->vg_p->coord,
		     tol);
    nmg_face_g(fu, plane);


    /* make funky end */
    f_vertl[0] = &vertl[14];
    f_vertl[1] = &vertl[20];
    f_vertl[2] = &vertl[19];
    f_vertl[3] = &vertl[18];
    fu_end = fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[19],   0.0,   0.0,  75.0);
    nmg_vertex_g(vertl[20],   0.0,  25.0,  75.0);
    (void)nmg_fu_planeeqn(fu, tol);

    f_vertl[0] = &vertl[12];
    f_vertl[1] = &vertl[17];
    f_vertl[2] = &vertl[19];
    f_vertl[3] = &vertl[20];
    f_vertl[4] = &vertl[14];
    f_vertl[5] = &vertl[13];
    nmg_jf(fu, nmg_cmface(s, f_vertl, 6));


    /* make funky bottom */
    f_vertl[0] = &vertl[15];
    f_vertl[1] = &vertl[18];
    f_vertl[2] = &vertl[19];
    f_vertl[3] = &vertl[21];
    ul_fu = fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[21],  25.0,   0.0,  75.0);
    (void)nmg_fu_planeeqn(fu, tol);

    f_vertl[0] = &vertl[7];
    f_vertl[1] = &vertl[2];
    f_vertl[2] = &vertl[15];
    f_vertl[3] = &vertl[21];
    f_vertl[4] = &vertl[19];
    f_vertl[5] = &vertl[17];
    nmg_jf(fu, nmg_cmface(s, f_vertl, 6));


    /* now create the (3manifold) hole through the object */

    /* make the holes in the end face */
    f_vertl[0] = &vertl[29];
    f_vertl[1] = &vertl[28];
    f_vertl[2] = &vertl[27];
    f_vertl[3] = &vertl[26];
    fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[26],  0.0,   60.0, 10.0);
    nmg_vertex_g(vertl[27],  0.0,   60.0, 25.0);
    nmg_vertex_g(vertl[28],  0.0,   40.0, 25.0);
    nmg_vertex_g(vertl[29],  0.0,   40.0, 10.0);

    /* GROSS HACK XXX
     * we reverse the orientation of the faceuses and loopuses
     * so that we can make the hole as a face, and transfer the hole
     * to an existing face
     */

    lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
    lu->orientation = OT_OPPOSITE;
    lu->lumate_p->orientation = OT_OPPOSITE;

    fu->orientation = OT_OPPOSITE;
    fu->fumate_p->orientation = OT_SAME;

    nmg_jf(fu_end, fu->fumate_p);


    f_vertl[0] = &vertl[22];
    f_vertl[1] = &vertl[23];
    f_vertl[2] = &vertl[24];
    f_vertl[3] = &vertl[25];
    fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[22],  10.0, 60.0,  0.0);
    nmg_vertex_g(vertl[23],  25.0,  60.0,  0.0);
    nmg_vertex_g(vertl[24],  25.0,  40.0,  0.0);
    nmg_vertex_g(vertl[25],  10.0, 40.0,  0.0);

    /* GROSS HACK XXX
     * we reverse the orientation of the faceuses and loopuses
     * so that we can make the hole as a face, and transfer the hole
     * to an existing face.
     */

    lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
    lu->orientation = OT_OPPOSITE;
    lu->lumate_p->orientation = OT_OPPOSITE;

    fu->orientation = OT_OPPOSITE;
    fu->fumate_p->orientation = OT_SAME;

    nmg_jf(bl_fu, fu->fumate_p);


    /* make the top of the hole */
    f_vertl[0] = &vertl[22];
    f_vertl[1] = &vertl[23];
    f_vertl[2] = &vertl[27];
    f_vertl[3] = &vertl[26];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);


    /* make the bottom of the hole */
    f_vertl[0] = &vertl[24];
    f_vertl[1] = &vertl[25];
    f_vertl[2] = &vertl[29];
    f_vertl[3] = &vertl[28];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);


    /* make origin-ward side of the hole */
    f_vertl[0] = &vertl[22];
    f_vertl[1] = &vertl[26];
    f_vertl[2] = &vertl[29];
    f_vertl[3] = &vertl[25];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);

    /* make last side of hole */
    f_vertl[0] = &vertl[23];
    f_vertl[1] = &vertl[24];
    f_vertl[2] = &vertl[28];
    f_vertl[3] = &vertl[27];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);


    /* now make the void in the center of the solid */

    /* void bottom */
    f_vertl[0] = &vertl[41];
    f_vertl[1] = &vertl[40];
    f_vertl[2] = &vertl[39];
    f_vertl[3] = &vertl[38];
    fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[38],  85.0, 40.0, 60.0);
    nmg_vertex_g(vertl[39],  65.0, 40.0, 60.0);
    nmg_vertex_g(vertl[40],  65.0, 40.0, 40.0);
    nmg_vertex_g(vertl[41],  85.0, 40.0, 40.0);
    (void)nmg_fu_planeeqn(fu, tol);


    /* void top */
    f_vertl[0] = &vertl[42];
    f_vertl[1] = &vertl[43];
    f_vertl[2] = &vertl[44];
    f_vertl[3] = &vertl[45];
    fu = nmg_cmface(s, f_vertl, 4);
    nmg_vertex_g(vertl[42],  85.0, 60.0, 40.0);
    nmg_vertex_g(vertl[43],  85.0, 60.0, 60.0);
    nmg_vertex_g(vertl[44],  65.0, 60.0, 60.0);
    nmg_vertex_g(vertl[45],  65.0, 60.0, 40.0);
    (void)nmg_fu_planeeqn(fu, tol);


    /* void front */
    f_vertl[0] = &vertl[44];
    f_vertl[1] = &vertl[43];
    f_vertl[2] = &vertl[38];
    f_vertl[3] = &vertl[39];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);

    /* void back */
    f_vertl[0] = &vertl[42];
    f_vertl[1] = &vertl[45];
    f_vertl[2] = &vertl[40];
    f_vertl[3] = &vertl[41];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);


    /* void left */
    f_vertl[0] = &vertl[45];
    f_vertl[1] = &vertl[44];
    f_vertl[2] = &vertl[39];
    f_vertl[3] = &vertl[40];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);

    /* void right */
    f_vertl[0] = &vertl[42];
    f_vertl[1] = &vertl[41];
    f_vertl[2] = &vertl[38];
    f_vertl[3] = &vertl[43];
    fu = nmg_cmface(s, f_vertl, 4);
    (void)nmg_fu_planeeqn(fu, tol);


}