Ejemplo n.º 1
0
static void
Write_euclid_face(const struct loopuse *lu, const int facet_type, const int regionid, const int face_number)
{
    struct faceuse *fu;
    struct edgeuse *eu;
    plane_t plane;
    int vertex_count = 0;

    NMG_CK_LOOPUSE(lu);

    if (verbose)
	bu_log("Write_euclid_face: lu=%p, facet_type=%d, regionid=%d, face_number=%d\n",
	       (void *)lu, facet_type, regionid, face_number);

    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
	return;

    if (*lu->up.magic_p != NMG_FACEUSE_MAGIC)
	return;

    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd))
	vertex_count++;

    fprintf(fp_out, "%10d%3d     0.    1%5d", regionid, facet_type, vertex_count);

    vertex_count = 0;
    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd))
    {
	struct vertex *v;
	int i;

	NMG_CK_EDGEUSE(eu);
	v = eu->vu_p->v_p;
	NMG_CK_VERTEX(v);
/*		fprintf(fp_out, "%10d%8f%8f%8f", ++vertex_count, V3ARGS(v->vg_p->coord)); */
	vertex_count++;
	fprintf(fp_out, "%10d", vertex_count);

	for (i=X; i<=Z; i++)
	    fastf_print(fp_out, 8, v->vg_p->coord[i]);
    }

    fu = lu->up.fu_p;
    NMG_CK_FACEUSE(fu);
    NMG_GET_FU_PLANE(plane, fu);
    fprintf(fp_out, "%10d%15.5f%15.5f%15.5f%15.5f", face_number, V4ARGS(plane));
}
/**
 * Intersect all the edges in fu1 that don't lie on any of the faces
 * of shell s2 with s2, i.e. "interior" edges, where the endpoints lie
 * on s2, but the edge is not shared with a face of s2.  Such edges
 * wouldn't have been processed by the NEWLINE version of
 * nmg_isect_two_generic_faces(), so intersections need to be looked
 * for here.  Fortunately, it's easy to reject everything except edges
 * that need processing using only the topology structures.
 *
 * The "_int" at the end of the name is to signify that this routine
 * does only "interior" edges, and is not a general face/shell
 * intersector.
 */
void
nmg_isect_face3p_shell_int(struct nmg_inter_struct *is, struct faceuse *fu1, struct shell *s2)
{
    struct shell *s1;
    struct loopuse *lu1;
    struct edgeuse *eu1;

    NMG_CK_INTER_STRUCT(is);
    NMG_CK_FACEUSE(fu1);
    NMG_CK_SHELL(s2);
    s1 = fu1->s_p;
    NMG_CK_SHELL(s1);

    if (RTG.NMG_debug & DEBUG_POLYSECT)
	bu_log("nmg_isect_face3p_shell_int(, fu1=x%x, s2=x%x) START\n", fu1, s2);

    for (BU_LIST_FOR (lu1, loopuse, &fu1->lu_hd)) {
	NMG_CK_LOOPUSE(lu1);
	if (BU_LIST_FIRST_MAGIC(&lu1->down_hd) == NMG_VERTEXUSE_MAGIC)
	    continue;
	for (BU_LIST_FOR (eu1, edgeuse, &lu1->down_hd)) {
	    struct edgeuse *eu2;

	    eu2 = nmg_find_matching_eu_in_s(eu1, s2);
	    if (eu2) {
		bu_log("nmg_isect_face3p_shell_int() eu1=x%x, e1=x%x, eu2=x%x, e2=x%x (nothing to do)\n", eu1, eu1->e_p, eu2, eu2->e_p);
		/* Whether the edgeuse is in a face, or a wire
		 * edgeuse, the other guys will isect it.
		 */
		continue;
	    }
	    /* vu2a and vu2b are in shell s2, but there is no edge
	     * running between them in shell s2.  Create a line of
	     * intersection, and go to it!.
	     */
	    bu_log("nmg_isect_face3p_shell_int(, s2=x%x) eu1=x%x, no eu2\n", s2, eu1);
/* XXX eso no existe todavia */
/* 	    nmg_isect_edge3p_shell(is, eu1, s2); */
	}
    }

    if (RTG.NMG_debug & DEBUG_POLYSECT)
	bu_log("nmg_isect_face3p_shell_int(, fu1=x%x, s2=x%x) END\n", fu1, s2);
}
Ejemplo n.º 3
0
/**
 * Count number of vertices in an NMG loop.
 */
static int
verts_in_nmg_loop(struct loopuse *lu)
{
    int cnt;
    struct edgeuse *eu;
    struct vertex *v;

    /* Count number of vertices in loop. */
    cnt = 0;
    NMG_CK_LOOPUSE(lu);
    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
	for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
	    NMG_CK_EDGEUSE(eu);
	    NMG_CK_EDGE(eu->e_p);
	    NMG_CK_VERTEXUSE(eu->vu_p);
	    NMG_CK_VERTEX(eu->vu_p->v_p);
	    cnt++;
	}
    } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
void
nmg_visit_loopuse(struct loopuse *lu, const struct nmg_visit_handlers *htab, void *state)


/* Handler's private state */
{
    NMG_CK_LOOPUSE(lu);

    if (htab->bef_loopuse) htab->bef_loopuse((uint32_t *)lu, state, 0);

    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
	struct vertexuse *vu;
	vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
	nmg_visit_vertexuse(vu, htab, state);
    } else {
	struct edgeuse *eu;
	for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
	    nmg_visit_edgeuse(eu, htab, state);
	}
    }
    nmg_visit_loop(lu->l_p, htab, state);

    if (htab->aft_loopuse) htab->aft_loopuse((uint32_t *)lu, state, 1);
}
Ejemplo n.º 5
0
extern "C" void
rt_nmg_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
{
    struct model *m;
    struct nmgregion *r;
    struct shell *s;
    struct faceuse *fu;
    struct loopuse *lu;
    struct edgeuse *eu;

    int edge_index;
    long* brepi;

    RT_CK_DB_INTERNAL(ip);
    m = (struct model *)ip->idb_ptr;
    NMG_CK_MODEL(m);

    brepi = static_cast<long*>(bu_malloc(m->maxindex * sizeof(long), "rt_nmg_brep: brepi[]"));
    for (int i = 0; i < m->maxindex; i++) brepi[i] = -INT_MAX;

    for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
	for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	    for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
		NMG_CK_FACEUSE(fu);
		if (fu->orientation != OT_SAME) continue;

		// Need to create ON_NurbsSurface based on plane of
		// face in order to have UV space in which to define
		// trimming loops.  Bounding points are NOT on the
		// face plane, so another approach must be used.
		//
		// General approach: For all loops in the faceuse,
		// collect all the vertices.  Find the center point of
		// all the vertices, and search for the point with the
		// greatest distance from that center point.  Once
		// found, cross the vector between the center point
		// and furthest point with the normal of the face and
		// scale the resulting vector to have the same length
		// as the vector to the furthest point.  Add the two
		// resulting vectors to find the first corner point.
		// Mirror the first corner point across the center to
		// find the second corner point.  Cross the two
		// vectors created by the first two corner points with
		// the face normal to get the vectors of the other two
		// corners, and scale the resulting vectors to the
		// same magnitude as the first two.  These four points
		// bound all vertices on the plane and form a suitable
		// staring point for a UV space, since all points on
		// all the edges are equal to or further than the
		// distance between the furthest vertex and the center
		// point.

		// ............. .............
		// .           .* .          .
		// .         .  .    .       .
		// .        .   .      .     .
		// .       .    .       *    .
		// .      .     .       .    .
		// .     .      .       .    .
		// .    .       .       .    .
		// .   *        *       .    .
		// .   .                .    .
		// .   .                .    .
		// .   .                .    .
		// .   *.               .    .
		// .     ...        ...*     .
		// .       .... ....         .
		// .           *             .
		// ...........................
		//


		const struct face_g_plane *fg = fu->f_p->g.plane_p;
		struct bu_ptbl vert_table;
		nmg_tabulate_face_g_verts(&vert_table, fg);
		point_t tmppt, center, max_pt;
		struct vertex **pt;

		VSET(tmppt, 0, 0, 0);
		VSET(max_pt, 0, 0, 0);

		int ptcnt = 0;
		for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
		    tmppt[0] += (*pt)->vg_p->coord[0];
		    tmppt[1] += (*pt)->vg_p->coord[1];
		    tmppt[2] += (*pt)->vg_p->coord[2];
		    ptcnt++;
		    if (brepi[(*pt)->vg_p->index] == -INT_MAX) {
			ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF);
			brepi[(*pt)->vg_p->index] = vert.m_vertex_index;
		    }
		}
		VSET(center, tmppt[0]/ptcnt, tmppt[1]/ptcnt, tmppt[2]/ptcnt);
		fastf_t max_dist = 0.0;
		fastf_t curr_dist;
		for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
		    tmppt[0] = (*pt)->vg_p->coord[0];
		    tmppt[1] = (*pt)->vg_p->coord[1];
		    tmppt[2] = (*pt)->vg_p->coord[2];
		    curr_dist = DIST_PT_PT(center, tmppt);
		    if (curr_dist > max_dist) {
			max_dist = curr_dist;
			VMOVE(max_pt, tmppt);
		    }
		}
		bu_ptbl_free(&vert_table);
		int ccw = 0;
		vect_t vtmp, uv1, uv2, uv3, uv4, vnormal;
		// If an outer loop is found in the nmg with a cw
		// orientation, use a flipped normal to form the NURBS
		// surface
		for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		    if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1;
		}
		if (ccw != -1) {
		    VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]);
		} else {
		    VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]);
		}
		VSUB2(uv1, max_pt, center);
		VCROSS(vtmp, uv1, vnormal);
		VADD2(uv1, uv1, vtmp);
		VCROSS(uv2, uv1, vnormal);
		VREVERSE(uv3, uv1);
		VCROSS(uv4, uv3, vnormal);
		VADD2(uv1, uv1, center);
		VADD2(uv2, uv2, center);
		VADD2(uv3, uv3, center);
		VADD2(uv4, uv4, center);

		ON_3dPoint p1 = ON_3dPoint(uv1);
		ON_3dPoint p2 = ON_3dPoint(uv2);
		ON_3dPoint p3 = ON_3dPoint(uv3);
		ON_3dPoint p4 = ON_3dPoint(uv4);

		(*b)->m_S.Append(sideSurface(p1, p4, p3, p2));
		ON_Surface *surf = (*(*b)->m_S.Last());
		int surfindex = (*b)->m_S.Count();

		// Now that we have the surface, define the face
		ON_BrepFace& face = (*b)->NewFace(surfindex - 1);

		// With the surface and the face defined, make
		// trimming loops and create faces.  To generate UV
		// coordinates for each from and to for the
		// edgecurves, the UV origin is defined to be v1,
		// v1->v2 is defined as the U domain, and v1->v4 is
		// defined as the V domain.
		vect_t u_axis, v_axis;
		VSUB2(u_axis, uv2, uv1);
		VSUB2(v_axis, uv4, uv1);
		fastf_t u_axis_dist = MAGNITUDE(u_axis);
		fastf_t v_axis_dist = MAGNITUDE(v_axis);

		// Now that the surface context is set up, add the loops.
		for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		    int edges=0;
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex
		    ON_BrepLoop::TYPE looptype;
		    // Check if this is an inner or outer loop
		    if (lu->orientation == OT_SAME) {
			looptype = ON_BrepLoop::outer;
		    } else {
			looptype = ON_BrepLoop::inner;
		    }
		    ON_BrepLoop& loop = (*b)->NewLoop(looptype, face);
		    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
			++edges;
			vect_t ev1, ev2;
			struct vertex_g *vg1, *vg2;
			vg1 = eu->vu_p->v_p->vg_p;
			NMG_CK_VERTEX_G(vg1);
			int vert1 = brepi[vg1->index];
			VMOVE(ev1, vg1->coord);
			vg2 = eu->eumate_p->vu_p->v_p->vg_p;
			NMG_CK_VERTEX_G(vg2);
			int vert2 = brepi[vg2->index];
			VMOVE(ev2, vg2->coord);
			// Add edge if not already added
			if (brepi[eu->e_p->index] == -INT_MAX) {
			    /* always add edges with the small vertex index as from */
			    if (vg1->index > vg2->index) {
				int tmpvert = vert1;
				vert1 = vert2;
				vert2 = tmpvert;
			    }
			    // Create and add 3D curve
			    ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point());
			    c3d->SetDomain(0.0, 1.0);
			    (*b)->m_C3.Append(c3d);
			    // Create and add 3D edge
			    ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1);
			    e.m_tolerance = 0.0;
			    brepi[eu->e_p->index] = e.m_edge_index;
			}
			// Regardless of whether the edge existed as
			// an object, it needs to be added to the
			// trimming loop
			vect_t u_component, v_component;
			ON_3dPoint vg1pt(vg1->coord);
			int orientation = 0;
			edge_index = brepi[eu->e_p->index];
			if (vg1pt !=  (*b)->m_V[(*b)->m_E[edge_index].m_vi[0]].Point()) {
			    orientation = 1;
			}
			// Now, make 2d trimming curves
			vect_t vect1, vect2;
			VSUB2(vect1, ev1, uv1);
			VSUB2(vect2, ev2, uv1);
			ON_2dPoint from_uv, to_uv;
			double u0, u1, v0, v1;
			surf->GetDomain(0, &u0, &u1);
			surf->GetDomain(1, &v0, &v1);

			VPROJECT(vect1, u_axis, u_component, v_component);
			from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
			from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
			VPROJECT(vect2, u_axis, u_component, v_component);
			to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
			to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
			ON_3dPoint S1, S2;
			ON_3dVector Su, Sv;
			surf->Ev1Der(from_uv.x, from_uv.y, S1, Su, Sv);
			surf->Ev1Der(to_uv.x, to_uv.y, S2, Su, Sv);
			ON_Curve* c2d =  new ON_LineCurve(from_uv, to_uv);
			c2d->SetDomain(0.0, 1.0);
			int c2i = (*b)->m_C2.Count();
			(*b)->m_C2.Append(c2d);
			edge_index = brepi[eu->e_p->index];
			ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[edge_index], orientation, loop, c2i);
			trim.m_type = ON_BrepTrim::mated;
			trim.m_tolerance[0] = 0.0;
			trim.m_tolerance[1] = 0.0;
		    }
		}
	    }
	    (*b)->SetTrimIsoFlags();
	}
    }

    bu_free(brepi, "rt_nmg_brep: brepi[]");
}
Ejemplo n.º 6
0
static void
nmg_to_dxf(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float color[3])
{
    struct model *m;
    struct shell *s;
    struct vertex *v;
    struct bu_ptbl verts;
    char *region_name;
    int region_polys=0;
    int tri_count=0;
    int color_num;
    int do_triangulate=0;

    NMG_CK_REGION(r);
    RT_CK_FULL_PATH(pathp);

    region_name = db_path_to_string(pathp);

    m = r->m_p;
    NMG_CK_MODEL(m);

    /* Count triangles */
    for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

	for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
	    struct loopuse *lu;
	    int vert_count=0;

	    NMG_CK_FACEUSE(fu);

	    if (fu->orientation != OT_SAME)
		continue;

	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		struct edgeuse *eu;

		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
		    vert_count++;
		}

		if (vert_count > 3) {
		    do_triangulate = 1;
		    goto triangulate;
		}

		tri_count++;
	    }
	}
    }

 triangulate:
    if (do_triangulate) {
	/* triangulate model */
	nmg_triangulate_model(m, &tol);

	/* Count triangles */
	tri_count = 0;
	for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	    struct faceuse *fu;

	    for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
		struct loopuse *lu;

		if (fu->orientation != OT_SAME)
		    continue;

		for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
			continue;

		    tri_count++;
		}
	    }
	}
    }

    nmg_vertex_tabulate(&verts, &r->l.magic);

    color_num = find_closest_color(color);

    if (polyface_mesh) {
	size_t i;


	fprintf(fp, "0\nPOLYLINE\n8\n%s\n62\n%d\n70\n64\n71\n%lu\n72\n%d\n",
		 region_name, color_num, (unsigned long)BU_PTBL_LEN(&verts), tri_count);
	for (i = 0; i < BU_PTBL_LEN(&verts); i++) {
	    fprintf(fp, "0\nVERTEX\n8\n%s\n", region_name);
	    v = (struct vertex *)BU_PTBL_GET(&verts, i);
	    NMG_CK_VERTEX(v);
	    if (inches) {
		fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGSIN(v->vg_p->coord));
	    } else {
		fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGS(v->vg_p->coord));
	    }
	}
    }

    /* Check triangles */
    for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

	for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
	    struct loopuse *lu;

	    NMG_CK_FACEUSE(fu);

	    if (fu->orientation != OT_SAME)
		continue;

	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		struct edgeuse *eu;
		int vert_count=0;

		NMG_CK_LOOPUSE(lu);

		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		if (polyface_mesh) {
		    fprintf(fp, "0\nVERTEX\n8\n%s\n70\n128\n10\n0.0\n20\n0.0\n30\n0.0\n",
			     region_name);
		} else {
		    fprintf(fp, "0\n3DFACE\n8\n%s\n62\n%d\n", region_name, color_num);
		}

		/* check vertex numbers for each triangle */
		for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
		    NMG_CK_EDGEUSE(eu);

		    vert_count++;

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);

		    if (polyface_mesh) {
			fprintf(fp, "%d\n%d\n",
				 vert_count+70, bu_ptbl_locate(&verts, (long *)v) + 1);
		    } else {
			if (inches) {
			    fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n",
				     10 + vert_count - 1,
				     v->vg_p->coord[X] / 25.4,
				     20 + vert_count - 1,
				     v->vg_p->coord[Y] / 25.4,
				     30 + vert_count -1,
				     v->vg_p->coord[Z] / 25.4);
			} else {
			    fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n",
				     10 + vert_count - 1,
				     v->vg_p->coord[X],
				     20 + vert_count - 1,
				     v->vg_p->coord[Y],
				     30 + vert_count -1,
				     v->vg_p->coord[Z]);
			}
		    }
		}
		if (vert_count > 3) {
		    bu_free(region_name, "region name");
		    bu_log("lu %p has %d vertices!\n", (void *)lu, vert_count);
		    bu_exit(1, "ERROR: LU is not a triangle\n");
		} else if (vert_count < 3) {
		    continue;
		} else {
		    /* repeat the last vertex for the benefit of codes
		     * that interpret the dxf specification for
		     * 3DFACES as requiring a fourth vertex even when
		     * only three are input.
		     */
		    if (!polyface_mesh) {
			vert_count++;
			if (inches) {
			    fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n",
				     10 + vert_count - 1,
				     v->vg_p->coord[X] / 25.4,
				     20 + vert_count - 1,
				     v->vg_p->coord[Y] / 25.4,
				     30 + vert_count -1,
				     v->vg_p->coord[Z] / 25.4);
			} else {
			    fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n",
				     10 + vert_count - 1,
				     v->vg_p->coord[X],
				     20 + vert_count - 1,
				     v->vg_p->coord[Y],
				     30 + vert_count -1,
				     v->vg_p->coord[Z]);
			}
		    }
		}

		tot_polygons++;
		region_polys++;
	    }
	}
    }

    bu_ptbl_free(&verts);
    bu_free(region_name, "region name");

    if (polyface_mesh) {
	fprintf(fp, "0\nSEQEND\n");
    }

}
Ejemplo n.º 7
0
/*
 *	J A C K _ F A C E S
 *
 *	Continues the conversion of an nmg into Jack format.  Before
 *	this routine is called, a list of unique vertices has been
 *	stored in a heap.  Using this heap and the nmg structure, a
 *	list of face vertices is written to the Jack data base file.
 */
static void
jack_faces(struct nmgregion *r, FILE *fp_psurf, int *map)
    /* NMG region to be converted. */
    /* Jack format file to write face vertices to. */

{
    struct edgeuse		*eu;
    struct faceuse		*fu;
    struct loopuse		*lu;
    struct shell		*s;
    struct vertex		*v;

    for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	/* Shell is made of faces. */
	for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
	    NMG_CK_FACEUSE(fu);
	    if (fu->orientation != OT_SAME)
		continue;
	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		NMG_CK_LOOPUSE(lu);
		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
		    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
			NMG_CK_EDGEUSE(eu);
			NMG_CK_EDGE(eu->e_p);
			NMG_CK_VERTEXUSE(eu->vu_p);
			NMG_CK_VERTEX(eu->vu_p->v_p);
			NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p);
			fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, eu->vu_p->v_p));
		    }
		} else if (BU_LIST_FIRST_MAGIC(&lu->down_hd)
			   == NMG_VERTEXUSE_MAGIC) {
		    v = BU_LIST_PNEXT(vertexuse, &lu->down_hd)->v_p;
		    NMG_CK_VERTEX(v);
		    NMG_CK_VERTEX_G(v->vg_p);
		    fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, v));
		} else
		    bu_log("jack_faces: loopuse mess up! (1)\n");
		fprintf(fp_psurf, ";\n");
	    }
	}

	/* Shell contains loops. */
	for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
	    NMG_CK_LOOPUSE(lu);
	    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
		for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
		    NMG_CK_EDGEUSE(eu);
		    NMG_CK_EDGE(eu->e_p);
		    NMG_CK_VERTEXUSE(eu->vu_p);
		    NMG_CK_VERTEX(eu->vu_p->v_p);
		    NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p);
		    fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, eu->vu_p->v_p));
		}
	    } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd)
		       == NMG_VERTEXUSE_MAGIC) {
		v = BU_LIST_PNEXT(vertexuse, &lu->down_hd)->v_p;
		NMG_CK_VERTEX(v);
		NMG_CK_VERTEX_G(v->vg_p);
		fprintf(fp_psurf, "%d ", NMG_INDEX_GET(map, v));
	    } else
		bu_log("jack_faces: loopuse mess up! (1)\n");
	    fprintf(fp_psurf, ";\n");
	}
void
nmg_2_vrml(struct db_tree_state *tsp, const struct db_full_path *pathp, struct model *m)
{
    struct mater_info *mater = &tsp->ts_mater;
    const struct bn_tol *tol2 = tsp->ts_tol;
    struct nmgregion *reg;
    struct bu_ptbl verts;
    struct vrml_mat mat;
    struct bu_vls vls = BU_VLS_INIT_ZERO;
    char *tok;
    int i;
    int first = 1;
    int is_light = 0;
    point_t ave_pt = VINIT_ZERO;
    struct bu_vls shape_name = BU_VLS_INIT_ZERO;
    char *full_path;
    /* There may be a better way to capture the region_id, than
     * getting the rt_comb_internal structure, (and may be a better
     * way to capture the rt_comb_internal struct), but for now I just
     * copied the method used in select_lights/select_non_lights above,
     * could have used a global variable but I noticed none other were
     * used, so I didn't want to be the first
     */
    struct directory *dp;
    struct rt_db_internal intern;
    struct rt_comb_internal *comb;
    int id;

    /* static due to libbu exception handling */
    static float r, g, b;

    NMG_CK_MODEL(m);

    full_path = db_path_to_string(pathp);

    RT_CK_FULL_PATH(pathp);
    dp = DB_FULL_PATH_CUR_DIR(pathp);

    if (!(dp->d_flags & RT_DIR_COMB)) {
	return;
    }

    id = rt_db_get_internal(&intern, dp, dbip, (matp_t)NULL, &rt_uniresource);
    if (id < 0) {
	bu_log("Cannot internal form of %s\n", dp->d_namep);
	return;
    }

    if (id != ID_COMBINATION) {
	bu_log("Directory/database mismatch!\n\t is '%s' a combination or not?\n",
		dp->d_namep);
	return;
    }

    comb = (struct rt_comb_internal *)intern.idb_ptr;
    RT_CK_COMB(comb);

    if (mater->ma_color_valid) {
	r = mater->ma_color[0];
	g = mater->ma_color[1];
	b = mater->ma_color[2];
    } else {
	r = g = b = 0.5;
    }

    if (mater->ma_shader) {
	tok = strtok(mater->ma_shader, tok_sep);
	bu_strlcpy(mat.shader, tok, TXT_NAME_SIZE);
    } else {
	mat.shader[0] = '\0';
    }

    mat.shininess = -1;
    mat.transparency = -1.0;
    mat.lt_fraction = -1.0;
    VSETALL(mat.lt_dir, 0.0);
    mat.lt_angle = -1.0;
    mat.tx_file[0] = '\0';
    mat.tx_w = -1;
    mat.tx_n = -1;
    bu_vls_strcpy(&vls, &mater->ma_shader[strlen(mat.shader)]);
    (void)bu_struct_parse(&vls, vrml_mat_parse, (char *)&mat, NULL);

    if (bu_strncmp("light", mat.shader, 5) == 0) {
	/* this is a light source */
	is_light = 1;
    } else {
	path_2_vrml_id(&shape_name, full_path);
	fprintf(fp_out, "\t\tDEF %s Shape {\n", bu_vls_addr(&shape_name));

	fprintf(fp_out, "\t\t\t# Component_ID: %ld   %s\n", comb->region_id, full_path);
	fprintf(fp_out, "\t\t\tappearance Appearance {\n");

	if (bu_strncmp("plastic", mat.shader, 7) == 0) {
	    if (mat.shininess < 0) {
		mat.shininess = 10;
	    }
	    if (mat.transparency < SMALL_FASTF) {
		mat.transparency = 0.0;
	    }

	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b);
	    fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0));
	    if (mat.transparency > SMALL_FASTF) {
		fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency);
	    }
	    fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0);
	} else if (bu_strncmp("glass", mat.shader, 5) == 0) {
	    if (mat.shininess < 0) {
		mat.shininess = 4;
	    }
	    if (mat.transparency < SMALL_FASTF) {
		mat.transparency = 0.8;
	    }

	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b);
	    fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0));
	    if (mat.transparency > SMALL_FASTF) {
		fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency);
	    }
	    fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0);
	} else if (bu_strncmp("texture", mat.shader, 7) == 0) {
	    if (mat.tx_w < 0) {
		mat.tx_w = 512;
	    }
	    if (mat.tx_n < 0) {
		mat.tx_n = 512;
	    }
	    if (strlen(mat.tx_file)) {
		int tex_fd;
		unsigned char tex_buf[TXT_BUF_LEN * 3];

		if ((tex_fd = open(mat.tx_file, O_RDONLY | O_BINARY)) == (-1)) {
		    bu_log("Cannot open texture file (%s)\n", mat.tx_file);
		    perror("g-vrml: ");
		} else {
		    long tex_len;
		    long bytes_read = 0;
		    long bytes_to_go = 0;

		    /* Johns note - need to check (test) the texture stuff */
		    fprintf(fp_out, "\t\t\t\ttextureTransform TextureTransform {\n");
		    fprintf(fp_out, "\t\t\t\t\tscale 1.33333 1.33333\n\t\t\t\t}\n");
		    fprintf(fp_out, "\t\t\t\ttexture PixelTexture {\n");
		    fprintf(fp_out, "\t\t\t\t\trepeatS TRUE\n");
		    fprintf(fp_out, "\t\t\t\t\trepeatT TRUE\n");
		    fprintf(fp_out, "\t\t\t\t\timage %d %d %d\n", mat.tx_w, mat.tx_n, 3);
		    tex_len = mat.tx_w*mat.tx_n * 3;
		    while (bytes_read < tex_len) {
			int nbytes;
			long readval;

			bytes_to_go = tex_len - bytes_read;
			CLAMP(bytes_to_go, 0, TXT_BUF_LEN * 3);

			nbytes = 0;
			while (nbytes < bytes_to_go) {
			    readval = read(tex_fd, &tex_buf[nbytes], bytes_to_go-nbytes);
			    if (readval < 0) {
				perror("READ ERROR");
				break;
			    } else {
				nbytes += readval;
			    }
			}
			bytes_read += nbytes;
			for (i = 0; i < nbytes; i += 3) {
			    fprintf(fp_out, "\t\t\t0x%02x%02x%02x\n",
				    tex_buf[i], tex_buf[i+1], tex_buf[i+2]);
			}
		    }
		    fprintf(fp_out, "\t\t\t\t}\n");

		    close(tex_fd);
		}
	    }
	} else if (mater->ma_color_valid) {
	    /* no shader specified, but a color is assigned */
	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g }\n", r, g, b);
	} else {
	    /* If no color was defined set the colors according to the thousands groups */
	    int thou = comb->region_id / 1000;
	    thou == 0 ? fprintf(fp_out, "\t\t\tmaterial USE Material_999\n")
		: thou == 1 ? fprintf(fp_out, "\t\t\tmaterial USE Material_1999\n")
		: thou == 2 ? fprintf(fp_out, "\t\t\tmaterial USE Material_2999\n")
		: thou == 3 ? fprintf(fp_out, "\t\t\tmaterial USE Material_3999\n")
		: thou == 4 ? fprintf(fp_out, "\t\t\tmaterial USE Material_4999\n")
		: thou == 5 ? fprintf(fp_out, "\t\t\tmaterial USE Material_5999\n")
		: thou == 6 ? fprintf(fp_out, "\t\t\tmaterial USE Material_6999\n")
		: thou == 7 ? fprintf(fp_out, "\t\t\tmaterial USE Material_7999\n")
		: thou == 8 ? fprintf(fp_out, "\t\t\tmaterial USE Material_8999\n")
		: fprintf(fp_out, "\t\t\tmaterial USE Material_9999\n");
	}
    }

    if (!is_light) {
	nmg_triangulate_model(m, tol2);
	fprintf(fp_out, "\t\t\t}\n");
	fprintf(fp_out, "\t\t\tgeometry IndexedFaceSet {\n");
	fprintf(fp_out, "\t\t\t\tcoord Coordinate {\n");
    }

    /* get list of vertices */
    nmg_vertex_tabulate(&verts, &m->magic);
    if (!is_light) {
	fprintf(fp_out, "\t\t\t\t\tpoint [");
    } else {
	VSETALL(ave_pt, 0.0);
    }

    for (i = 0; i < BU_PTBL_END(&verts); i++) {
	struct vertex *v;
	struct vertex_g *vg;
	point_t pt_meters;

	v = (struct vertex *)BU_PTBL_GET(&verts, i);
	NMG_CK_VERTEX(v);
	vg = v->vg_p;
	NMG_CK_VERTEX_G(vg);

	/* convert to desired units */
	VSCALE(pt_meters, vg->coord, scale_factor);

	if (is_light) {
	    VADD2(ave_pt, ave_pt, pt_meters);
	}

	if (first) {
	    if (!is_light) {
		fprintf(fp_out, " %10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i);
	    }
	    first = 0;
	} else if (!is_light) {
	    fprintf(fp_out, "\t\t\t\t\t%10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i);
	}
    }

    if (!is_light) {
	fprintf(fp_out, "\t\t\t\t\t]\n\t\t\t\t}\n");
    } else {
	fastf_t one_over_count;
	one_over_count = 1.0/(fastf_t)BU_PTBL_END(&verts);
	VSCALE(ave_pt, ave_pt, one_over_count);
    }

    first = 1;
    if (!is_light) {
	fprintf(fp_out, "\t\t\t\tcoordIndex [\n");
	for (BU_LIST_FOR(reg, nmgregion, &m->r_hd)) {
	    struct shell *s;

	    NMG_CK_REGION(reg);
	    for (BU_LIST_FOR(s, shell, &reg->s_hd)) {
		struct faceuse *fu;

		NMG_CK_SHELL(s);
		for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
		    struct loopuse *lu;

		    NMG_CK_FACEUSE(fu);

		    if (fu->orientation != OT_SAME) {
			continue;
		    }

		    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
			struct edgeuse *eu;

			NMG_CK_LOOPUSE(lu);
			if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) {
			    continue;
			}

			if (!first) {
			    fprintf(fp_out, ",\n");
			} else {
			    first = 0;
			}

			fprintf(fp_out, "\t\t\t\t\t");
			for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
			    struct vertex *v;

			    NMG_CK_EDGEUSE(eu);
			    v = eu->vu_p->v_p;
			    NMG_CK_VERTEX(v);
			    fprintf(fp_out, " %d,", bu_ptbl_locate(&verts, (long *)v));
			}
			fprintf(fp_out, "-1");
		    }
		}
	    }
	}
	fprintf(fp_out, "\n\t\t\t\t]\n\t\t\t\tnormalPerVertex FALSE\n");
	fprintf(fp_out, "\t\t\t\tconvex FALSE\n");
	fprintf(fp_out, "\t\t\t\tcreaseAngle 0.5\n");
	fprintf(fp_out, "\t\t\t}\n\t\t}\n");
    } else {
Ejemplo n.º 9
0
static void
nmg_to_obj(struct nmgregion *r, struct db_full_path *pathp, int region_id, int aircode, int los, int material_id)
{
    struct model *m;
    struct shell *s;
    struct vertex *v;
    struct bu_ptbl verts;
    struct bu_ptbl norms;
    char *region_name;
    int numverts = 0;		/* Number of vertices to output */
    int numtri   = 0;		/* Number of triangles to output */
    int i;

    NMG_CK_REGION( r );
    RT_CK_FULL_PATH(pathp);

    region_name = db_path_to_string( pathp );

#if 0
    printf("Attempting to process region %s\n", region_name);
    fflush(stdout);
#endif

    m = r->m_p;
    NMG_CK_MODEL( m );

    /* triangulate model */
    nmg_triangulate_model( m, &tol );

    /* list all vertices in result */
    nmg_vertex_tabulate( &verts, &r->l.magic );

    /* Get number of vertices */
    numverts = BU_PTBL_END (&verts);

    /* get list of vertexuse normals */
    if ( do_normals )
	nmg_vertexuse_normal_tabulate( &norms, &r->l.magic );

/* XXX Check vertices, shells faces first? Do not want to punt mid-stream */
/* BEGIN CHECK SECTION */
/* Check vertices */

    for ( i=0; i<numverts; i++ )
    {
	v = (struct vertex *)BU_PTBL_GET( &verts, i );
	NMG_CK_VERTEX( v );
    }

/* Check triangles */
    for ( BU_LIST_FOR( s, shell, &r->s_hd ) )
    {
	struct faceuse *fu;

	NMG_CK_SHELL( s );

	for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
	{
	    struct loopuse *lu;

	    NMG_CK_FACEUSE( fu );

	    if ( fu->orientation != OT_SAME )
		continue;

	    for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
	    {
		struct edgeuse *eu;
		int vert_count=0;

		NMG_CK_LOOPUSE( lu );

		if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
		    continue;

		/* check vertex numbers for each triangle */
		for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
		{
		    NMG_CK_EDGEUSE( eu );

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX( v );

		    vert_count++;
		    i = bu_ptbl_locate( &verts, (long *)v );
		    if ( i < 0 )
		    {
			/*XXX*/				bu_ptbl_free( &verts);
			/*XXX*/				bu_free( region_name, "region name" );
			bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r );
			bu_exit(1, "ERROR: Can't find vertex in list!");
		    }
		}
		if ( vert_count > 3 )
		{
		    /*XXX*/			bu_ptbl_free( &verts);
		    /*XXX*/			bu_free( region_name, "region name" );
		    bu_log( "lu x%x has %d vertices!\n", lu, vert_count );
		    bu_exit(1, "ERROR: LU is not a triangle\n");
		}
		else if ( vert_count < 3 )
		    continue;
		numtri++;
	    }
	}
    }

/* END CHECK SECTION */
/* Write pertinent info for this region */

    if ( usemtl )
	fprintf( fp, "usemtl %d_%d_%d\n", aircode, los, material_id );

    fprintf( fp, "g %s", pathp->fp_names[0]->d_namep );
    for ( i=1; i<pathp->fp_len; i++ )
	fprintf( fp, "/%s", pathp->fp_names[i]->d_namep );
    fprintf( fp, "\n" );

    /* Write vertices */
    for ( i=0; i<numverts; i++ )
    {
	v = (struct vertex *)BU_PTBL_GET( &verts, i );
	NMG_CK_VERTEX( v );
	if (inches)
	    fprintf( fp, "v %f %f %f\n", V3ARGSIN( v->vg_p->coord ));
	else
	    fprintf( fp, "v %f %f %f\n", V3ARGS( v->vg_p->coord ));
    }

    /* Write vertexuse normals */
    if ( do_normals )
    {
	for ( i=0; i<BU_PTBL_END( &norms ); i++ )
	{
	    struct vertexuse_a_plane *va;

	    va = (struct vertexuse_a_plane *)BU_PTBL_GET( &norms, i );
	    NMG_CK_VERTEXUSE_A_PLANE( va );
	    if (inches)
		fprintf( fp, "vn %f %f %f\n", V3ARGSIN( va->N ));
	    else
		fprintf( fp, "vn %f %f %f\n", V3ARGS( va->N ));
	}
    }

    /* output triangles */
    for ( BU_LIST_FOR( s, shell, &r->s_hd ) )
    {
	struct faceuse *fu;

	NMG_CK_SHELL( s );

	for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
	{
	    struct loopuse *lu;

	    NMG_CK_FACEUSE( fu );

	    if ( fu->orientation != OT_SAME )
		continue;

	    for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
	    {
		struct edgeuse *eu;
		int vert_count=0;
		int use_normals=1;

		NMG_CK_LOOPUSE( lu );

		if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
		    continue;

		/* Each vertexuse of the face must have a normal in order
		 * to use the normals in Wavefront
		 */
		if ( do_normals )
		{
		    for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
		    {
			NMG_CK_EDGEUSE( eu );

			if ( !eu->vu_p->a.magic_p )
			{
			    use_normals = 0;
			    break;
			}

			if ( *eu->vu_p->a.magic_p != NMG_VERTEXUSE_A_PLANE_MAGIC )
			{
			    use_normals = 0;
			    break;
			}
		    }
		}
		else
		    use_normals = 0;

		fprintf( fp, "f" );

		/* list vertex numbers for each triangle */
		for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
		{
		    NMG_CK_EDGEUSE( eu );

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX( v );

		    vert_count++;
		    i = bu_ptbl_locate( &verts, (long *)v );
		    if ( i < 0 )
		    {
			bu_ptbl_free( &verts);
			bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r );
			/*XXX*/				bu_free( region_name, "region name" );
			/*XXX*/				bu_exit(1, "Can't find vertex in list!\n");
		    }

		    if ( use_normals )
		    {
			int j;

			j = bu_ptbl_locate( &norms, (long *)eu->vu_p->a.magic_p );
			fprintf( fp, " %ld//%ld", i+1+vert_offset, j+1+norm_offset );
		    }
		    else
			fprintf( fp, " %ld", i+1+vert_offset );
		}

		fprintf( fp, "\n" );

		if ( vert_count > 3 )
		{
		    bu_ptbl_free( &verts);
		    bu_free( region_name, "region name" );
		    bu_log( "lu x%x has %d vertices!\n", lu, vert_count );
		    bu_exit(1, "ERROR: LU is not a triangle\n" );
		}
	    }
	}
    }
Ejemplo n.º 10
0
static struct loopuse *
nmg_construct_loopuse(void *parent, const struct loopuse *original, void **structArray)
{
    struct loopuse *ret;

    NMG_GETSTRUCT(ret, loopuse);

    ret->l.magic     = NMG_LOOPUSE_MAGIC;
    ret->up.magic_p  = (uint32_t *)parent;
    ret->lumate_p    = (struct loopuse *)NULL;
    ret->orientation = original->orientation;
    ret->l_p         = (struct loop *)NULL;

    BU_LIST_INIT(&ret->down_hd);

    ret->index              = original->index;
    structArray[ret->index] = ret;

    if (original->lumate_p != NULL) {
	ret->lumate_p = (struct loopuse *)structArray[original->lumate_p->index];

	/* because it's tricky to choose the right parent for the mate
	 * wait until it's created and set eumate_p afterwards
	 */
	if (ret->lumate_p != NULL)
	    ret->lumate_p->lumate_p = ret;
    }

    if (original->l_p != NULL) {
	ret->l_p = (struct loop *)structArray[original->l_p->index];

	if (ret->l_p == 0)
	    ret->l_p = nmg_construct_loop(ret, original->l_p, structArray);
    }

    switch (BU_LIST_FIRST_MAGIC(&original->down_hd)) {
	case NMG_VERTEXUSE_MAGIC: {
	    const struct vertexuse *originalVertexUse = BU_LIST_FIRST(vertexuse, &original->down_hd);
	    struct vertexuse       *newVertexUse      = (struct vertexuse *)structArray[originalVertexUse->index];

	    if (newVertexUse == NULL)
		newVertexUse = nmg_construct_vertexuse(ret, originalVertexUse, structArray);

	    BU_LIST_INSERT(&ret->down_hd, &newVertexUse->l);
	}
	    break;
	case NMG_EDGEUSE_MAGIC: {
	    const struct edgeuse *originalEdgeUse;
	    for (BU_LIST_FOR(originalEdgeUse, edgeuse, &original->down_hd)) {
		struct edgeuse *newEdgeUse = (struct edgeuse *)structArray[originalEdgeUse->index];
		if (newEdgeUse == NULL)
		    newEdgeUse = nmg_construct_edgeuse(ret, originalEdgeUse, structArray);
		BU_LIST_INSERT(&ret->down_hd, &newEdgeUse->l);
	    }
	}
	    break;
	default:
	    /* FIXME: any more cases? any action to take? */
	    break;
    }

    return ret;
}
Ejemplo n.º 11
0
/*	Routine to write an nmgregion in the Euclid "decoded" format */
static void
Write_euclid_region(struct nmgregion *r, struct db_tree_state *tsp)
{
    struct shell *s;
    struct facets *faces=NULL;
    int i, j;

    NMG_CK_REGION(r);

    if (verbose)
	bu_log("Write_euclid_region: r=%p\n", (void *)r);

    /* if bounds haven't been calculated, do it now */
    if (r->ra_p == NULL)
	nmg_region_a(r, &tol);

    /* Check if region extents are beyond the limitations of the format */
    for (i=X; i<ELEMENTS_PER_POINT; i++)
    {
	if (r->ra_p->min_pt[i] < (-999999.0))
	{
	    bu_log("g-euclid: Coordinates too large (%g) for Euclid format\n", r->ra_p->min_pt[i]);
	    return;
	}
	if (r->ra_p->max_pt[i] > 9999999.0)
	{
	    bu_log("g-euclid: Coordinates too large (%g) for Euclid format\n", r->ra_p->max_pt[i]);
	    return;
	}
    }

    /* write out each face in the region */
    for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	struct faceuse *fu;

	for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
	    struct loopuse *lu;
	    int no_of_loops = 0;
	    int no_of_holes = 0;

	    if (fu->orientation != OT_SAME)
		continue;

	    /* count the loops in this face */
	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		no_of_loops++;
	    }

	    if (!no_of_loops)
		continue;

	    faces = (struct facets *)bu_calloc(no_of_loops, sizeof(struct facets), "g-euclid: faces");

	    i = 0;
	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		faces[i].lu = lu;
		if (lu->orientation == OT_OPPOSITE)
		    faces[i].facet_type = 1; /* this is a hole */
		else
		    faces[i].facet_type = (-1); /* TBD */

		faces[i].outer_loop = NULL;
		i++;
	    }

	    /* determine type of face
	     * 0 -> simple facet (no holes)
	     * 1 -> a hole
	     * 2 -> a facet that will have holes
	     */

	    for (i = 0; i < no_of_loops; i++) {
		if (faces[i].facet_type == 1)
		    no_of_holes++;
	    }

	    if (!no_of_holes) {
		/* no holes, so each loop is a simple face (type 0) */
		for (i = 0; i < no_of_loops; i++)
		    faces[i].facet_type = 0;
	    } else if (no_of_loops == no_of_holes + 1) {
		struct loopuse *outer_lu = (struct loopuse *)NULL;

		/* only one outer loop, so find it */
		for (i = 0; i < no_of_loops; i++) {
		    if (faces[i].facet_type == (-1)) {
			outer_lu = faces[i].lu;
			faces[i].facet_type = 2;
			break;
		    }
		}

		/* every hole must have this same outer_loop */
		for (i = 0; i < no_of_loops; i++) {
		    if (faces[i].facet_type == 1)
			faces[i].outer_loop = outer_lu;
		}
	    } else {
		int loop1, loop2;
		int outer_loop_count;

		/* must determine which holes go with which outer loops */
		for (loop1 = 0; loop1 < no_of_loops; loop1++) {
		    if (faces[loop1].facet_type != 1)
			continue;

		    /* loop1 is a hole look for loops containing loop1 */
		    outer_loop_count = 0;
		    for (loop2 = 0; loop2 < no_of_loops; loop2++) {
			int nmg_class;

			if (faces[loop2].facet_type == 1)
			    continue;

			nmg_class = nmg_classify_lu_lu(faces[loop1].lu,
						   faces[loop2].lu, &tol);

			if (nmg_class != NMG_CLASS_AinB)
			    continue;

			/* loop1 is inside loop2, possible outer loop */
			faces[loop2].facet_type = (-2);
			outer_loop_count++;
		    }

		    if (outer_loop_count > 1) {
			/* must choose outer loop from a list of candidates
			 * if any of these candidates contain one of the
			 * other candidates, the outer one can be eliminated
			 * as a possible choice */
			for (loop2 = 0; loop2 < no_of_loops; loop2++) {
			    if (faces[loop2].facet_type != (-2))
				continue;

			    for (i = 0; i < no_of_loops; i++) {
				if (faces[i].facet_type != (-2))
				    continue;

				if (nmg_classify_lu_lu(faces[i].lu,
						       faces[loop2].lu, &tol)) {
				    if (faces[i].facet_type != (-2))
					continue;

				    faces[loop2].facet_type = (-1);
				    outer_loop_count--;
				}
			    }
			}
		    }

		    if (outer_loop_count != 1) {
			bu_log("Failed to find outer loop for hole in component %d\n", tsp->ts_regionid);
			goto outt;
		    }

		    for (i = 0; i < no_of_loops; i++) {
			if (faces[i].facet_type == (-2)) {
			    faces[i].facet_type = 2;
			    faces[loop1].outer_loop = faces[i].lu;
			}
		    }
		}

		/* Check */
		for (i = 0; i < no_of_loops; i++) {
		    if (faces[i].facet_type < 0) {
			/* all holes have been placed
			 * so these must be simple faces
			 */
			faces[i].facet_type = 0;
		    }

		    if (faces[i].facet_type == 1 && faces[i].outer_loop == NULL) {
			bu_log("Failed to find outer loop for hole in component %d\n", tsp->ts_regionid);
			goto outt;
		    }
		}
	    }
	    /* output faces with holes first */
	    for (i = 0; i < no_of_loops; i++) {
		struct loopuse *outer_loop;

		if (faces[i].facet_type != 2)
		    continue;

		outer_loop = faces[i].lu;
		Write_euclid_face(outer_loop, 2, tsp->ts_regionid, ++face_count);

		/* output holes for this face */
		for (j = 0; j < no_of_loops; j++) {
		    if (j == i)
			continue;

		    if (faces[j].outer_loop == outer_loop)
			Write_euclid_face(faces[j].lu, 1, tsp->ts_regionid, ++face_count);
		}
	    }
	    /* output simple faces */
	    for (i = 0; i < no_of_loops; i++) {
		if (faces[i].facet_type != 0)
		    continue;
		Write_euclid_face(faces[i].lu, 0, tsp->ts_regionid, ++face_count);
	    }

	    bu_free((char *)faces, "g-euclid: faces");
	    faces = (struct facets*)NULL;
	}
    }

    regions_written++;

outt:
    if (faces)
	bu_free((char *)faces, "g-euclid: faces");
    return;
}
Ejemplo n.º 12
0
void
nmg_2_vrml(FILE *fp, const struct db_full_path *pathp, struct model *m, struct mater_info *mater)
{
    struct nmgregion *reg;
    struct bu_ptbl verts;
    struct vrml_mat mat;
    struct bu_vls vls = BU_VLS_INIT_ZERO;
    char *tok;
    int i;
    int first=1;
    int is_light=0;
    float r, g, b;
    point_t ave_pt;
    char *full_path;
    /*There may be a better way to capture the region_id, than getting the rt_comb_internal structure,
     * (and may be a better way to capture the rt_comb_internal struct), but for now I just copied the
     * method used in select_lights/select_non_lights above, could have used a global variable but I noticed
     * none other were used, so I didn't want to be the first
     */
    struct directory *dp;
    struct rt_db_internal intern;
    struct rt_comb_internal *comb;
    int id;

    NMG_CK_MODEL( m );

    BARRIER_CHECK;

    full_path = db_path_to_string( pathp );

    /* replace all occurrences of '.' with '_' */
    char_replace(full_path, '.', '_');

    RT_CK_FULL_PATH( pathp );
    dp = DB_FULL_PATH_CUR_DIR( pathp );

    if ( !(dp->d_flags & RT_DIR_COMB) )
	return;

    id = rt_db_get_internal( &intern, dp, dbip, (matp_t)NULL, &rt_uniresource );
    if ( id < 0 )
    {
	bu_log( "Cannot internal form of %s\n", dp->d_namep );
	return;
    }

    if ( id != ID_COMBINATION )
    {
	bu_log( "Directory/database mismatch!\n\t is '%s' a combination or not?\n",
		dp->d_namep );
	return;
    }

    comb = (struct rt_comb_internal *)intern.idb_ptr;
    RT_CK_COMB( comb );

    if ( mater->ma_color_valid )
    {
	r = mater->ma_color[0];
	g = mater->ma_color[1];
	b = mater->ma_color[2];
    }
    else
    {
	r = g = b = 0.5;
    }

    if ( mater->ma_shader )
    {
	tok = strtok( mater->ma_shader, tok_sep );
	bu_strlcpy( mat.shader, tok, TXT_NAME_SIZE );
    }
    else
	mat.shader[0] = '\0';
    mat.shininess = -1;
    mat.transparency = -1.0;
    mat.lt_fraction = -1.0;
    VSETALL( mat.lt_dir, 0.0 );
    mat.lt_angle = -1.0;
    mat.tx_file[0] = '\0';
    mat.tx_w = -1;
    mat.tx_n = -1;

    bu_vls_strcpy( &vls, &mater->ma_shader[strlen(mat.shader)] );
    (void)bu_struct_parse( &vls, vrml_mat_parse, (char *)&mat, NULL);

    if ( bu_strncmp( "light", mat.shader, 5 ) == 0 )
    {
	/* this is a light source */
	is_light = 1;
    }
    else
    {
	fprintf( fp, "\t<Shape DEF=\"%s\">\n", full_path);
	fprintf( fp, "\t\t<Appearance>\n");

	if ( bu_strncmp( "plastic", mat.shader, 7 ) == 0 )
	{
	    if ( mat.shininess < 0 )
		mat.shininess = 10;
	    V_MAX(mat.transparency, 0.0);

	    fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0);
	}
	else if ( bu_strncmp( "glass", mat.shader, 5 ) == 0 )
	{
	    if ( mat.shininess < 0 )
		mat.shininess = 4;
	    if ( mat.transparency < 0.0 )
		mat.transparency = 0.8;

	    fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0);
	}
	else if ( mater->ma_color_valid )
	{
	    fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\"/>\n", r, g, b);
	}
	else
	{
	    /* If no color was defined set the colors according to the thousands groups */
	    int thou = comb->region_id/1000;
	    thou == 0 ? fprintf( fp, "\t\t\t<Material USE=\"Material_999\"/>\n")
		: thou == 1 ? fprintf( fp, "\t\t\t<Material USE=\"Material_1999\"/>\n")
		: thou == 2 ? fprintf( fp, "\t\t\t<Material USE=\"Material_2999\"/>\n")
		: thou == 3 ? fprintf( fp, "\t\t\t<Material USE=\"Material_3999\"/>\n")
		: thou == 4 ? fprintf( fp, "\t\t\t<Material USE=\"Material_4999\"/>\n")
		: thou == 5 ? fprintf( fp, "\t\t\t<Material USE=\"Material_5999\"/>\n")
		: thou == 6 ? fprintf( fp, "\t\t\t<Material USE=\"Material_6999\"/>\n")
		: thou == 7 ? fprintf( fp, "\t\t\t<Material USE=\"Material_7999\"/>\n")
		: thou == 8 ? fprintf( fp, "\t\t\t<Material USE=\"Material_8999\"/>\n")
		: fprintf( fp, "\t\t\t<Material USE=\"Material_9999\"/>\n");
	}
    }

    if ( !is_light )
    {
	process_non_light(m);
	fprintf( fp, "\t\t</Appearance>\n");
    }

    /* FIXME: need code to handle light */

    /* get list of vertices */
    nmg_vertex_tabulate( &verts, &m->magic );

    fprintf( fp, "\t\t<IndexedFaceSet coordIndex=\"\n");
    first = 1;
    if ( !is_light )
    {
	for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) )
	{
	    struct shell *s;

	    NMG_CK_REGION( reg );
	    for ( BU_LIST_FOR( s, shell, &reg->s_hd ) )
	    {
		struct faceuse *fu;

		NMG_CK_SHELL( s );
		for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
		{
		    struct loopuse *lu;

		    NMG_CK_FACEUSE( fu );

		    if ( fu->orientation != OT_SAME )
			continue;

		    for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
		    {
			struct edgeuse *eu;

			NMG_CK_LOOPUSE( lu );

			if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
			    continue;

			if ( !first )
			    fprintf( fp, ",\n" );
			else
			    first = 0;

			fprintf( fp, "\t\t\t\t" );
			for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
			{
			    struct vertex *v;

			    NMG_CK_EDGEUSE( eu );

			    v = eu->vu_p->v_p;
			    NMG_CK_VERTEX( v );
			    fprintf( fp, " %d,", bu_ptbl_locate( &verts, (long *)v ) );
			}
			fprintf( fp, "-1" );
		    }
		}
	    }
	}
	/* close coordIndex */
	fprintf( fp, "\" ");
	fprintf( fp, "normalPerVertex=\"false\" ");
	fprintf( fp, "convex=\"false\" ");
	fprintf( fp, "creaseAngle=\"0.5\" ");
	/* close IndexedFaceSet open tag */
	fprintf( fp, ">\n");
    }

    fprintf( fp, "\t\t\t<Coordinate point=\"");

    for ( i=0; i<BU_PTBL_END( &verts ); i++ )
    {
	struct vertex *v;
	struct vertex_g *vg;
	point_t pt_meters;

	v = (struct vertex *)BU_PTBL_GET( &verts, i );
	NMG_CK_VERTEX( v );
	vg = v->vg_p;
	NMG_CK_VERTEX_G( vg );

	/* convert to desired units */
	VSCALE( pt_meters, vg->coord, scale_factor );

	if ( is_light )
	    VADD2( ave_pt, ave_pt, pt_meters );
	if ( first )
	{
	    if ( !is_light )
		fprintf( fp, " %10.10e %10.10e %10.10e, ", V3ARGS(pt_meters));
	    first = 0;
	}
	else
	    if ( !is_light )
		fprintf( fp, "%10.10e %10.10e %10.10e, ", V3ARGS( pt_meters ));
    }

    /* close point */
    fprintf(fp, "\"");
    /* close Coordinate */
    fprintf(fp, "/>\n");
    /* IndexedFaceSet end tag */
    fprintf( fp, "\t\t</IndexedFaceSet>\n");
    /* Shape end tag */
    fprintf( fp, "\t</Shape>\n");

    BARRIER_CHECK;
}
Ejemplo n.º 13
0
/* routine to output the faceted NMG representation of a BRL-CAD region */
static void
output_nmg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id))
{
    struct model *m;
    struct shell *s;
    struct vertex *v;
    char *region_name;

    NMG_CK_REGION(r);
    RT_CK_FULL_PATH(pathp);

    region_name = db_path_to_string(pathp);

    m = r->m_p;
    NMG_CK_MODEL(m);

    /* triangulate model */
    nmg_triangulate_model(m, &tol);

    /* Output triangles */
    if (verbose) {
	printf("Convert these triangles to your format for region %s\n", region_name);
    } else {
	printf("Converted %s\n", region_name);
    }
    for (BU_LIST_FOR(s, shell, &r->s_hd))
    {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

	for (BU_LIST_FOR(fu, faceuse, &s->fu_hd))
	{
	    struct loopuse *lu;
	    /* vect_t facet_normal; */

	    NMG_CK_FACEUSE(fu);

	    if (fu->orientation != OT_SAME)
		continue;

	    /* Grab the face normal if needed */
	    /* NMG_GET_FU_NORMAL(facet_normal, fu); */

	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
	    {
		struct edgeuse *eu;

		NMG_CK_LOOPUSE(lu);

		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		/* loop through the edges in this loop (facet) */
		if (verbose)
		    printf("\tfacet:\n");
		for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd))
		{
		    NMG_CK_EDGEUSE(eu);

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);
		    if (verbose)
			printf("\t\t(%g %g %g)\n", V3ARGS(v->vg_p->coord));
		}
		tot_polygons++;
	    }
	}
    }

    bu_free(region_name, "region name");
}
Ejemplo n.º 14
0
static void
nmg_to_acad(struct nmgregion *r, const struct db_full_path *pathp, int region_id)
{
    struct model *m;
    struct shell *s;
    struct vertex *v;
    struct bu_ptbl verts;
    char *region_name;
    int numverts = 0;		/* Number of vertices to output */
    int numtri   = 0;		/* Number of triangles to output */
    int tricount = 0;		/* Triangle number */
    int i;

    NMG_CK_REGION(r);
    RT_CK_FULL_PATH(pathp);

    region_name = db_path_to_string(pathp);

    m = r->m_p;
    NMG_CK_MODEL(m);

    /* triangulate model */
    nmg_triangulate_model(m, &tol);


    /* list all vertices in result */
    nmg_vertex_tabulate(&verts, &r->l.magic);

    /* Get number of vertices */

    numverts = BU_PTBL_END (&verts);

/* BEGIN CHECK SECTION */

/* Check vertices */

    for (i=0; i<numverts; i++) {
	v = (struct vertex *)BU_PTBL_GET(&verts, i);
	NMG_CK_VERTEX(v);
    }

/* Check triangles */
    for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

	for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
	    struct loopuse *lu;

	    NMG_CK_FACEUSE(fu);

	    if (fu->orientation != OT_SAME)
		continue;

	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		struct edgeuse *eu;
		int vert_count=0;

		NMG_CK_LOOPUSE(lu);

		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		/* check vertex numbers for each triangle */
		for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
		    NMG_CK_EDGEUSE(eu);

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);

		    vert_count++;
		    i = bu_ptbl_locate(&verts, (long *)v);
		    if (i < 0) {
			bu_ptbl_free(&verts);
			bu_free(region_name, "region name");
			bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r);
			bu_exit(1, "ERROR: Triangle vertex was not located\n");
		    }
		}
		if (vert_count > 3) {
		    bu_ptbl_free(&verts);
		    bu_free(region_name, "region name");
		    bu_log("lu %p has too many (%d) vertices!\n", (void *)lu, vert_count);
		    bu_exit(1, "ERROR: LU is not a triangle\n");
		} else if (vert_count < 3)
		    continue;
		numtri++;
	    }
	}
    }

/* END CHECK SECTION */
/* Write pertinent info for this region */

    fprintf(fp, "%s\n", (region_name+1));
/* No mirror plane */
    fprintf(fp, "%d\n", 0);
/* Number of vertices */
    fprintf(fp, "%d\n", numverts);


    /* Write numverts, then vertices */

    for (i=0; i<numverts; i++) {
	v = (struct vertex *)BU_PTBL_GET(&verts, i);
	NMG_CK_VERTEX(v);
	if (inches)
	    fprintf(fp, "%f %f %f\n", V3ARGSIN(v->vg_p->coord));
	else
	    fprintf(fp, "%f %f %f\n", V3ARGS(v->vg_p->coord));
    }

/* Number of sub-parts (always 1 with BRL-CAD) */
    fprintf(fp, "%d\n", 1);
/* Write out name again */
    fprintf(fp, "%s\n", (region_name+1));
/* Number of triangles, number of vert/tri (3) */
    fprintf(fp, "%d       %d\n", numtri, 3);

    /* output triangles */
    for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

	for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
	    struct loopuse *lu;

	    NMG_CK_FACEUSE(fu);

	    if (fu->orientation != OT_SAME)
		continue;

	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		struct edgeuse *eu;
		int vert_count=0;

		NMG_CK_LOOPUSE(lu);

		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		/* list vertex numbers for each triangle */
		for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
		    NMG_CK_EDGEUSE(eu);

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);

		    vert_count++;
		    i = bu_ptbl_locate(&verts, (long *)v);
		    if (i < 0) {
			bu_ptbl_free(&verts);
			bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r);
			bu_free(region_name, "region name");
			bu_exit(1, "ERROR: Can't find vertex in list!\n");
		    }

		    fprintf(fp, " %d", i+1);
		}

		/* Output other info. for triangle ICOAT, component#, facet# */
		/* Map Icoat from material table later */
		/* fprintf(fp, "%s icomp=%d material=%d:\n", (region_name+1), region_id);*/

		fprintf(fp, " %d    %d    %d\n", 0, region_id, ++tricount);

		if (vert_count > 3) {
		    bu_ptbl_free(&verts);
		    bu_free(region_name, "region name");
		    bu_log("lu %p has %d vertices!\n", (void *)lu, vert_count);
		    bu_exit(1, "ERROR: LU is not a triangle\n");
		} else if (vert_count < 3)
		    continue;
		tot_polygons++;
	    }
	}
    }
/* regions_converted++;
   printf("Processed region %s\n", region_name);
   printf("Regions attempted = %d Regions done = %d\n", regions_tried, regions_converted);
   fflush(stdout);
*/
    bu_ptbl_free(&verts);
    bu_free(region_name, "region name");
}
Ejemplo n.º 15
0
static void
nmg_to_egg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float UNUSED(color[3]), void *client_data)
{
    struct model *m;
    struct shell *s;
    struct vertex *v;
    char *region_name;
    int region_polys=0;
    int vert_count=0;
    struct egg_conv_data *conv_data = (struct egg_conv_data *)client_data;

    NMG_CK_REGION(r);
    RT_CK_FULL_PATH(pathp);

    region_name = db_path_to_string(pathp);

    m = r->m_p;
    NMG_CK_MODEL(m);

    /* triangulate model */
    nmg_triangulate_model(m, &conv_data->tol);

    /* Write pertinent info for this region */
    fprintf(conv_data->fp, "  <VertexPool> %s {\n", (region_name+1));

    /* Build the VertexPool */
    for (BU_LIST_FOR (s, shell, &r->s_hd)) {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

	for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) {
	    struct loopuse *lu;
	    vect_t facet_normal;

	    NMG_CK_FACEUSE(fu);

	    if (fu->orientation != OT_SAME)
		continue;

	    /* Grab the face normal and save it for all the vertex loops */
	    NMG_GET_FU_NORMAL(facet_normal, fu);

	    for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) {
		struct edgeuse *eu;

		NMG_CK_LOOPUSE(lu);

		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		/* check vertex numbers for each triangle */
		for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) {
		    NMG_CK_EDGEUSE(eu);

		    vert_count++;

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);
		    fprintf(conv_data->fp, "    <Vertex> %d {\n      %f %f %f\n      <Normal> { %f %f %f }\n    }\n",
			    vert_count,
			    V3ARGS(v->vg_p->coord),
			    V3ARGS(facet_normal));
		}
	    }
	}
    }
    fprintf(conv_data->fp, "  }\n");
    vert_count = 0;

    for (BU_LIST_FOR (s, shell, &r->s_hd)) {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

	for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) {
	    struct loopuse *lu;

	    NMG_CK_FACEUSE(fu);

	    if (fu->orientation != OT_SAME)
		continue;

	    for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) {
		struct edgeuse *eu;

		NMG_CK_LOOPUSE(lu);

		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;

		fprintf(conv_data->fp, "  <Polygon> { \n    <RGBA> { 1 1 1 1 } \n    <VertexRef> { ");
		/* check vertex numbers for each triangle */
		for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) {
		    NMG_CK_EDGEUSE(eu);

		    vert_count++;

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);
		    fprintf(conv_data->fp, " %d", vert_count);
		}
		fprintf(conv_data->fp, " <Ref> { \"%s\" } }\n  }\n", region_name+1);

		region_polys++;
	    }
	}
    }

    conv_data->tot_polygons += region_polys;
    bu_free(region_name, "region name");
}
Ejemplo n.º 16
0
/**
 * Actually do the work of meshing two faces.
 * The two fu arguments may be the same, which causes the face to be
 * meshed against itself.
 *
 * The return is the number of edges meshed.
 */
int
nmg_mesh_two_faces(register struct faceuse *fu1, register struct faceuse *fu2, const struct bn_tol *tol)
{
    struct loopuse *lu1;
    struct loopuse *lu2;
    struct edgeuse *eu1;
    struct edgeuse *eu2;
    struct vertex *v1a, *v1b;
    struct edge *e1;
    pointp_t pt1, pt2;
    int count = 0;

    /* Visit all the loopuses in faceuse 1 */
    for (BU_LIST_FOR(lu1, loopuse, &fu1->lu_hd)) {
	/* Ignore self-loops */
	if (BU_LIST_FIRST_MAGIC(&lu1->down_hd) != NMG_EDGEUSE_MAGIC)
	    continue;

	/* Visit all the edgeuses in loopuse1 */
	for (BU_LIST_FOR(eu1, edgeuse, &lu1->down_hd)) {

	    v1a = eu1->vu_p->v_p;
	    v1b = eu1->eumate_p->vu_p->v_p;
	    e1 = eu1->e_p;
	    if (RTG.NMG_debug & DEBUG_MESH) {
		pt1 = v1a->vg_p->coord;
		pt2 = v1b->vg_p->coord;
		bu_log("ref_e=%8p v:%8p--%8p (%g, %g, %g)->(%g, %g, %g)\n",
		       (void *)e1, (void *)v1a, (void *)v1b,
		       V3ARGS(pt1), V3ARGS(pt2));
	    }

	    /* Visit all the loopuses in faceuse2 */
	    for (BU_LIST_FOR(lu2, loopuse, &fu2->lu_hd)) {
		/* Ignore self-loops */
		if (BU_LIST_FIRST_MAGIC(&lu2->down_hd) != NMG_EDGEUSE_MAGIC)
		    continue;
		/* Visit all the edgeuses in loopuse2 */
		for (BU_LIST_FOR(eu2, edgeuse, &lu2->down_hd)) {
		    if (RTG.NMG_debug & DEBUG_MESH) {
			pt1 = eu2->vu_p->v_p->vg_p->coord;
			pt2 = eu2->eumate_p->vu_p->v_p->vg_p->coord;
			bu_log("\te:%8p v:%8p--%8p (%g, %g, %g)->(%g, %g, %g)\n",
			       (void *)eu2->e_p,
			       (void *)eu2->vu_p->v_p,
			       (void *)eu2->eumate_p->vu_p->v_p,
			       V3ARGS(pt1), V3ARGS(pt2));
		    }

		    /* See if already shared */
		    if (eu2->e_p == e1) continue;
		    if ((eu2->vu_p->v_p == v1a &&
			 eu2->eumate_p->vu_p->v_p == v1b) ||
			(eu2->eumate_p->vu_p->v_p == v1a &&
			 eu2->vu_p->v_p == v1b)) {
			nmg_radial_join_eu(eu1, eu2, tol);
			count++;
		    }
		}
	    }
	}
    }
    return count;
}
Ejemplo n.º 17
0
static size_t
show_dangling_edges(struct ged *gedp, const uint32_t *magic_p, const char *name, int out_type)
{
    FILE *plotfp = NULL;
    const char *manifolds = NULL;
    const struct edgeuse *eur;
    int done;
    point_t pt1, pt2;
    size_t i, cnt;
    struct bn_vlblock *vbp = NULL;
    struct bu_list *vhead = NULL;
    struct bu_ptbl faces;
    struct bu_vls plot_file_name = BU_VLS_INIT_ZERO;
    struct edgeuse *eu = NULL;
    struct face *fp = NULL;
    struct faceuse *fu, *fu1, *fu2;
    struct faceuse *newfu = NULL;
    struct loopuse *lu = NULL;

    /* out_type: 0 = none, 1 = show, 2 = plot */
    if (out_type < 0 || out_type > 2) {
	bu_log("Internal error, open edge test failed.\n");
	return 0;
    }

    if (out_type == 1) {
	vbp = rt_vlblock_init();
	vhead = rt_vlblock_find(vbp, 0xFF, 0xFF, 0x00);
    }

    bu_ptbl_init(&faces, 64, "faces buffer");
    nmg_face_tabulate(&faces, magic_p);

    cnt = 0;
    for (i = 0; i < (size_t)BU_PTBL_END(&faces) ; i++) {
	fp = (struct face *)BU_PTBL_GET(&faces, i);
	NMG_CK_FACE(fp);
	fu = fu1 = fp->fu_p;
	NMG_CK_FACEUSE(fu1);
	fu2 = fp->fu_p->fumate_p;
	NMG_CK_FACEUSE(fu2);
	done = 0;
	while (!done) {
	    NMG_CK_FACEUSE(fu);
	    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		NMG_CK_LOOPUSE(lu);
		if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
		    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
			NMG_CK_EDGEUSE(eu);
			eur = nmg_radial_face_edge_in_shell(eu);
			newfu = eur->up.lu_p->up.fu_p;
			while (manifolds &&
			       NMG_MANIFOLDS(manifolds, newfu) &
			       NMG_2MANIFOLD &&
			       eur != eu->eumate_p) {
			    eur = nmg_radial_face_edge_in_shell(eur->eumate_p);
			    newfu = eur->up.lu_p->up.fu_p;
			}
			if (eur == eu->eumate_p) {
			    VMOVE(pt1, eu->vu_p->v_p->vg_p->coord);
			    VMOVE(pt2, eu->eumate_p->vu_p->v_p->vg_p->coord);
			    if (out_type == 1) {
				BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt1, BN_VLIST_LINE_MOVE);
				BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt2, BN_VLIST_LINE_DRAW);
			    } else if (out_type == 2) {
				if (!plotfp) {
				    bu_vls_sprintf(&plot_file_name, "%s.%p.pl", name, (void *)magic_p);
				    if ((plotfp = fopen(bu_vls_addr(&plot_file_name), "wb")) == (FILE *)NULL) {
					bu_vls_free(&plot_file_name);
					bu_log("Error, unable to create plot file (%s), open edge test failed.\n",
					       bu_vls_addr(&plot_file_name));
					return 0;
				    }
				}
				pdv_3line(plotfp, pt1, pt2);
			    }
			    cnt++;
			}
		    }
		}
	    }
	    if (fu == fu1) fu = fu2;
	    if (fu == fu2) done = 1;
	};

    }

    if (out_type == 1) {
	/* Add overlay */
	_ged_cvt_vlblock_to_solids(gedp, vbp, (char *)name, 0);
	rt_vlblock_free(vbp);
	bu_log("Showing open edges...\n");
    } else if (out_type == 2) {
	if (plotfp) {
	    (void)fclose(plotfp);
	    bu_log("Wrote plot file (%s)\n", bu_vls_addr(&plot_file_name));
	    bu_vls_free(&plot_file_name);
	}
    }
    bu_ptbl_free(&faces);

    return cnt;
}
Ejemplo n.º 18
0
/**
 * Make a life-and-death decision on every element of a shell.
 * Descend the "great chain of being" from the face to loop to edge to
 * vertex, saving or demoting along the way.
 *
 * Note that there is no moving of items from one shell to another.
 */
HIDDEN void
nmg_eval_shell(register struct shell *s, struct nmg_bool_state *bs)
{
    struct faceuse *fu;
    struct faceuse *nextfu;
    struct loopuse *lu;
    struct loopuse *nextlu;
    struct edgeuse *eu;
    struct edgeuse *nexteu;
    struct vertexuse *vu;
    int loops_retained;

    NMG_CK_SHELL(s);
    BN_CK_TOL(bs->bs_tol);

    if (RTG.NMG_debug & DEBUG_VERIFY)
	nmg_vshell(&s->r_p->s_hd, s->r_p);

    /*
     * For each face in the shell, process all the loops in the face,
     * and then handle the face and all loops as a unit.
     */
    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
    fu = BU_LIST_FIRST(faceuse, &s->fu_hd);
    while (BU_LIST_NOT_HEAD(fu, &s->fu_hd)) {
	NMG_CK_FACEUSE(fu);
	nextfu = BU_LIST_PNEXT(faceuse, fu);

	/* Faceuse mates will be handled at same time as OT_SAME fu */
	if (fu->orientation != OT_SAME) {
	    fu = nextfu;
	    continue;
	}
	if (fu->fumate_p == nextfu)
	    nextfu = BU_LIST_PNEXT(faceuse, nextfu);

	/* Consider this face */
	NMG_CK_FACE(fu->f_p);

	loops_retained = 0;
	lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
	while (BU_LIST_NOT_HEAD(lu, &fu->lu_hd)) {
	    NMG_CK_LOOPUSE(lu);
	    nextlu = BU_LIST_PNEXT(loopuse, lu);
	    if (lu->lumate_p == nextlu)
		nextlu = BU_LIST_PNEXT(loopuse, nextlu);

	    NMG_CK_LOOP(lu->l_p);
	    nmg_ck_lu_orientation(lu, bs->bs_tol);
	    switch (nmg_eval_action(&lu->l_p->magic, bs)) {
		case BACTION_KILL:
		    /* Kill by demoting loop to edges */
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
			/* loop of single vertex */
			(void)nmg_klu(lu);
		    } else if (nmg_demote_lu(lu) == 0) {
			nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
		    }
		    lu = nextlu;
		    continue;
		case BACTION_RETAIN:
		    loops_retained++;
		    break;
		default:
		    bu_bomb("nmg_eval_shell() bad BACTION\n");
	    }
	    lu = nextlu;
	}

	if (RTG.NMG_debug & DEBUG_BOOLEVAL)
	    bu_log("faceuse %p loops retained=%d\n",
		   (void *)fu, loops_retained);
	if (RTG.NMG_debug & DEBUG_VERIFY)
	    nmg_vshell(&s->r_p->s_hd, s->r_p);

	/*
	 * Here, faceuse will have 0 or more loopuses still in it.
	 * Decide the fate of the face;  if the face dies,
	 * then any remaining loops, edges, etc., will die too.
	 */
	if (BU_LIST_IS_EMPTY(&fu->lu_hd)) {
	    if (loops_retained) bu_bomb("nmg_eval_shell() empty faceuse with retained loops?\n");
	    /* faceuse is empty, face & mate die */
	    if (RTG.NMG_debug & DEBUG_BOOLEVAL)
		bu_log("faceuse %p empty, kill\n", (void *)fu);
	    nmg_kfu(fu);	/* kill face & mate, dequeue from shell */
	    if (RTG.NMG_debug & DEBUG_VERIFY)
		nmg_vshell(&s->r_p->s_hd, s->r_p);
	    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
	    fu = nextfu;
	    continue;
	}

	if (loops_retained <= 0) {
	    nmg_pr_fu(fu, (char *)NULL);
	    bu_bomb("nmg_eval_shell() non-empty faceuse, no loops retained?\n");
	}
	fu = nextfu;
    }
    if (RTG.NMG_debug & DEBUG_VERIFY)
	nmg_vshell(&s->r_p->s_hd, s->r_p);

    /*
     * For each loop in the shell, process.
     * Each loop is either a wire-loop, or a vertex-with-self-loop.
     * Only consider wire loops here.
     */
    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
    lu = BU_LIST_FIRST(loopuse, &s->lu_hd);
    while (BU_LIST_NOT_HEAD(lu, &s->lu_hd)) {
	NMG_CK_LOOPUSE(lu);
	nextlu = BU_LIST_PNEXT(loopuse, lu);
	if (lu->lumate_p == nextlu)
	    nextlu = BU_LIST_PNEXT(loopuse, nextlu);

	if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
	    /* ignore vertex-with-self-loop */
	    lu = nextlu;
	    continue;
	}
	NMG_CK_LOOP(lu->l_p);
	switch (nmg_eval_action(&lu->l_p->magic, bs)) {
	    case BACTION_KILL:
		/* Demote the loopuse into wire edges */
		/* kill loop & mate */
		if (nmg_demote_lu(lu) == 0)
		    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
		lu = nextlu;
		continue;
	    case BACTION_RETAIN:
		break;
	    default:
		bu_bomb("nmg_eval_shell() bad BACTION\n");
	}
	lu = nextlu;
    }
    if (RTG.NMG_debug & DEBUG_VERIFY)
	nmg_vshell(&s->r_p->s_hd, s->r_p);

    /*
     * For each wire-edge in the shell, ...
     */
    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
    eu = BU_LIST_FIRST(edgeuse, &s->eu_hd);
    while (BU_LIST_NOT_HEAD(eu, &s->eu_hd)) {
	NMG_CK_EDGEUSE(eu);
	nexteu = BU_LIST_PNEXT(edgeuse, eu);	/* may be head */
	if (eu->eumate_p == nexteu)
	    nexteu = BU_LIST_PNEXT(edgeuse, nexteu);

	/* Consider this edge */
	NMG_CK_EDGE(eu->e_p);
	switch (nmg_eval_action(&eu->e_p->magic, bs)) {
	    case BACTION_KILL:
		/* Demote the edegeuse (and mate) into vertices */
		if (nmg_demote_eu(eu) == 0)
		    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
		eu = nexteu;
		continue;
	    case BACTION_RETAIN:
		break;
	    default:
		bu_bomb("nmg_eval_shell() bad BACTION\n");
	}
	eu = nexteu;
    }

    /*
     * For each lone vertex-with-self-loop, process.
     * Note that these are intermixed in the loop list.
     * Each loop is either a wire-loop, or a vertex-with-self-loop.
     * Only consider cases of vertex-with-self-loop here.
     *
     * This case has to be handled separately, because a wire-loop
     * may be demoted to a set of wire-edges above, some of which
     * may be retained.  The non-retained wire-edges may in turn
     * be demoted into vertex-with-self-loop objects above,
     * which will be processed here.
     */
    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
    lu = BU_LIST_FIRST(loopuse, &s->lu_hd);
    while (BU_LIST_NOT_HEAD(lu, &s->lu_hd)) {
	NMG_CK_LOOPUSE(lu);
	nextlu = BU_LIST_PNEXT(loopuse, lu);

	if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_VERTEXUSE_MAGIC) {
	    /* ignore any remaining wire-loops */
	    lu = nextlu;
	    continue;
	}
	if (nextlu == lu->lumate_p)
	    nextlu = BU_LIST_PNEXT(loopuse, nextlu);
	vu = BU_LIST_PNEXT(vertexuse, &lu->down_hd);
	NMG_CK_VERTEXUSE(vu);
	NMG_CK_VERTEX(vu->v_p);
	switch (nmg_eval_action(&vu->v_p->magic, bs)) {
	    case BACTION_KILL:
		/* Eliminate the loopuse, and mate */
		nmg_klu(lu);
		lu = nextlu;
		continue;
	    case BACTION_RETAIN:
		break;
	    default:
		bu_bomb("nmg_eval_shell() bad BACTION\n");
	}
	lu = nextlu;
    }
    if (RTG.NMG_debug & DEBUG_VERIFY)
	nmg_vshell(&s->r_p->s_hd, s->r_p);

    /*
     * Final case:  shell of a single vertexuse
     */
    vu = s->vu_p;
    if (vu) {
	NMG_CK_VERTEXUSE(vu);
	NMG_CK_VERTEX(vu->v_p);
	switch (nmg_eval_action(&vu->v_p->magic, bs)) {
	    case BACTION_KILL:
		nmg_kvu(vu);
		nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
		s->vu_p = (struct vertexuse *)0;	/* sanity */
		break;
	    case BACTION_RETAIN:
		break;
	    default:
		bu_bomb("nmg_eval_shell() bad BACTION\n");
	}
    }
    if (RTG.NMG_debug & DEBUG_VERIFY)
	nmg_vshell(&s->r_p->s_hd, s->r_p);
    nmg_eval_plot(bs, nmg_eval_count++);	/* debug */
}
HIDDEN int
nmg_brep_face(ON_Brep **b, const struct faceuse *fu, const struct bn_tol *tol, long *brepi) {
    const struct face_g_plane *fg = fu->f_p->g.plane_p;
    struct bu_ptbl vert_table;
    struct vertex **pt;
    int ret = 0;
    int pnt_cnt = 0;
    int pnt_index = 0;
    vect_t u_axis, v_axis;
    point_t obr_center;
    point_t *points_3d = NULL;
    point_t *points_obr = NULL;
    struct loopuse *lu;
    struct edgeuse *eu;

    /* Find out how many points we have, set up any uninitialized ON_Brep vertex
     * structures, and prepare a map of NMG index values to the point array indices */
    nmg_tabulate_face_g_verts(&vert_table, fg);

    for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
	if (brepi[(*pt)->vg_p->index] == -INT_MAX) {
	    ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF);
	    brepi[(*pt)->vg_p->index] = vert.m_vertex_index;
	}
	pnt_cnt++;
    }

    /* Prepare the 3D obr input array */
    points_3d = (point_t *)bu_calloc(pnt_cnt + 1, sizeof(point_t), "nmg points");
    for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
	VSET(points_3d[pnt_index], (*pt)->vg_p->coord[0],(*pt)->vg_p->coord[1],(*pt)->vg_p->coord[2]);
	pnt_index++;
    }
    bu_ptbl_free(&vert_table);


    /* Calculate the 3D coplanar oriented bounding rectangle (obr) */
    ret += bg_3d_coplanar_obr(&obr_center, &u_axis, &v_axis, (const point_t *)points_3d, pnt_cnt);
    if (ret) {
	bu_log("Failed to get oriented bounding rectangle for NMG faceuse #%lu\n", fu->index);
	return -1;
    }
    bu_free(points_3d, "done with obr 3d point inputs");

    /* Use the obr to define the 3D corner points of the NURBS surface */
    points_obr = (point_t *)bu_calloc(3 + 1, sizeof(point_t), "points_3d");
    VADD3(points_obr[2], obr_center, u_axis, v_axis);
    VSCALE(u_axis, u_axis, -1);
    VADD3(points_obr[3], obr_center, u_axis, v_axis);
    VSCALE(v_axis, v_axis, -1);
    VADD3(points_obr[0], obr_center, u_axis, v_axis);
    VSCALE(u_axis, u_axis, -1);
    VADD3(points_obr[1], obr_center, u_axis, v_axis);

    /* We need to orient our surface correctly according to the NMG - using
     * the openNURBS FlipFace function later does not seem to work very
     * well. If an outer loop is found in the NMG with a cw orientation,
     * factor that in in addition to the fu->f_p->flip flag. */
    int ccw = 0;
    vect_t vtmp, uv1, uv2, vnormal;
    point_t center;
    VADD2(center, points_obr[0], points_obr[1]);
    VADD2(center, center, points_obr[2]);
    VADD2(center, center, points_obr[3]);
    VSCALE(center, center, 0.25);
    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
	if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1;
    }
    if (ccw != -1) {
	VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]);
    } else {
	VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]);
    }
    if (fu->f_p->flip)
	VSET(vnormal, -vnormal[0], -vnormal[1], -vnormal[2]);
    VSUB2(uv1, points_obr[0], center);
    VSUB2(uv2, points_obr[1], center);
    VCROSS(vtmp, uv1, uv2);
    if (VDOT(vtmp, vnormal) < 0) {
	VMOVE(vtmp, points_obr[0]);
	VMOVE(points_obr[0], points_obr[1]);
	VMOVE(points_obr[1], vtmp);
	VMOVE(vtmp, points_obr[3]);
	VMOVE(points_obr[3], points_obr[2]);
	VMOVE(points_obr[2], vtmp);
    }

    /* Now that we've got our points correctly oriented for
     * the NURBS surface, proceed to create it. */
    ON_3dPoint p1 = ON_3dPoint(points_obr[0]);
    ON_3dPoint p2 = ON_3dPoint(points_obr[1]);
    ON_3dPoint p3 = ON_3dPoint(points_obr[2]);
    ON_3dPoint p4 = ON_3dPoint(points_obr[3]);

    (*b)->m_S.Append(sideSurface(p1, p2, p3, p4));
    ON_Surface *surf = (*(*b)->m_S.Last());
    int surfindex = (*b)->m_S.Count();
    ON_BrepFace& face = (*b)->NewFace(surfindex - 1);

    // With the surface and the face defined, make
    // trimming loops and create faces.  To generate UV
    // coordinates for each from and to for the
    // edgecurves, the UV origin is defined to be v1,
    // v1->v2 is defined as the U domain, and v1->v4 is
    // defined as the V domain.
    VSUB2(u_axis, points_obr[2], points_obr[1]);
    VSUB2(v_axis, points_obr[0], points_obr[1]);
    fastf_t u_axis_dist = MAGNITUDE(u_axis);
    fastf_t v_axis_dist = MAGNITUDE(v_axis);

    /* Now that we have the surface and the face, add the loops */
    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
	if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex
	// Check if this is an inner or outer loop
	ON_BrepLoop::TYPE looptype = (lu->orientation == OT_SAME) ? ON_BrepLoop::outer : ON_BrepLoop::inner;
	ON_BrepLoop& loop = (*b)->NewLoop(looptype, face);
	for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
	    vect_t ev1, ev2;
	    struct vertex_g *vg1 = eu->vu_p->v_p->vg_p;
	    struct vertex_g *vg2 = eu->eumate_p->vu_p->v_p->vg_p;
	    NMG_CK_VERTEX_G(vg1);
	    NMG_CK_VERTEX_G(vg2);
	    VMOVE(ev1, vg1->coord);
	    VMOVE(ev2, vg2->coord);
	    // Add edge if not already added
	    if (brepi[eu->e_p->index] == -INT_MAX) {
		/* always add edges with the small vertex index as from */
		int vert1 = (vg1->index <= vg2->index) ? brepi[vg1->index] : brepi[vg2->index];
		int vert2 = (vg1->index > vg2->index) ? brepi[vg1->index] : brepi[vg2->index];
		// Create and add 3D curve
		ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point());
		c3d->SetDomain(0.0, 1.0);
		(*b)->m_C3.Append(c3d);
		// Create and add 3D edge
		ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1);
		e.m_tolerance = 0.0;
		brepi[eu->e_p->index] = e.m_edge_index;
	    }
	    // Regardless of whether the edge existed as an object, it needs to be added to the trimming loop
	    ON_3dPoint vg1pt(vg1->coord);
	    int orientation = ((vg1pt != (*b)->m_V[(*b)->m_E[(int)brepi[eu->e_p->index]].m_vi[0]].Point())) ? 1 : 0;
	    // Make a 2d trimming curve, create a trim, and add the trim to the loop
	    vect_t vect1, vect2, u_component, v_component;
	    double u0, u1, v0, v1;
	    ON_2dPoint from_uv, to_uv;
	    VSUB2(vect1, ev1, points_obr[0]);
	    VSUB2(vect2, ev2, points_obr[0]);
	    surf->GetDomain(0, &u0, &u1);
	    surf->GetDomain(1, &v0, &v1);
	    VPROJECT(vect1, u_axis, u_component, v_component);
	    from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
	    from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
	    VPROJECT(vect2, u_axis, u_component, v_component);
	    to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
	    to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
	    ON_Curve* c2d =  new ON_LineCurve(from_uv, to_uv);
	    c2d->SetDomain(0.0, 1.0);
	    int c2i = (*b)->m_C2.Count();
	    (*b)->m_C2.Append(c2d);
	    ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[(int)brepi[eu->e_p->index]], orientation, loop, c2i);
	    trim.m_type = ON_BrepTrim::mated;
	    trim.m_tolerance[0] = 0.0;
	    trim.m_tolerance[1] = 0.0;
	}
    }

    bu_free(points_obr, "Done with obr");

    return 0;
}
Ejemplo n.º 20
0
/*
 * Default keypoint in model space is established in "pt". Returns
 * GED_ERROR if unable to determine a keypoint, otherwise returns
 * GED_OK.
 */
int
_ged_get_solid_keypoint(struct ged *const gedp,
			fastf_t *const pt,
			const struct rt_db_internal *const ip,
			const fastf_t *const mat)
{
    point_t mpt;

    RT_CK_DB_INTERNAL(ip);

    switch (ip->idb_type) {
	case ID_CLINE:
	    {
		struct rt_cline_internal *cli =
		    (struct rt_cline_internal *)ip->idb_ptr;

		RT_CLINE_CK_MAGIC(cli);

		VMOVE(mpt, cli->v);
		break;
	    }
	case ID_PARTICLE:
	    {
		struct rt_part_internal *part =
		    (struct rt_part_internal *)ip->idb_ptr;

		RT_PART_CK_MAGIC(part);

		VMOVE(mpt, part->part_V);
		break;
	    }
	case ID_PIPE:
	    {
		struct rt_pipe_internal *pipeip;
		struct wdb_pipept *pipe_seg;

		pipeip = (struct rt_pipe_internal *)ip->idb_ptr;

		RT_PIPE_CK_MAGIC(pipeip);

		pipe_seg = BU_LIST_FIRST(wdb_pipept, &pipeip->pipe_segs_head);
		VMOVE(mpt, pipe_seg->pp_coord);
		break;
	    }
	case ID_METABALL:
	    {
		struct rt_metaball_internal *metaball =
		    (struct rt_metaball_internal *)ip->idb_ptr;
		struct wdb_metaballpt *metaballpt;

		RT_METABALL_CK_MAGIC(metaball);

		VSETALL(mpt, 0.0);
		metaballpt = BU_LIST_FIRST(wdb_metaballpt,
					   &metaball->metaball_ctrl_head);
		VMOVE(mpt, metaballpt->coord);
		break;
	    }
	case ID_ARBN:
	    {
		struct rt_arbn_internal *arbn =
		    (struct rt_arbn_internal *)ip->idb_ptr;
		size_t i, j, k;
		int good_vert = 0;

		RT_ARBN_CK_MAGIC(arbn);
		for (i = 0; i < arbn->neqn; i++) {
		    for (j = i + 1; j < arbn->neqn; j++) {
			for (k = j + 1; k < arbn->neqn; k++) {
			    if (!bn_mkpoint_3planes(mpt, arbn->eqn[i],
						    arbn->eqn[j],
						    arbn->eqn[k])) {
				size_t l;

				good_vert = 1;
				for (l = 0; l < arbn->neqn; l++) {
				    if (l == i || l == j || l == k)
					continue;

				    if (DIST_PT_PLANE(mpt,
					arbn->eqn[l]) >
					gedp->ged_wdbp->wdb_tol.dist) {
					good_vert = 0;
					break;
				    }
				}

				if (good_vert)
				    break;
			    }
			}
			if (good_vert)
			    break;
		    }
		    if (good_vert)
			break;
		}

		break;
	    }
	case ID_EBM:
	    {
		struct rt_ebm_internal *ebm =
		    (struct rt_ebm_internal *)ip->idb_ptr;
		point_t pnt;

		RT_EBM_CK_MAGIC(ebm);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, ebm->mat, pnt);
		break;
	    }
	case ID_BOT:
	    {
		struct rt_bot_internal *bot =
		    (struct rt_bot_internal *)ip->idb_ptr;

		    VMOVE(mpt, bot->vertices);
		break;
	    }
	case ID_DSP:
	    {
		struct rt_dsp_internal *dsp =
		    (struct rt_dsp_internal *)ip->idb_ptr;
		point_t pnt;

		RT_DSP_CK_MAGIC(dsp);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, dsp->dsp_stom, pnt);
		break;
	    }
	case ID_HF:
	    {
		struct rt_hf_internal *hf =
		    (struct rt_hf_internal *)ip->idb_ptr;

		RT_HF_CK_MAGIC(hf);

		VMOVE(mpt, hf->v);
		break;
	    }
	case ID_VOL:
	    {
		struct rt_vol_internal *vol =
		    (struct rt_vol_internal *)ip->idb_ptr;
		point_t pnt;

		RT_VOL_CK_MAGIC(vol);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, vol->mat, pnt);
		break;
	    }
	case ID_HALF:
	    {
		struct rt_half_internal *haf =
		    (struct rt_half_internal *)ip->idb_ptr;
		RT_HALF_CK_MAGIC(haf);

		VSCALE(mpt, haf->eqn, haf->eqn[H]);
		break;
	    }
	case ID_ARB8:
	    {
		struct rt_arb_internal *arb =
		    (struct rt_arb_internal *)ip->idb_ptr;
		RT_ARB_CK_MAGIC(arb);

		VMOVE(mpt, arb->pt[0]);
		break;
	    }
	case ID_ELL:
	case ID_SPH:
	    {
		struct rt_ell_internal *ell =
		    (struct rt_ell_internal *)ip->idb_ptr;
		RT_ELL_CK_MAGIC(ell);

		VMOVE(mpt, ell->v);
		break;
	    }
	case ID_SUPERELL:
	    {
		struct rt_superell_internal *superell =
		    (struct rt_superell_internal *)ip->idb_ptr;
		RT_SUPERELL_CK_MAGIC(superell);

		VMOVE(mpt, superell->v);
		break;
	    }
	case ID_TOR:
	    {
		struct rt_tor_internal *tor =
		    (struct rt_tor_internal *)ip->idb_ptr;
		RT_TOR_CK_MAGIC(tor);

		VMOVE(mpt, tor->v);
		break;
	    }
	case ID_TGC:
	case ID_REC:
	    {
		struct rt_tgc_internal *tgc =
		    (struct rt_tgc_internal *)ip->idb_ptr;
		RT_TGC_CK_MAGIC(tgc);

		VMOVE(mpt, tgc->v);
		break;
	    }
	case ID_GRIP:
	    {
		struct rt_grip_internal *gip =
		    (struct rt_grip_internal *)ip->idb_ptr;
		RT_GRIP_CK_MAGIC(gip);
		VMOVE(mpt, gip->center);
		break;
	    }
	case ID_ARS:
	    {
		struct rt_ars_internal *ars =
		    (struct rt_ars_internal *)ip->idb_ptr;
		RT_ARS_CK_MAGIC(ars);

		VMOVE(mpt, &ars->curves[0][0]);
		break;
	    }
	case ID_RPC:
	    {
		struct rt_rpc_internal *rpc =
		    (struct rt_rpc_internal *)ip->idb_ptr;
		RT_RPC_CK_MAGIC(rpc);

		VMOVE(mpt, rpc->rpc_V);
		break;
	    }
	case ID_RHC:
	    {
		struct rt_rhc_internal *rhc =
		    (struct rt_rhc_internal *)ip->idb_ptr;
		RT_RHC_CK_MAGIC(rhc);

		VMOVE(mpt, rhc->rhc_V);
		break;
	    }
	case ID_EPA:
	    {
		struct rt_epa_internal *epa =
		    (struct rt_epa_internal *)ip->idb_ptr;
		RT_EPA_CK_MAGIC(epa);

		VMOVE(mpt, epa->epa_V);
		break;
	    }
	case ID_EHY:
	    {
		struct rt_ehy_internal *ehy =
		    (struct rt_ehy_internal *)ip->idb_ptr;
		RT_EHY_CK_MAGIC(ehy);

		VMOVE(mpt, ehy->ehy_V);
		break;
	    }
	case ID_HYP:
	    {
		struct rt_hyp_internal *hyp =
		    (struct rt_hyp_internal *)ip->idb_ptr;
		RT_HYP_CK_MAGIC(hyp);

		VMOVE(mpt, hyp->hyp_Vi);
		break;
	    }
	case ID_ETO:
	    {
		struct rt_eto_internal *eto =
		    (struct rt_eto_internal *)ip->idb_ptr;
		RT_ETO_CK_MAGIC(eto);

		VMOVE(mpt, eto->eto_V);
		break;
	    }
	case ID_POLY:
	    {
		struct rt_pg_face_internal *_poly;
		struct rt_pg_internal *pg =
		    (struct rt_pg_internal *)ip->idb_ptr;
		RT_PG_CK_MAGIC(pg);

		_poly = pg->poly;
		VMOVE(mpt, _poly->verts);
		break;
	    }
	case ID_SKETCH:
	    {
		struct rt_sketch_internal *skt =
		    (struct rt_sketch_internal *)ip->idb_ptr;
		RT_SKETCH_CK_MAGIC(skt);

		VMOVE(mpt, skt->V);
		break;
	    }
	case ID_EXTRUDE:
	    {
		struct rt_extrude_internal *extr =
		    (struct rt_extrude_internal *)ip->idb_ptr;
		RT_EXTRUDE_CK_MAGIC(extr);

		if (extr->skt && extr->skt->verts) {
		    VJOIN2(mpt, extr->V, extr->skt->verts[0][0], extr->u_vec,
			   extr->skt->verts[0][1], extr->v_vec);
		} else {
		    VMOVE(mpt, extr->V);
		}
		break;
	    }
	case ID_NMG:
	    {
		struct vertex *v;
		struct vertexuse *vu;
		struct edgeuse *eu;
		struct loopuse *lu;
		struct faceuse *fu;
		struct shell *s;
		struct nmgregion *r;
		struct model *m =
		    (struct model *) ip->idb_ptr;
		NMG_CK_MODEL(m);

		/* set default first */
		VSETALL(mpt, 0.0);

		if (BU_LIST_IS_EMPTY(&m->r_hd))
		    break;

		r = BU_LIST_FIRST(nmgregion, &m->r_hd);
		if (!r)
		    break;
		NMG_CK_REGION(r);

		if (BU_LIST_IS_EMPTY(&r->s_hd))
		    break;

		s = BU_LIST_FIRST(shell, &r->s_hd);
		if (!s)
		    break;
		NMG_CK_SHELL(s);

		if (BU_LIST_IS_EMPTY(&s->fu_hd))
		    fu = (struct faceuse *)NULL;
		else
		    fu = BU_LIST_FIRST(faceuse, &s->fu_hd);
		if (fu) {
		    NMG_CK_FACEUSE(fu);
		    lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
		    NMG_CK_LOOPUSE(lu);
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
			eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
			NMG_CK_EDGEUSE(eu);
			NMG_CK_VERTEXUSE(eu->vu_p);
			v = eu->vu_p->v_p;
		    } else {
			vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
			NMG_CK_VERTEXUSE(vu);
			v = vu->v_p;
		    }
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		if (BU_LIST_IS_EMPTY(&s->lu_hd))
		    lu = (struct loopuse *)NULL;
		else
		    lu = BU_LIST_FIRST(loopuse, &s->lu_hd);
		if (lu) {
		    NMG_CK_LOOPUSE(lu);
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
			eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
			NMG_CK_EDGEUSE(eu);
			NMG_CK_VERTEXUSE(eu->vu_p);
			v = eu->vu_p->v_p;
		    } else {
			vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
			NMG_CK_VERTEXUSE(vu);
			v = vu->v_p;
		    }
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		if (BU_LIST_IS_EMPTY(&s->eu_hd))
		    eu = (struct edgeuse *)NULL;
		else
		    eu = BU_LIST_FIRST(edgeuse, &s->eu_hd);
		if (eu) {
		    NMG_CK_EDGEUSE(eu);
		    NMG_CK_VERTEXUSE(eu->vu_p);
		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		vu = s->vu_p;
		if (vu) {
		    NMG_CK_VERTEXUSE(vu);
		    v = vu->v_p;
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
	    }
	default:
	    VSETALL(mpt, 0.0);
	    bu_vls_printf(gedp->ged_result_str,
			  "get_solid_keypoint: unrecognized solid type");
	    return GED_ERROR;
    }
    MAT4X3PNT(pt, mat, mpt);
    return GED_OK;
}
Ejemplo n.º 21
0
int
nmg_uv_in_lu(const fastf_t u, const fastf_t v, const struct loopuse *lu)
{
    struct edgeuse *eu;
    int crossings=0;

    NMG_CK_LOOPUSE( lu );

    if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
	return( 0 );

    for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
    {
	struct edge_g_cnurb *eg;

	if ( !eu->g.magic_p )
	{
	    bu_log( "nmg_uv_in_lu: eu (x%x) has no geometry!!!\n", eu );
	    bu_bomb( "nmg_uv_in_lu: eu has no geometry!!!\n" );
	}

	if ( *eu->g.magic_p != NMG_EDGE_G_CNURB_MAGIC )
	{
	    bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing eu (x%x) that is not CNURB!!!!\n",
		    lu, eu );
	    bu_bomb( "nmg_uv_in_lu: Called with lu containing eu that is not CNURB!!!\n" );
	}

	eg = eu->g.cnurb_p;

	if ( eg->order <= 0 )
	{
	    struct vertexuse *vu1, *vu2;
	    struct vertexuse_a_cnurb *vua1, *vua2;
	    point_t uv1, uv2;
	    fastf_t slope, intersept;
	    fastf_t u_on_curve;

	    vu1 = eu->vu_p;
	    vu2 = eu->eumate_p->vu_p;

	    if ( !vu1->a.magic_p || !vu2->a.magic_p )
	    {
		bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu with no attribute!!!!\n",
			lu );
		bu_bomb( "nmg_uv_in_lu: Called with lu containing vu with no attribute!!!\n" );
	    }

	    if ( *vu1->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC ||
		 *vu2->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
	    {
		bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu that is not CNURB!!!!\n",
			lu );
		bu_bomb( "nmg_uv_in_lu: Called with lu containing vu that is not CNURB!!!\n" );
	    }

	    vua1 = vu1->a.cnurb_p;
	    vua2 = vu2->a.cnurb_p;

	    VMOVE( uv1, vua1->param );
	    VMOVE( uv2, vua2->param );

	    if ( RT_NURB_IS_PT_RATIONAL( eg->pt_type ) )
	    {
		uv1[0] /= uv1[2];
		uv1[1] /= uv1[2];
		uv2[0] /= uv2[2];
		uv2[1] /= uv2[2];
	    }

	    if ( uv1[1] < v && uv2[1] < v )
		continue;
	    if ( uv1[1] > v && uv2[1] > v )
		continue;
	    if ( uv1[0] <= u && uv2[0] <= u )
		continue;
	    if ( uv1[0] == uv2[0] )
	    {
		if ( (uv1[1] <= v && uv2[1] >= v) ||
		     (uv2[1] <= v && uv1[1] >= v) )
		    crossings++;

		continue;
	    }

	    /* need to calculate intersection */
	    slope = (uv1[1] - uv2[1])/(uv1[0] - uv2[0]);
	    intersept = uv1[1] - slope * uv1[0];
	    u_on_curve = (v - intersept)/slope;
	    if ( u_on_curve > u )
		crossings++;
	}
	else
	    crossings += rt_uv_in_trim( eg, u, v );
    }

    if ( crossings & 01 )
	return( 1 );
    else
	return( 0 );
}