bool ON_Brep::Morph( const ON_SpaceMorph& morph ) { bool rc = IsMorphable(); if ( rc ) { ON_Surface* srf = const_cast<ON_Surface*>(m_F[0].SurfaceOf()); if ( srf->IsMorphable() ) { rc = srf->Morph(morph); } else { ON_NurbsSurface* new_srf = srf->NurbsSurface(); if ( !new_srf ) return false; rc = new_srf->Morph(morph); if (rc) { int si = m_F[0].m_si; m_F[0].SetProxySurface(new_srf); delete srf; srf = new_srf; m_S[si] = srf; DestroyMesh(ON::any_mesh,true); } else { delete new_srf; new_srf = 0; } } if ( rc ) { double tol = 0.01; rc = RebuildEdges( m_F[0], tol, true, true ); DestroyMesh(ON::analysis_mesh); DestroyMesh(ON::preview_mesh); ON_Mesh* mesh = const_cast<ON_Mesh*>(m_F[0].Mesh(ON::render_mesh)); if ( mesh ) mesh->EvaluateMeshGeometry( *srf ); } } return rc; }
void ON_SurfaceProxy::DestroyRuntimeCache( bool bDelete ) { if ( m_stree ) { #if defined(OPENNURBS_PLUS_INC_) if ( bDelete ) delete m_stree; #endif m_stree = 0; } if ( 0 != m_surface && m_surface != this ) { ON_Surface* surface = const_cast<ON_Surface*>(m_surface); if ( 0 != surface ) surface->DestroyRuntimeCache( bDelete ); } }
void ON_GL( const ON_Surface& surface, // GLUnurbsObj* nobj // created with gluNewNurbsRenderer ) { ON_NurbsSurface tmp; const ON_NurbsSurface* nurbs_surface; nurbs_surface = ON_NurbsSurface::Cast(&surface); if ( !nurbs_surface ) { if ( surface.GetNurbForm(tmp) ) { nurbs_surface = &tmp; } } if ( nurbs_surface ) ON_GL( *nurbs_surface, nobj, 0, true ); }
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[]"); }
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; }
void subbrep_planar_init(struct subbrep_object_data *data) { if (!data) return; if (data->planar_obj) return; BU_GET(data->planar_obj, struct subbrep_object_data); subbrep_object_init(data->planar_obj, data->brep); bu_vls_sprintf(data->planar_obj->key, "%s", bu_vls_addr(data->key)); data->planar_obj->obj_cnt = data->obj_cnt; (*data->obj_cnt)++; bu_vls_sprintf(data->planar_obj->name_root, "%s_%d", bu_vls_addr(data->name_root), *(data->obj_cnt)); data->planar_obj->type = PLANAR_VOLUME; data->planar_obj->local_brep = ON_Brep::New(); std::map<int, int> face_map; std::map<int, int> surface_map; std::map<int, int> edge_map; std::map<int, int> vertex_map; std::map<int, int> loop_map; std::map<int, int> c3_map; std::map<int, int> c2_map; std::map<int, int> trim_map; std::set<int> faces; std::set<int> fil; std::set<int> loops; std::set<int> skip_verts; std::set<int> skip_edges; std::set<int> keep_verts; std::set<int> partial_edges; std::set<int> isolated_trims; // collect 2D trims whose parent loops aren't fully included here array_to_set(&faces, data->faces, data->faces_cnt); array_to_set(&fil, data->fil, data->fil_cnt); array_to_set(&loops, data->loops, data->loops_cnt); std::map<int, std::set<int> > face_loops; std::map<int, std::set<int> >::iterator fl_it; std::set<int>::iterator l_it; for (int i = 0; i < data->edges_cnt; i++) { int c3i; int new_edge_curve = 0; const ON_BrepEdge *old_edge = &(data->brep->m_E[data->edges[i]]); //std::cout << "old edge: " << old_edge->Vertex(0)->m_vertex_index << "," << old_edge->Vertex(1)->m_vertex_index << "\n"; // See if the vertices from this edge play a role in the planar volume int use_edge = 2; for (int vi = 0; vi < 2; vi++) { int vert_test = -1; int vert_ind = old_edge->Vertex(vi)->m_vertex_index; if (skip_verts.find(vert_ind) != skip_verts.end()) { vert_test = 1; } if (vert_test == -1 && keep_verts.find(vert_ind) != keep_verts.end()) { vert_test = 0; } if (vert_test == -1) { vert_test = characterize_vert(data, old_edge->Vertex(vi)); if (vert_test) { skip_verts.insert(vert_ind); ON_3dPoint vp = old_edge->Vertex(vi)->Point(); bu_log("vert %d (%f %f %f): %d\n", vert_ind, vp.x, vp.y, vp.z, vert_test); } else { keep_verts.insert(vert_ind); } } if (vert_test == 1) { use_edge--; } } if (use_edge == 0) { bu_log("skipping edge %d - both verts are skips\n", old_edge->m_edge_index); skip_edges.insert(old_edge->m_edge_index); continue; } if (use_edge == 1) { bu_log("One of the verts for edge %d is a skip.\n", old_edge->m_edge_index); partial_edges.insert(old_edge->m_edge_index); continue; } // Get the 3D curves from the edges if (c3_map.find(old_edge->EdgeCurveIndexOf()) == c3_map.end()) { ON_Curve *nc = old_edge->EdgeCurveOf()->Duplicate(); ON_Curve *tc = old_edge->EdgeCurveOf()->Duplicate(); if (tc->IsLinear()) { c3i = data->planar_obj->local_brep->AddEdgeCurve(nc); c3_map[old_edge->EdgeCurveIndexOf()] = c3i; } else { ON_Curve *c3 = new ON_LineCurve(old_edge->Vertex(0)->Point(), old_edge->Vertex(1)->Point()); c3i = data->planar_obj->local_brep->AddEdgeCurve(c3); c3_map[old_edge->EdgeCurveIndexOf()] = c3i; new_edge_curve = 1; } } else { c3i = c3_map[old_edge->EdgeCurveIndexOf()]; } // Get the vertices from the edges int v[2]; for (int vi = 0; vi < 2; vi++) { if (vertex_map.find(old_edge->Vertex(vi)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(old_edge->Vertex(vi)->Point(), old_edge->Vertex(vi)->m_tolerance); v[vi] = newvvi.m_vertex_index; vertex_map[old_edge->Vertex(vi)->m_vertex_index] = v[vi]; } else { v[vi] = vertex_map[old_edge->Vertex(vi)->m_vertex_index]; } } ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[v[0]], data->planar_obj->local_brep->m_V[v[1]], c3i, NULL ,0); edge_map[old_edge->m_edge_index] = new_edge.m_edge_index; // Get the 2D curves from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); if (faces.find(old_trim->Face()->m_face_index) != faces.end()) { if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) { ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate(); int c2i = data->planar_obj->local_brep->AddTrimCurve(nc); c2_map[old_trim->TrimCurveIndexOf()] = c2i; //std::cout << "c2i: " << c2i << "\n"; } } } // Get the faces and surfaces from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); if (face_map.find(old_trim->Face()->m_face_index) == face_map.end()) { if (faces.find(old_trim->Face()->m_face_index) != faces.end()) { ON_Surface *ns = old_trim->Face()->SurfaceOf()->Duplicate(); ON_Surface *ts = old_trim->Face()->SurfaceOf()->Duplicate(); if (ts->IsPlanar(NULL, BREP_PLANAR_TOL)) { int nsid = data->planar_obj->local_brep->AddSurface(ns); surface_map[old_trim->Face()->SurfaceIndexOf()] = nsid; ON_BrepFace &new_face = data->planar_obj->local_brep->NewFace(nsid); face_map[old_trim->Face()->m_face_index] = new_face.m_face_index; //std::cout << "old face " << old_trim->Face()->m_face_index << " is now " << new_face.m_face_index << "\n"; if (fil.find(old_trim->Face()->m_face_index) != fil.end()) { data->planar_obj->local_brep->FlipFace(new_face); } } } } } // Get the loops from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); ON_BrepLoop *old_loop = old_trim->Loop(); if (face_map.find(old_trim->Face()->m_face_index) != face_map.end()) { if (loops.find(old_loop->m_loop_index) != loops.end()) { if (loop_map.find(old_loop->m_loop_index) == loop_map.end()) { face_loops[old_trim->Face()->m_face_index].insert(old_loop->m_loop_index); } } } } } for (fl_it = face_loops.begin(); fl_it != face_loops.end(); fl_it++) { int loop_cnt = fl_it->second.size(); if (loop_cnt == 1) { // If we have only one loop on a face it's an outer loop, // whatever it was in the original brep. const ON_BrepLoop *old_loop = &(data->brep->m_L[*(fl_it->second.begin())]); ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } else { bu_log("loop_cnt: %d\n", loop_cnt); // If we ended up with multiple loops, one of them should be an outer loop // and the rest inner loops // Get the outer loop first for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]); if (data->brep->LoopDirection(data->brep->m_L[*l_it]) == 1) { ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } } // Now get the inner loops; for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]); if (data->brep->LoopDirection(data->brep->m_L[*l_it]) != 1) { ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::inner, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } } } } // Now, create new trims using the old loop definitions and the maps std::map<int, int>::iterator loop_it; std::set<int> evaluated; for (loop_it = loop_map.begin(); loop_it != loop_map.end(); loop_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[(*loop_it).first]); ON_BrepLoop &new_loop = data->planar_obj->local_brep->m_L[(*loop_it).second]; for (int j = 0; j < old_loop->TrimCount(); j++) { const ON_BrepTrim *old_trim = old_loop->Trim(j); ON_BrepEdge *o_edge = old_trim->Edge(); if (!o_edge) { /* If we didn't have an edge originally, we need to add the 2d curve here */ if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) { ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate(); int c2i = data->planar_obj->local_brep->AddTrimCurve(nc); c2_map[old_trim->TrimCurveIndexOf()] = c2i; } if (vertex_map.find(old_trim->Vertex(0)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvs = data->planar_obj->local_brep->NewVertex(old_trim->Vertex(0)->Point(), old_trim->Vertex(0)->m_tolerance); vertex_map[old_trim->Vertex(0)->m_vertex_index] = newvs.m_vertex_index; ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(newvs, new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; } else { ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(data->planar_obj->local_brep->m_V[vertex_map[old_trim->Vertex(0)->m_vertex_index]], new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; } continue; } if (evaluated.find(o_edge->m_edge_index) != evaluated.end()) { bu_log("edge %d already handled, continuing...\n", o_edge->m_edge_index); continue; } // Don't use a trim connected to an edge we are skipping if (skip_edges.find(o_edge->m_edge_index) != skip_edges.end()) { bu_log("edge %d is skipped, continuing...\n", o_edge->m_edge_index); evaluated.insert(o_edge->m_edge_index); continue; } int is_partial = 0; if (partial_edges.find(o_edge->m_edge_index) != partial_edges.end()) is_partial = 1; if (!is_partial) { ON_BrepEdge &n_edge = data->planar_obj->local_brep->m_E[edge_map[o_edge->m_edge_index]]; ON_Curve *ec = o_edge->EdgeCurveOf()->Duplicate(); if (ec->IsLinear()) { ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; } else { // Wasn't linear, but wasn't partial either - replace with a line ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate(); ON_3dPoint p1 = c2_orig->PointAt(c2_orig->Domain().Min()); ON_3dPoint p2 = c2_orig->PointAt(c2_orig->Domain().Max()); ON_Curve *c2 = new ON_LineCurve(p1, p2); c2->ChangeDimension(2); int c2i = data->planar_obj->local_brep->AddTrimCurve(c2); ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2i); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; delete c2_orig; } delete ec; } else { // Partial edge - let the fun begin ON_3dPoint p1, p2; ON_BrepEdge *next_edge; bu_log("working a partial edge: %d\n", o_edge->m_edge_index); int v[2]; v[0] = o_edge->Vertex(0)->m_vertex_index; v[1] = o_edge->Vertex(1)->m_vertex_index; // figure out which trim point we can use, the min or max int pos1 = 0; if (skip_verts.find(v[0]) != skip_verts.end()) { pos1 = 1; } int j_next = j; ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate(); ON_Curve *c2_next = NULL; int walk_dir = 1; // bump the loop iterator to get passed any skipped edges to // the next partial while (!c2_next) { (walk_dir == 1) ? j_next++ : j_next--; if (j_next == old_loop->TrimCount()) { j_next = 0; } if (j_next == -1) { j_next = old_loop->TrimCount() - 1; } const ON_BrepTrim *next_trim = old_loop->Trim(j_next); next_edge = next_trim->Edge(); if (!next_edge) continue; if (skip_edges.find(next_edge->m_edge_index) == skip_edges.end()) { if (partial_edges.find(next_edge->m_edge_index) != partial_edges.end()) { bu_log("found next partial edge %d\n", next_edge->m_edge_index); evaluated.insert(next_edge->m_edge_index); c2_next = next_trim->TrimCurveOf()->Duplicate(); } else { bu_log("partial edge %d followed by non-partial %d, need to go the other way\n", o_edge->m_edge_index, next_edge->m_edge_index); j_next--; walk_dir = -1; } } else { bu_log("skipping fully ignored edge %d\n", next_edge->m_edge_index); evaluated.insert(next_edge->m_edge_index); } } int v2[2]; v2[0] = next_edge->Vertex(0)->m_vertex_index; v2[1] = next_edge->Vertex(1)->m_vertex_index; // figure out which trim point we can use, the min or max int pos2 = 0; if (skip_verts.find(v2[0]) != skip_verts.end()) { pos2 = 1; } int vmapped[2]; if (vertex_map.find(o_edge->Vertex(pos1)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(o_edge->Vertex(pos1)->Point(), o_edge->Vertex(pos1)->m_tolerance); vertex_map[o_edge->Vertex(pos1)->m_vertex_index] = newvvi.m_vertex_index; } if (vertex_map.find(next_edge->Vertex(pos2)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(next_edge->Vertex(pos2)->Point(), next_edge->Vertex(pos2)->m_tolerance); vertex_map[next_edge->Vertex(pos2)->m_vertex_index] = newvvi.m_vertex_index; } // If walk_dir is -1, need to flip things around (I think...) the verts and trim points // will be swapped compared to a forward walk if (walk_dir == -1) { vmapped[1] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index]; vmapped[0] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index]; } else { vmapped[0] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index]; vmapped[1] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index]; } // New Edge curve ON_Curve *c3 = new ON_LineCurve(o_edge->Vertex(pos1)->Point(), next_edge->Vertex(pos2)->Point()); int c3i = data->planar_obj->local_brep->AddEdgeCurve(c3); ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[vmapped[0]], data->planar_obj->local_brep->m_V[vmapped[1]], c3i, NULL ,0); // Again, flip if walk_dir is -1 if (walk_dir == -1) { p2 = c2_orig->PointAt(c2_orig->Domain().Min()); p1 = c2_next->PointAt(c2_orig->Domain().Max()); } else { p1 = c2_orig->PointAt(c2_orig->Domain().Min()); p2 = c2_next->PointAt(c2_orig->Domain().Max()); } std::cout << "p1: " << pout(p1) << "\n"; std::cout << "p2: " << pout(p2) << "\n"; ON_Curve *c2 = new ON_LineCurve(p1, p2); c2->ChangeDimension(2); int c2i = data->planar_obj->local_brep->AddTrimCurve(c2); ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(new_edge, false, new_loop, c2i); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; delete c2_orig; delete c2_next; } } } // If there is a possibility of a negative volume for the planar solid, do a test. // The only way to get a negative planar solid in this context is if that solid is // "inside" a non-planar shape (it would be "part of" the parent shape if it were // planar and it would be a separate shape altogether if it were not topologically // connected. So we take one partial edge, find its associated non-planar faces, // and collect all the partial and skipped edges from that face and any non-planar // faces associated with the other partial/skipped edges. // // TODO - We still have an unhandled possibility here - the self-intersecting // planar_obj. For example: // // * * // * * * * // * * * * * * // * * * * * * * * // * * * * * * // * * * * * * * * * * * * // if (partial_edges.size() > 0) { std::queue<int> connected_faces; std::set<int> relevant_edges; std::set<int>::iterator re_it; std::set<int> efaces; std::set<int>::iterator f_it; std::set<int> found_faces; const ON_BrepEdge *seed_edge = &(data->brep->m_E[*partial_edges.begin()]); for (int j = 0; j < seed_edge->TrimCount(); j++) { ON_BrepTrim *trim = seed_edge->Trim(j); efaces.insert(trim->Face()->m_face_index); } for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) { surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), NULL); if (stype != SURFACE_PLANE) { connected_faces.push(data->brep->m_F[*f_it].m_face_index); } } while (!connected_faces.empty()) { int face_index = connected_faces.front(); connected_faces.pop(); std::set<int> local_edges; std::set<int>::iterator le_it; found_faces.insert(face_index); const ON_BrepFace *face = &(data->brep->m_F[face_index]); const ON_BrepLoop *loop = NULL; // Find the loop in this face that is associated with this subbrep for (int i = 0; i < face->LoopCount(); i++) { int loop_ind = face->Loop(i)->m_loop_index; if (loops.find(loop_ind) != loops.end()) { loop = &(data->brep->m_L[loop_ind]); break; } } // Collect the edges that are partial or skipped for (int i = 0; i < loop->TrimCount(); i++) { const ON_BrepTrim *trim = loop->Trim(i); ON_BrepEdge *edge = trim->Edge(); if (edge) { if (partial_edges.find(edge->m_edge_index) != partial_edges.end()) { relevant_edges.insert(edge->m_edge_index); local_edges.insert(edge->m_edge_index); } if (skip_edges.find(edge->m_edge_index) != skip_edges.end()) { relevant_edges.insert(edge->m_edge_index); local_edges.insert(edge->m_edge_index); } } } // For each collected partial/skipped edge, add any faces not already // found to the queue. for (le_it = local_edges.begin(); le_it != local_edges.end(); le_it++) { const ON_BrepEdge *edge = &(data->brep->m_E[*le_it]); for (int j = 0; j < edge->TrimCount(); j++) { ON_BrepTrim *trim = edge->Trim(j); if (found_faces.find(trim->Face()->m_face_index) == found_faces.end()) { found_faces.insert(trim->Face()->m_face_index); connected_faces.push(trim->Face()->m_face_index); } } } } // Build two bounding boxes - one with the new verts in planar_obj, and the other with // the edges found above. ON_BoundingBox pbb, ebb; ON_MinMaxInit(&pbb.m_min, &pbb.m_max); ON_MinMaxInit(&ebb.m_min, &ebb.m_max); for (int i = 0; i < data->planar_obj->local_brep->m_V.Count(); i++) { const ON_BrepVertex *v = &(data->planar_obj->local_brep->m_V[i]); pbb.Set(v->Point(), true); } for (re_it = relevant_edges.begin(); re_it != relevant_edges.end(); re_it++) { const ON_BrepEdge *e = &(data->brep->m_E[*re_it]); ON_BoundingBox cbb = e->EdgeCurveOf()->BoundingBox(); ebb.Set(cbb.m_min, true); ebb.Set(cbb.m_max, true); } //std::cout << "in pbb.s rpp " << pout(pbb.m_min) << " " << pout(pbb.m_max) << "\n"; //std::cout << "in ebb.s rpp " << pout(ebb.m_min) << " " << pout(ebb.m_max) << "\n"; if (ebb.Includes(pbb)) { bu_log("negative volume\n"); data->planar_obj->negative_shape = -1; } else { bu_log("positive volume\n"); data->planar_obj->negative_shape = 1; } data->planar_obj->params->bool_op = (data->planar_obj->negative_shape == -1) ? '-' : 'u'; } // Need to preserve the vertex map for this, since we're not done building up the brep map_to_array(&(data->planar_obj->planar_obj_vert_map), &(data->planar_obj->planar_obj_vert_cnt), &vertex_map); data->planar_obj->local_brep->SetTrimTypeFlags(true); }
int negative_polygon(struct subbrep_object_data *data) { int io_state = 0; int all_faces_cnt = 0; std::vector<int> all_faces; int *final_faces = NULL; std::set<int> fol_faces; /* This will get reused for all faces, so make it once */ point_t *all_verts = (point_t *)bu_calloc(data->brep->m_V.Count(), sizeof(point_t), "bot verts"); for (int vi = 0; vi < data->brep->m_V.Count(); vi++) { VMOVE(all_verts[vi], data->brep->m_V[vi].Point()); } array_to_set(&fol_faces, data->fol, data->fol_cnt); // Check each face to see if it is fil or fol - the first fol face, stash its // normal - don't even need the triangle face normal, we can just use the face's normal and // a point from the center of one of the fol triangles on that particular face. ON_3dPoint origin_pnt; ON_3dVector triangle_normal; int have_hit_pnt = 0; /* Get triangles from the faces */ ON_BoundingBox vert_bbox; ON_MinMaxInit(&vert_bbox.m_min, &vert_bbox.m_max); for (int i = 0; i < data->loops_cnt; i++) { const ON_BrepLoop *b_loop = &(data->brep->m_L[data->loops[i]]); int *ffaces = NULL; int num_faces = subbrep_polygon_tri(data->brep, all_verts, (int *)&(b_loop->m_loop_index), 1, &ffaces); if (!num_faces) { bu_log("Error - triangulation failed for loop %d!\n", b_loop->m_loop_index); return 0; } if (!have_hit_pnt) { const ON_BrepFace *b_face = b_loop->Face(); if (fol_faces.find(b_face->m_face_index) != fol_faces.end()) { ON_3dPoint p1 = data->brep->m_V[ffaces[0]].Point(); ON_3dPoint p2 = data->brep->m_V[ffaces[1]].Point(); ON_3dPoint p3 = data->brep->m_V[ffaces[2]].Point(); ON_Plane fp; ON_Surface *ts = b_face->SurfaceOf()->Duplicate(); (void)ts->IsPlanar(&fp, BREP_PLANAR_TOL); delete ts; triangle_normal = fp.Normal(); if (b_face->m_bRev) triangle_normal = triangle_normal * -1; origin_pnt = (p1 + p2 + p3) / 3; have_hit_pnt = 1; } } for (int f_ind = 0; f_ind < num_faces*3; f_ind++) { all_faces.push_back(ffaces[f_ind]); vert_bbox.Set(data->brep->m_V[ffaces[f_ind]].Point(), true); } if (ffaces) bu_free(ffaces, "free polygon face array"); all_faces_cnt += num_faces; } /* Now we can build the final faces array */ final_faces = (int *)bu_calloc(all_faces_cnt * 3, sizeof(int), "final bot verts"); for (int i = 0; i < all_faces_cnt*3; i++) { final_faces[i] = all_faces[i]; } // Scale bounding box to make sure corners are away from the volume vert_bbox.m_min = vert_bbox.m_min * 1.1; vert_bbox.m_max = vert_bbox.m_max * 1.1; // Pick a ray direction ON_3dVector rdir; ON_3dPoint box_corners[8]; vert_bbox.GetCorners(box_corners); int have_dir = 0; int corner = 0; double dotp; while (!have_dir && corner < 8) { rdir = box_corners[corner] - origin_pnt; dotp = ON_DotProduct(triangle_normal, rdir); (NEAR_ZERO(dotp, 0.01)) ? corner++ : have_dir = 1; } if (!have_dir) { bu_log("Error: NONE of the corners worked??\n"); return 0; } point_t origin, dir; VMOVE(origin, origin_pnt); VMOVE(dir, rdir); #if 0 std::cout << "working: " << bu_vls_addr(data->key) << "\n"; bu_log("in origin.s sph %f %f %f 1\n", origin[0], origin[1], origin[2]); bu_log("in triangle_normal.s rcc %f %f %f %f %f %f 1 \n", origin_pnt.x, origin_pnt.y, origin_pnt.z, triangle_normal.x, triangle_normal.y, triangle_normal.z); bu_log("in ray.s rcc %f %f %f %f %f %f 1 \n", origin[0], origin[1], origin[2], dir[0], dir[1], dir[2]); #endif // Test the ray against the triangle set int hit_cnt = 0; point_t p1, p2, p3, isect; ON_3dPointArray hit_pnts; for (int i = 0; i < all_faces_cnt; i++) { ON_3dPoint onp1, onp2, onp3, hit_pnt; VMOVE(p1, all_verts[all_faces[i*3+0]]); VMOVE(p2, all_verts[all_faces[i*3+1]]); VMOVE(p3, all_verts[all_faces[i*3+2]]); onp1.x = p1[0]; onp1.y = p1[1]; onp1.z = p1[2]; onp2.x = p2[0]; onp2.y = p2[1]; onp2.z = p2[2]; onp3.x = p3[0]; onp3.y = p3[1]; onp3.z = p3[2]; ON_Plane fplane(onp1, onp2, onp3); int is_hit = bg_isect_tri_ray(origin, dir, p1, p2, p3, &isect); VMOVE(hit_pnt, isect); // Don't count the point on the ray origin if (hit_pnt.DistanceTo(origin_pnt) < 0.0001) is_hit = 0; if (is_hit) { // No double-counting for (int j = 0; j < hit_pnts.Count(); j++) { if (hit_pnts[j].DistanceTo(hit_pnt) < 0.001) is_hit = 0; } if (is_hit) { //bu_log("in hit_cnt%d.s sph %f %f %f 0.1\n", hit_pnts.Count()+1, isect[0], isect[1], isect[2]); hit_pnts.Append(hit_pnt); } } } hit_cnt = hit_pnts.Count(); //bu_log("hit count: %d\n", hit_cnt); //bu_log("dotp : %f\n", dotp); // Final inside/outside determination if (hit_cnt % 2) { io_state = (dotp > 0) ? -1 : 1; } else { io_state = (dotp < 0) ? -1 : 1; } //bu_log("inside out state: %d\n", io_state); bu_free(all_verts, "free top level vertex array"); bu_free(final_faces, "free face array"); return io_state; }
bool ON_BrepExtrude( ON_Brep& brep, const ON_Curve& path_curve, bool bCap ) { ON_Workspace ws; const int vcount0 = brep.m_V.Count(); const int tcount0 = brep.m_T.Count(); const int lcount0 = brep.m_L.Count(); const int ecount0 = brep.m_E.Count(); const int fcount0 = brep.m_F.Count(); const ON_3dPoint PathStart = path_curve.PointAtStart(); ON_3dPoint P = path_curve.PointAtEnd(); if ( !PathStart.IsValid() || !P.IsValid() ) return false; const ON_3dVector height = P - PathStart; if ( !height.IsValid() || height.Length() <= ON_ZERO_TOLERANCE ) return false; ON_Xform tr; tr.Translation(height); // count number of new sides int side_count = 0; int i, vi, ei, fi; bool* bSideEdge = (bool*)ws.GetIntMemory(ecount0*sizeof(bSideEdge[0])); for ( ei = 0; ei < ecount0; ei++ ) { const ON_BrepEdge& e = brep.m_E[ei]; if ( 1 == e.m_ti.Count() ) { side_count++; bSideEdge[ei] = true; } else { bSideEdge[ei] = false; } } brep.m_V.Reserve( 2*vcount0 ); i = 4*side_count + (bCap?tcount0:0); brep.m_T.Reserve( tcount0 + i ); brep.m_C2.Reserve( brep.m_C2.Count() + i ); brep.m_L.Reserve( lcount0 + side_count + (bCap?lcount0:0) ); i = side_count + (bCap?ecount0:side_count); brep.m_E.Reserve( ecount0 + i ); brep.m_C3.Reserve( brep.m_C3.Count() + i ); i = side_count + (bCap?fcount0:0); brep.m_F.Reserve( fcount0 + i ); brep.m_S.Reserve( brep.m_S.Count() + i ); bool bOK = true; // build top vertices int* topvimap = ws.GetIntMemory(vcount0); memset(topvimap,0,vcount0*sizeof(topvimap[0])); if ( bCap ) { for ( vi = 0; vi < vcount0; vi++ ) { const ON_BrepVertex& bottomv = brep.m_V[vi]; ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance); topvimap[vi] = topv.m_vertex_index; } } else { for ( ei = 0; ei < ecount0; ei++ ) { if ( bSideEdge[ei] ) { const ON_BrepEdge& bottome = brep.m_E[ei]; int bottomvi0 = bottome.m_vi[0]; if ( bottomvi0 < 0 || bottomvi0 >= vcount0 ) { bOK = false; break; } int bottomvi1 = bottome.m_vi[1]; if ( bottomvi1 < 0 || bottomvi1 >= vcount0 ) { bOK = false; break; } if ( !topvimap[bottomvi0] ) { const ON_BrepVertex& bottomv = brep.m_V[bottomvi0]; ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance); topvimap[bottomvi0] = topv.m_vertex_index; } if ( !topvimap[bottomvi1] ) { const ON_BrepVertex& bottomv = brep.m_V[bottomvi1]; ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance); topvimap[bottomvi1] = topv.m_vertex_index; } } } } // build top edges int* topeimap = ws.GetIntMemory(ecount0); memset(topeimap,0,ecount0*sizeof(topeimap[0])); if ( bOK ) for ( ei = 0; ei < ecount0; ei++ ) { if ( bCap || bSideEdge[ei] ) { const ON_BrepEdge& bottome = brep.m_E[ei]; ON_BrepVertex& topv0 = brep.m_V[topvimap[bottome.m_vi[0]]]; ON_BrepVertex& topv1 = brep.m_V[topvimap[bottome.m_vi[1]]]; ON_Curve* c3 = bottome.DuplicateCurve(); if ( !c3 ) { bOK = false; break; } c3->Transform(tr); int c3i = brep.AddEdgeCurve(c3); ON_BrepEdge& tope = brep.NewEdge(topv0,topv1,c3i,0,bottome.m_tolerance); topeimap[ei] = tope.m_edge_index; } } // build side edges int* sideveimap = ws.GetIntMemory(vcount0); memset(sideveimap,0,vcount0*sizeof(sideveimap[0])); if ( bOK ) for ( vi = 0; vi < vcount0; vi++ ) { ON_BrepVertex& bottomv = brep.m_V[vi]; for ( int vei = 0; vei < bottomv.m_ei.Count(); vei++ ) { if ( bSideEdge[bottomv.m_ei[vei]] && topvimap[vi] ) { ON_BrepVertex& topv = brep.m_V[topvimap[vi]]; ON_Curve* c3 = path_curve.DuplicateCurve(); if ( !c3 ) { bOK = false; } else { ON_3dVector D = bottomv.point - PathStart; c3->Translate(D); int c3i = brep.AddEdgeCurve(c3); const ON_BrepEdge& e = brep.NewEdge(bottomv,topv,c3i,0,0.0); sideveimap[vi] = e.m_edge_index; } break; } } } if ( bOK && bCap ) { // build top faces for (fi = 0; fi < fcount0; fi++ ) { const ON_BrepFace& bottomf = brep.m_F[fi]; ON_Surface* srf = bottomf.DuplicateSurface(); if ( !srf ) { bOK = false; break; } srf->Transform(tr); int si = brep.AddSurface(srf); ON_BrepFace& topf = brep.NewFace(si); topf.m_bRev = !bottomf.m_bRev; const int loop_count = bottomf.m_li.Count(); topf.m_li.Reserve(loop_count); for ( int fli = 0; fli < loop_count; fli++ ) { const ON_BrepLoop& bottoml = brep.m_L[bottomf.m_li[fli]]; ON_BrepLoop& topl = brep.NewLoop(bottoml.m_type,topf); const int loop_trim_count = bottoml.m_ti.Count(); topl.m_ti.Reserve(loop_trim_count); for ( int lti = 0; lti < loop_trim_count; lti++ ) { const ON_BrepTrim& bottomt = brep.m_T[bottoml.m_ti[lti]]; ON_NurbsCurve* c2 = ON_NurbsCurve::New(); if ( !bottomt.GetNurbForm(*c2) ) { delete c2; bOK = false; break; } int c2i = brep.AddTrimCurve(c2); ON_BrepTrim* topt = 0; if ( bottomt.m_ei >= 0 ) { ON_BrepEdge& tope = brep.m_E[topeimap[bottomt.m_ei]]; topt = &brep.NewTrim(tope,bottomt.m_bRev3d,topl,c2i); } else { // singular trim ON_BrepVertex& topv = brep.m_V[topvimap[bottomt.m_vi[0]]]; topt = &brep.NewSingularTrim(topv,topl,bottomt.m_iso,c2i); } topt->m_tolerance[0] = bottomt.m_tolerance[0]; topt->m_tolerance[1] = bottomt.m_tolerance[1]; topt->m_pbox = bottomt.m_pbox; topt->m_type = bottomt.m_type; topt->m_iso = bottomt.m_iso; } topl.m_pbox = bottoml.m_pbox; } } } // build sides int bRev3d[4] = {0,0,1,1}; int vid[4], eid[4]; if( bOK ) for ( ei = 0; ei < ecount0; ei++ ) { if ( bSideEdge[ei] && topeimap[ei] ) { ON_BrepEdge& bottome = brep.m_E[ei]; ON_BrepEdge& tope = brep.m_E[topeimap[ei]]; vid[0] = bottome.m_vi[0]; vid[1] = bottome.m_vi[1]; vid[2] = topvimap[vid[1]]; vid[3] = topvimap[vid[0]]; if ( sideveimap[vid[0]] && sideveimap[vid[1]] ) { ON_BrepEdge& leftedge = brep.m_E[sideveimap[vid[0]]]; ON_BrepEdge& rightedge = brep.m_E[sideveimap[vid[1]]]; ON_Curve* cx = bottome.DuplicateCurve(); if ( !cx ) { bOK = false; break; } ON_Curve* cy = leftedge.DuplicateCurve(); if ( !cy ) { delete cx; bOK = false; break; } ON_SumSurface* srf = new ON_SumSurface(); srf->m_curve[0] = cx; srf->m_curve[1] = cy; srf->m_basepoint = srf->m_curve[1]->PointAtStart(); srf->m_basepoint.x = -srf->m_basepoint.x; srf->m_basepoint.y = -srf->m_basepoint.y; srf->m_basepoint.z = -srf->m_basepoint.z; eid[0] = bottome.m_edge_index; eid[1] = rightedge.m_edge_index; eid[2] = tope.m_edge_index; eid[3] = leftedge.m_edge_index; ON_BrepFace* face = brep.NewFace(srf,vid,eid,bRev3d); if ( !face ) { bOK = false; break; } else if ( bottome.m_ti.Count() == 2 ) { const ON_BrepTrim& trim0 = brep.m_T[bottome.m_ti[0]]; const ON_BrepTrim& trim1 = brep.m_T[bottome.m_ti[1]]; const ON_BrepLoop& loop0 = brep.m_L[trim0.m_li]; const ON_BrepLoop& loop1 = brep.m_L[trim1.m_li]; bool bBottomFaceRev = brep.m_F[(loop0.m_fi != face->m_face_index) ? loop0.m_fi : loop1.m_fi].m_bRev; bool bSideFaceRev = ( trim0.m_bRev3d != trim1.m_bRev3d ) ? bBottomFaceRev : !bBottomFaceRev; face->m_bRev = bSideFaceRev; } } } } if ( !bOK ) { for ( vi = brep.m_V.Count(); vi >= vcount0; vi-- ) { brep.DeleteVertex(brep.m_V[vi]); } } return bOK; }