extern "C" void rt_ehy_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *) { struct rt_ehy_internal *eip; RT_CK_DB_INTERNAL(ip); eip = (struct rt_ehy_internal *)ip->idb_ptr; RT_EHY_CK_MAGIC(eip); // Check the parameters if (!NEAR_ZERO(VDOT(eip->ehy_Au, eip->ehy_H), RT_DOT_TOL)) { bu_log("rt_ehy_brep: Au and H are not perpendicular!\n"); return; } if (!NEAR_EQUAL(MAGNITUDE(eip->ehy_Au), 1.0, RT_LEN_TOL)) { bu_log("rt_ehy_brep: Au not a unit vector!\n"); return; } if (MAGNITUDE(eip->ehy_H) < RT_LEN_TOL || eip->ehy_c < RT_LEN_TOL || eip->ehy_r1 < RT_LEN_TOL || eip->ehy_r2 < RT_LEN_TOL) { bu_log("rt_ehy_brep: not all dimensions positive!\n"); return; } if (eip->ehy_r2 > eip->ehy_r1) { bu_log("rt_ehy_brep: semi-minor axis cannot be longer than semi-major axis!\n"); return; } point_t p1_origin; ON_3dPoint plane1_origin, plane2_origin; ON_3dVector plane_x_dir, plane_y_dir; // First, find plane in 3 space corresponding to the bottom face of the EPA. vect_t x_dir, y_dir; VMOVE(x_dir, eip->ehy_Au); VCROSS(y_dir, eip->ehy_Au, eip->ehy_H); VUNITIZE(y_dir); VMOVE(p1_origin, eip->ehy_V); plane1_origin = ON_3dPoint(p1_origin); plane_x_dir = ON_3dVector(x_dir); plane_y_dir = ON_3dVector(y_dir); const ON_Plane ehy_bottom_plane(plane1_origin, plane_x_dir, plane_y_dir); // Next, create an ellipse in the plane corresponding to the edge of the ehy. ON_Ellipse ellipse1(ehy_bottom_plane, eip->ehy_r1, eip->ehy_r2); ON_NurbsCurve* ellcurve1 = ON_NurbsCurve::New(); ellipse1.GetNurbForm((*ellcurve1)); ellcurve1->SetDomain(0.0, 1.0); // Generate the bottom cap ON_SimpleArray<ON_Curve*> boundary; boundary.Append(ON_Curve::Cast(ellcurve1)); ON_PlaneSurface* bp = new ON_PlaneSurface(); bp->m_plane = ehy_bottom_plane; bp->SetDomain(0, -100.0, 100.0); bp->SetDomain(1, -100.0, 100.0); bp->SetExtents(0, bp->Domain(0)); bp->SetExtents(1, bp->Domain(1)); (*b)->m_S.Append(bp); const int bsi = (*b)->m_S.Count() - 1; ON_BrepFace& bface = (*b)->NewFace(bsi); (*b)->NewPlanarFaceLoop(bface.m_face_index, ON_BrepLoop::outer, boundary, true); const ON_BrepLoop* bloop = (*b)->m_L.Last(); bp->SetDomain(0, bloop->m_pbox.m_min.x, bloop->m_pbox.m_max.x); bp->SetDomain(1, bloop->m_pbox.m_min.y, bloop->m_pbox.m_max.y); bp->SetExtents(0, bp->Domain(0)); bp->SetExtents(1, bp->Domain(1)); (*b)->SetTrimIsoFlags(bface); delete ellcurve1; // Now, the hard part. Need an elliptical hyperbolic NURBS surface // First step is to create a nurbs curve. double intercept_calc = (eip->ehy_c)*(eip->ehy_c)/(MAGNITUDE(eip->ehy_H) + eip->ehy_c); double intercept_dist = MAGNITUDE(eip->ehy_H) + eip->ehy_c - intercept_calc; double intercept_length = intercept_dist - MAGNITUDE(eip->ehy_H); double MX = MAGNITUDE(eip->ehy_H); double MP = MX + intercept_length; double w = (MX/MP)/(1-MX/MP); point_t ep1, ep2, ep3; VSET(ep1, -eip->ehy_r1, 0, 0); VSET(ep2, 0, 0, w*intercept_dist); VSET(ep3, eip->ehy_r1, 0, 0); ON_3dPoint onp1 = ON_3dPoint(ep1); ON_3dPoint onp2 = ON_3dPoint(ep2); ON_3dPoint onp3 = ON_3dPoint(ep3); ON_3dPointArray cpts(3); cpts.Append(onp1); cpts.Append(onp2); cpts.Append(onp3); ON_BezierCurve *bcurve = new ON_BezierCurve(cpts); bcurve->MakeRational(); bcurve->SetWeight(1, w); ON_NurbsCurve* tnurbscurve = ON_NurbsCurve::New(); bcurve->GetNurbForm(*tnurbscurve); ON_NurbsCurve* hypbnurbscurve = ON_NurbsCurve::New(); const ON_Interval subinterval = ON_Interval(0, 0.5); tnurbscurve->GetNurbForm(*hypbnurbscurve, 0.0, &subinterval); // Next, rotate that curve around the height vector. point_t revpoint1, revpoint2; VSET(revpoint1, 0, 0, 0); VSET(revpoint2, 0, 0, MX); ON_3dPoint rpnt1 = ON_3dPoint(revpoint1); ON_3dPoint rpnt2 = ON_3dPoint(revpoint2); ON_Line revaxis = ON_Line(rpnt1, rpnt2); ON_RevSurface* hyp_surf = ON_RevSurface::New(); hyp_surf->m_curve = hypbnurbscurve; hyp_surf->m_axis = revaxis; hyp_surf->m_angle = ON_Interval(0, 2*ON_PI); // Get the NURBS form of the surface ON_NurbsSurface *ehycurvedsurf = ON_NurbsSurface::New(); hyp_surf->GetNurbForm(*ehycurvedsurf, 0.0); delete hyp_surf; delete tnurbscurve; delete bcurve; // Transformations for (int i = 0; i < ehycurvedsurf->CVCount(0); i++) { for (int j = 0; j < ehycurvedsurf->CVCount(1); j++) { point_t cvpt; ON_4dPoint ctrlpt; ehycurvedsurf->GetCV(i, j, ctrlpt); // Scale the control points of the // resulting surface to map to the shorter axis. VSET(cvpt, ctrlpt.x, ctrlpt.y * eip->ehy_r2/eip->ehy_r1, ctrlpt.z); // Rotate according to the directions of Au and H vect_t Hu; mat_t R; point_t new_cvpt; VSCALE(Hu, eip->ehy_H, 1/MAGNITUDE(eip->ehy_H)); MAT_IDN(R); VMOVE(&R[0], eip->ehy_Au); VMOVE(&R[4], y_dir); VMOVE(&R[8], Hu); VEC3X3MAT(new_cvpt, cvpt, R); VMOVE(cvpt, new_cvpt); // Translate according to V vect_t scale_v; VSCALE(scale_v, eip->ehy_V, ctrlpt.w); VADD2(cvpt, cvpt, scale_v); ON_4dPoint newpt = ON_4dPoint(cvpt[0], cvpt[1], cvpt[2], ctrlpt.w); ehycurvedsurf->SetCV(i, j, newpt); } } (*b)->m_S.Append(ehycurvedsurf); int surfindex = (*b)->m_S.Count(); ON_BrepFace& face = (*b)->NewFace(surfindex - 1); (*b)->FlipFace(face); int faceindex = (*b)->m_F.Count(); (*b)->NewOuterLoop(faceindex-1); }
extern "C" void rt_hyp_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *) { struct rt_hyp_internal *eip; RT_CK_DB_INTERNAL(ip); eip = (struct rt_hyp_internal *)ip->idb_ptr; RT_HYP_CK_MAGIC(eip); point_t p1_origin, p2_origin; ON_3dPoint plane1_origin, plane2_origin; ON_3dVector plane_x_dir, plane_y_dir; // First, find planes corresponding to the top and bottom faces - initially vect_t x_dir, y_dir; VMOVE(x_dir, eip->hyp_A); VCROSS(y_dir, eip->hyp_A, eip->hyp_Hi); VREVERSE(y_dir, y_dir); VMOVE(p1_origin, eip->hyp_Vi); plane1_origin = ON_3dPoint(p1_origin); plane_x_dir = ON_3dVector(x_dir); plane_y_dir = ON_3dVector(y_dir); const ON_Plane hyp_bottom_plane(plane1_origin, plane_x_dir, plane_y_dir); VADD2(p2_origin, eip->hyp_Vi, eip->hyp_Hi); plane2_origin = ON_3dPoint(p2_origin); const ON_Plane hyp_top_plane(plane2_origin, plane_x_dir, plane_y_dir); // Next, create ellipses in the planes corresponding to the edges of the hyp ON_Ellipse b_ell(hyp_bottom_plane, MAGNITUDE(eip->hyp_A), eip->hyp_b); ON_NurbsCurve* bcurve = ON_NurbsCurve::New(); b_ell.GetNurbForm((*bcurve)); bcurve->SetDomain(0.0, 1.0); ON_Ellipse t_ell(hyp_top_plane, MAGNITUDE(eip->hyp_A), eip->hyp_b); ON_NurbsCurve* tcurve = ON_NurbsCurve::New(); t_ell.GetNurbForm((*tcurve)); tcurve->SetDomain(0.0, 1.0); // Generate the bottom cap ON_SimpleArray<ON_Curve*> boundary; boundary.Append(ON_Curve::Cast(bcurve)); ON_PlaneSurface* bp = new ON_PlaneSurface(); bp->m_plane = hyp_bottom_plane; bp->SetDomain(0, -100.0, 100.0); bp->SetDomain(1, -100.0, 100.0); bp->SetExtents(0, bp->Domain(0)); bp->SetExtents(1, bp->Domain(1)); (*b)->m_S.Append(bp); const int bsi = (*b)->m_S.Count() - 1; ON_BrepFace& bface = (*b)->NewFace(bsi); (*b)->NewPlanarFaceLoop(bface.m_face_index, ON_BrepLoop::outer, boundary, true); const ON_BrepLoop* bloop = (*b)->m_L.Last(); bp->SetDomain(0, bloop->m_pbox.m_min.x, bloop->m_pbox.m_max.x); bp->SetDomain(1, bloop->m_pbox.m_min.y, bloop->m_pbox.m_max.y); bp->SetExtents(0, bp->Domain(0)); bp->SetExtents(1, bp->Domain(1)); (*b)->FlipFace(bface); (*b)->SetTrimIsoFlags(bface); boundary.Empty(); delete bcurve; // Generate the top cap boundary.Append(ON_Curve::Cast(tcurve)); ON_PlaneSurface* tp = new ON_PlaneSurface(); tp->m_plane = hyp_top_plane; tp->SetDomain(0, -100.0, 100.0); tp->SetDomain(1, -100.0, 100.0); tp->SetExtents(0, bp->Domain(0)); tp->SetExtents(1, bp->Domain(1)); (*b)->m_S.Append(tp); int tsi = (*b)->m_S.Count() - 1; ON_BrepFace& tface = (*b)->NewFace(tsi); (*b)->NewPlanarFaceLoop(tface.m_face_index, ON_BrepLoop::outer, boundary, true); ON_BrepLoop* tloop = (*b)->m_L.Last(); tp->SetDomain(0, tloop->m_pbox.m_min.x, tloop->m_pbox.m_max.x); tp->SetDomain(1, tloop->m_pbox.m_min.y, tloop->m_pbox.m_max.y); tp->SetExtents(0, bp->Domain(0)); tp->SetExtents(1, bp->Domain(1)); (*b)->SetTrimIsoFlags(tface); delete tcurve; // Now, the hard part. Need an elliptical hyperbolic NURBS surface. // First step is to create a nurbs curve. double MX = eip->hyp_b * eip->hyp_bnr; point_t ep1, ep2, ep3; VSET(ep1, -eip->hyp_b, 0, 0.5*MAGNITUDE(eip->hyp_Hi)); VSET(ep2, -MX*eip->hyp_bnr, 0, 0); VSET(ep3, -eip->hyp_b, 0, -0.5*MAGNITUDE(eip->hyp_Hi)); ON_3dPoint onp1 = ON_3dPoint(ep1); ON_3dPoint onp2 = ON_3dPoint(ep2); ON_3dPoint onp3 = ON_3dPoint(ep3); ON_3dPointArray cpts(3); cpts.Append(onp1); cpts.Append(onp2); cpts.Append(onp3); ON_BezierCurve *bezcurve = new ON_BezierCurve(cpts); bezcurve->MakeRational(); bezcurve->SetWeight(1, bezcurve->Weight(0)/eip->hyp_bnr); ON_NurbsCurve* tnurbscurve = ON_NurbsCurve::New(); bezcurve->GetNurbForm(*tnurbscurve); delete bezcurve; ON_3dPoint revpnt1 = ON_3dPoint(0, 0, -0.5*MAGNITUDE(eip->hyp_Hi)); ON_3dPoint revpnt2 = ON_3dPoint(0, 0, 0.5*MAGNITUDE(eip->hyp_Hi)); ON_Line revaxis = ON_Line(revpnt1, revpnt2); ON_RevSurface* hyp_surf = ON_RevSurface::New(); hyp_surf->m_curve = tnurbscurve; hyp_surf->m_axis = revaxis; hyp_surf->m_angle = ON_Interval(0, 2*ON_PI); // Get the NURBS form of the surface ON_NurbsSurface *hypcurvedsurf = ON_NurbsSurface::New(); hyp_surf->GetNurbForm(*hypcurvedsurf, 0.0); delete hyp_surf; for (int i = 0; i < hypcurvedsurf->CVCount(0); i++) { for (int j = 0; j < hypcurvedsurf->CVCount(1); j++) { point_t cvpt; ON_4dPoint ctrlpt; hypcurvedsurf->GetCV(i, j, ctrlpt); // Scale and shear vect_t proj_ah; vect_t proj_ax; fastf_t factor; VPROJECT(eip->hyp_A, eip->hyp_Hi, proj_ah, proj_ax); VSET(cvpt, ctrlpt.x * MAGNITUDE(proj_ax)/eip->hyp_b, ctrlpt.y, ctrlpt.z); factor = VDOT(eip->hyp_A, eip->hyp_Hi)>0 ? 1.0 : -1.0; cvpt[2] += factor*cvpt[0]/MAGNITUDE(proj_ax)*MAGNITUDE(proj_ah) + 0.5*MAGNITUDE(eip->hyp_Hi)*ctrlpt.w; // Rotate vect_t Au, Bu, Hu; mat_t R; point_t new_cvpt; VSCALE(Bu, y_dir, 1/MAGNITUDE(y_dir)); VSCALE(Hu, eip->hyp_Hi, 1/MAGNITUDE(eip->hyp_Hi)); VCROSS(Au, Bu, Hu); VUNITIZE(Au); MAT_IDN(R); VMOVE(&R[0], Au); VMOVE(&R[4], Bu); VMOVE(&R[8], Hu); VEC3X3MAT(new_cvpt, cvpt, R); VMOVE(cvpt, new_cvpt); // Translate vect_t scale_v; VSCALE(scale_v, eip->hyp_Vi, ctrlpt.w); VADD2(cvpt, cvpt, scale_v); ON_4dPoint newpt = ON_4dPoint(cvpt[0], cvpt[1], cvpt[2], ctrlpt.w); hypcurvedsurf->SetCV(i, j, newpt); } } (*b)->m_S.Append(hypcurvedsurf); int surfindex = (*b)->m_S.Count(); ON_BrepFace& face = (*b)->NewFace(surfindex - 1); (*b)->FlipFace(face); int faceindex = (*b)->m_F.Count(); (*b)->NewOuterLoop(faceindex-1); }
void subbrep_add_planar_face(struct subbrep_object_data *data, ON_Plane *pcyl, ON_SimpleArray<const ON_BrepVertex *> *vert_loop, int neg_surf) { // We use the planar_obj's local_brep to store new faces. The planar local // brep contains the relevant linear and planar components from its parent // - our job here is to add the new surface, identify missing edges to // create, find existing edges to re-use, and call NewFace with the // results. At the end we should have just the faces needed // to define the planar volume of interest. struct subbrep_object_data *pdata = data->planar_obj; std::vector<int> edges; ON_SimpleArray<ON_Curve *> curves_2d; ON_SimpleArray<bool> reversed; std::map<int, int> vert_map; array_to_map(&vert_map, pdata->planar_obj_vert_map, pdata->planar_obj_vert_cnt); ON_3dPoint p1 = pdata->local_brep->m_V[vert_map[((*vert_loop)[0])->m_vertex_index]].Point(); ON_3dPoint p2 = pdata->local_brep->m_V[vert_map[((*vert_loop)[1])->m_vertex_index]].Point(); ON_3dPoint p3 = pdata->local_brep->m_V[vert_map[((*vert_loop)[2])->m_vertex_index]].Point(); ON_Plane loop_plane(p1, p2, p3); ON_BoundingBox loop_pbox, cbox; // get 2d trim curves ON_Xform proj_to_plane; proj_to_plane[0][0] = loop_plane.xaxis.x; proj_to_plane[0][1] = loop_plane.xaxis.y; proj_to_plane[0][2] = loop_plane.xaxis.z; proj_to_plane[0][3] = -(loop_plane.xaxis*loop_plane.origin); proj_to_plane[1][0] = loop_plane.yaxis.x; proj_to_plane[1][1] = loop_plane.yaxis.y; proj_to_plane[1][2] = loop_plane.yaxis.z; proj_to_plane[1][3] = -(loop_plane.yaxis*loop_plane.origin); proj_to_plane[2][0] = loop_plane.zaxis.x; proj_to_plane[2][1] = loop_plane.zaxis.y; proj_to_plane[2][2] = loop_plane.zaxis.z; proj_to_plane[2][3] = -(loop_plane.zaxis*loop_plane.origin); proj_to_plane[3][0] = 0.0; proj_to_plane[3][1] = 0.0; proj_to_plane[3][2] = 0.0; proj_to_plane[3][3] = 1.0; ON_PlaneSurface *s = new ON_PlaneSurface(loop_plane); const int si = pdata->local_brep->AddSurface(s); double flip = ON_DotProduct(loop_plane.Normal(), pcyl->Normal()) * neg_surf; for (int i = 0; i < vert_loop->Count(); i++) { int vind1, vind2; const ON_BrepVertex *v1, *v2; v1 = (*vert_loop)[i]; vind1 = vert_map[v1->m_vertex_index]; if (i < vert_loop->Count() - 1) { v2 = (*vert_loop)[i+1]; } else { v2 = (*vert_loop)[0]; } vind2 = vert_map[v2->m_vertex_index]; ON_BrepVertex &new_v1 = pdata->local_brep->m_V[vind1]; ON_BrepVertex &new_v2 = pdata->local_brep->m_V[vind2]; // Because we may have already created a needed edge only in the new // Brep with a previous face, we have to check all the edges in the new // structure for a vertex match. int edge_found = 0; for (int j = 0; j < pdata->local_brep->m_E.Count(); j++) { int ev1 = pdata->local_brep->m_E[j].Vertex(0)->m_vertex_index; int ev2 = pdata->local_brep->m_E[j].Vertex(1)->m_vertex_index; ON_3dPoint pv1 = pdata->local_brep->m_E[j].Vertex(0)->Point(); ON_3dPoint pv2 = pdata->local_brep->m_E[j].Vertex(1)->Point(); if ((ev1 == vind1) && (ev2 == vind2)) { edges.push_back(pdata->local_brep->m_E[j].m_edge_index); edge_found = 1; reversed.Append(false); // Get 2D curve from this edge's 3D curve const ON_Curve *c3 = pdata->local_brep->m_E[j].EdgeCurveOf(); ON_NurbsCurve *c2 = new ON_NurbsCurve(); c3->GetNurbForm(*c2); c2->Transform(proj_to_plane); c2->GetBoundingBox(cbox); c2->ChangeDimension(2); c2->MakePiecewiseBezier(2); curves_2d.Append(c2); loop_pbox.Union(cbox); break; } if ((ev2 == vind1) && (ev1 == vind2)) { edges.push_back(pdata->local_brep->m_E[j].m_edge_index); edge_found = 1; reversed.Append(true); // Get 2D curve from this edge's points ON_Curve *c3 = new ON_LineCurve(pv2, pv1); ON_NurbsCurve *c2 = new ON_NurbsCurve(); c3->GetNurbForm(*c2); c2->Transform(proj_to_plane); c2->GetBoundingBox(cbox); c2->ChangeDimension(2); c2->MakePiecewiseBezier(2); curves_2d.Append(c2); loop_pbox.Union(cbox); break; } } if (!edge_found) { int c3i = pdata->local_brep->AddEdgeCurve(new ON_LineCurve(new_v1.Point(), new_v2.Point())); // Get 2D curve from this edge's 3D curve const ON_Curve *c3 = pdata->local_brep->m_C3[c3i]; ON_NurbsCurve *c2 = new ON_NurbsCurve(); c3->GetNurbForm(*c2); c2->Transform(proj_to_plane); c2->GetBoundingBox(cbox); c2->ChangeDimension(2); c2->MakePiecewiseBezier(2); curves_2d.Append(c2); loop_pbox.Union(cbox); ON_BrepEdge &new_edge = pdata->local_brep->NewEdge(pdata->local_brep->m_V[vind1], pdata->local_brep->m_V[vind2], c3i, NULL ,0); edges.push_back(new_edge.m_edge_index); } } ON_BrepFace& face = pdata->local_brep->NewFace( si ); ON_BrepLoop& loop = pdata->local_brep->NewLoop(ON_BrepLoop::outer, face); loop.m_pbox = loop_pbox; for (int i = 0; i < vert_loop->Count(); i++) { ON_NurbsCurve *c2 = (ON_NurbsCurve *)curves_2d[i]; int c2i = pdata->local_brep->AddTrimCurve(c2); ON_BrepEdge &edge = pdata->local_brep->m_E[edges.at(i)]; ON_BrepTrim &trim = pdata->local_brep->NewTrim(edge, reversed[i], loop, c2i); trim.m_type = ON_BrepTrim::mated; trim.m_tolerance[0] = 0.0; trim.m_tolerance[1] = 0.0; } // set face domain s->SetDomain(0, loop.m_pbox.m_min.x, loop.m_pbox.m_max.x ); s->SetDomain(1, loop.m_pbox.m_min.y, loop.m_pbox.m_max.y ); s->SetExtents(0,s->Domain(0)); s->SetExtents(1,s->Domain(1)); // need to update trim m_iso flags because we changed surface shape if (flip < 0) pdata->local_brep->FlipFace(face); pdata->local_brep->SetTrimIsoFlags(face); pdata->local_brep->SetTrimTypeFlags(true); }