//! Can this BSpline be represented by a straight line? bool BSpline::isLine() { bool result = false; BRepAdaptor_Curve c(occEdge); Handle_Geom_BSplineCurve spline = c.BSpline(); if (spline->Degree() == 1) { result = true; } return result; }
Py::List BSplineCurvePy::getKnotSequence(void) const { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); Standard_Integer m = 0; if (curve->IsPeriodic()) { // knots=poles+2*degree-mult(1)+2 m = curve->NbPoles() + 2*curve->Degree() - curve->Multiplicity(1) + 2; } else { // knots=poles+degree+1 for (int i=1; i<= curve->NbKnots(); i++) m += curve->Multiplicity(i); } TColStd_Array1OfReal k(1,m); curve->KnotSequence(k); Py::List list; for (Standard_Integer i=k.Lower(); i<=k.Upper(); i++) { list.append(Py::Float(k(i))); } return list; }
Py::Int BSplineCurvePy::getDegree(void) const { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); return Py::Int(curve->Degree()); }
BSpline::BSpline(const TopoDS_Edge &e) { geomType = BSPLINE; BRepAdaptor_Curve c(e); occEdge = e; Handle_Geom_BSplineCurve spline = c.BSpline(); bool fail = false; double f,l; gp_Pnt s,m,ePt; //if startpoint == endpoint conversion to BSpline will fail //Base::Console().Message("TRACE - Geometry::BSpline - start(%.3f,%.3f,%.3f) end(%.3f,%.3f,%.3f)\n", // s.X(),s.Y(),s.Z(),ePt.X(),ePt.Y(),ePt.Z()); if (spline->Degree() > 3) { //if spline is too complex, approximate it Standard_Real tol3D = 0.001; //1/1000 of a mm? screen can't resolve this Standard_Integer maxDegree = 3, maxSegment = 10; Handle_BRepAdaptor_HCurve hCurve = new BRepAdaptor_HCurve(c); // approximate the curve using a tolerance //Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C2, maxSegment, maxDegree); //gives degree == 5 ==> too many poles ==> buffer overrun Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C0, maxSegment, maxDegree); if (approx.IsDone() && approx.HasResult()) { spline = approx.Curve(); } else { if (approx.HasResult()) { //result, but not within tolerance spline = approx.Curve(); Base::Console().Log("Geometry::BSpline - result not within tolerance\n"); } else { fail = true; f = c.FirstParameter(); l = c.LastParameter(); s = c.Value(f); m = c.Value((l+f)/2.0); ePt = c.Value(l); Base::Console().Log("Error - Geometry::BSpline - no result- from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n", s.X(),s.Y(),ePt.X(),ePt.Y(),spline->NbPoles()); throw Base::Exception("Geometry::BSpline - could not approximate curve"); } } } GeomConvert_BSplineCurveToBezierCurve crt(spline); gp_Pnt controlPoint; if (fail) { BezierSegment tempSegment; tempSegment.poles = 3; tempSegment.degree = 2; tempSegment.pnts.push_back(Base::Vector2d(s.X(),s.Y())); tempSegment.pnts.push_back(Base::Vector2d(m.X(),m.Y())); tempSegment.pnts.push_back(Base::Vector2d(ePt.X(),ePt.Y())); segments.push_back(tempSegment); } else { for (Standard_Integer i = 1; i <= crt.NbArcs(); ++i) { BezierSegment tempSegment; Handle_Geom_BezierCurve bezier = crt.Arc(i); if (bezier->Degree() > 3) { Base::Console().Log("Geometry::BSpline - converted curve degree > 3\n"); } tempSegment.poles = bezier->NbPoles(); tempSegment.degree = bezier->Degree(); for (int pole = 1; pole <= tempSegment.poles; ++pole) { controlPoint = bezier->Pole(pole); tempSegment.pnts.push_back(Base::Vector2d(controlPoint.X(), controlPoint.Y())); } segments.push_back(tempSegment); } } }
BSpline::BSpline(const TopoDS_Edge &e) { geomType = BSPLINE; BRepAdaptor_Curve c(e); occEdge = e; Handle_Geom_BSplineCurve spline = c.BSpline(); bool fail = false; double f,l; gp_Pnt s,m,ePt; //if startpoint == endpoint conversion to BSpline will fail if (spline->Degree() > 3) { //if spline is too complex, approximate it Standard_Real tol3D = 0.001; //1/1000 of a mm? screen can't resolve this Standard_Integer maxDegree = 3, maxSegment = 10; Handle_BRepAdaptor_HCurve hCurve = new BRepAdaptor_HCurve(c); // approximate the curve using a tolerance //Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C2, maxSegment, maxDegree); //gives degree == 5 ==> too many poles ==> buffer overrun Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C0, maxSegment, maxDegree); if (approx.IsDone() && approx.HasResult()) { spline = approx.Curve(); } else { if (approx.HasResult()) { //result, but not within tolerance spline = approx.Curve(); Base::Console().Log("Geometry::BSpline - result not within tolerance\n"); } else { fail = true; f = c.FirstParameter(); l = c.LastParameter(); s = c.Value(f); m = c.Value((l+f)/2.0); ePt = c.Value(l); Base::Console().Log("Error - Geometry::BSpline - from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n", s.X(),s.Y(),ePt.X(),ePt.Y(),spline->NbPoles()); //throw Base::Exception("Geometry::BSpline - could not approximate curve"); } } } GeomConvert_BSplineCurveToBezierCurve crt(spline); BezierSegment tempSegment; gp_Pnt controlPoint; if (fail) { tempSegment.poles = 3; tempSegment.pnts[0] = Base::Vector2D(s.X(),s.Y()); tempSegment.pnts[1] = Base::Vector2D(m.X(),m.Y()); tempSegment.pnts[2] = Base::Vector2D(ePt.X(),ePt.Y()); segments.push_back(tempSegment); } else { for (Standard_Integer i = 1; i <= crt.NbArcs(); ++i) { Handle_Geom_BezierCurve bezier = crt.Arc(i); if (bezier->Degree() > 3) { throw Base::Exception("Geometry::BSpline - converted curve degree > 3"); } tempSegment.poles = bezier->NbPoles(); // Note: We really only need to keep the pnts[0] for the first Bezier segment, // assuming this only gets used as in QGIViewPart::drawPainterPath // ...it also gets used in GeometryObject::calcBoundingBox(), similar note applies for (int pole = 1; pole <= tempSegment.poles; ++pole) { controlPoint = bezier->Pole(pole); tempSegment.pnts[pole - 1] = Base::Vector2D(controlPoint.X(), controlPoint.Y()); } segments.push_back(tempSegment); } } }
void DXFOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& out) //Not even close yet- DF { try { std::stringstream str; Handle_Geom_BSplineCurve spline = c.BSpline(); if (spline->Degree() > 3) { Standard_Real tol3D = 0.001; Standard_Integer maxDegree = 3, maxSegment = 10; Handle_BRepAdaptor_HCurve hCurve = new BRepAdaptor_HCurve(c); // approximate the curve using a tolerance Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C2,maxSegment,maxDegree); if (approx.IsDone() && approx.HasResult()) { // have the result spline = approx.Curve(); } } GeomConvert_BSplineCurveToBezierCurve crt(spline); //GeomConvert_BSplineCurveKnotSplitting crt(spline,0); Standard_Integer arcs = crt.NbArcs(); //Standard_Integer arcs = crt.NbSplits()-1; str << 0 << endl << "SECTION" << endl << 2 << endl << "ENTITIES" << endl << 0 << endl << "SPLINE" << endl; //<< 8 << endl //<< 0 << endl //<< 66 << endl //<< 1 << endl //<< 0 << endl; for (Standard_Integer i=1; i<=arcs; i++) { Handle_Geom_BezierCurve bezier = crt.Arc(i); Standard_Integer poles = bezier->NbPoles(); //Standard_Integer poles = bspline->NbPoles(); //gp_Pnt p1 = bspline->Pole(1); if (bezier->Degree() == 3) { if (poles != 4) Standard_Failure::Raise("do it the generic way"); gp_Pnt p1 = bezier->Pole(1); gp_Pnt p2 = bezier->Pole(2); gp_Pnt p3 = bezier->Pole(3); gp_Pnt p4 = bezier->Pole(4); if (i == 1) { str << 10 << endl << p1.X() << endl << 20 << endl << p1.Y() << endl << 30 << endl << 0 << endl << 10 << endl << p2.X() << endl << 20 << endl << p2.Y() << endl << 30 << endl << 0 << endl << 10 << endl << p3.X() << endl << 20 << endl << p3.Y() << endl << 30 << endl << 0 << endl << 10 << endl << p4.X() << endl << 20 << endl << p4.Y() << endl << 30 << endl << 0 << endl << 12 << endl << p1.X() << endl << 22 << endl << p1.Y() << endl << 32 << endl << 0 << endl << 13 << endl << p4.X() << endl << 23 << endl << p4.Y() << endl << 33 << endl << 0 << endl; } else { str << 10 << endl << p3.X() << endl << 20 << endl << p3.Y() << endl << 30 << endl << 0 << endl << 10 << endl << p4.X() << endl << 20 << endl << p4.Y() << endl << 30 << endl << 0 << endl << 12 << endl << p3.X() << endl << 22 << endl << p3.Y() << endl << 32 << endl << 0 << endl << 13 << endl << p4.X() << endl << 23 << endl << p4.Y() << endl << 33 << endl << 0 << endl; } } else if (bezier->Degree() == 2) { if (poles != 3) Standard_Failure::Raise("do it the generic way"); gp_Pnt p1 = bezier->Pole(1); gp_Pnt p2 = bezier->Pole(2); gp_Pnt p3 = bezier->Pole(3); if (i == 1) { str << 10 << endl << p1.X() << endl << 20 << endl << p1.Y() << endl << 30 << endl << 0 << endl << 10 << endl << p2.X() << endl << 20 << endl << p2.Y() << endl << 30 << endl << 0 << endl << 10 << endl << p3.X() << endl << 20 << endl << p3.Y() << endl << 30 << endl << 0 << endl << 12 << endl << p1.X() << endl << 22 << endl << p1.Y() << endl << 32 << endl << 0 << endl << 13 << endl << p3.X() << endl << 23 << endl << p3.Y() << endl << 33 << endl << 0 << endl; } else { str << 10 << endl << p3.X() << endl << 20 << endl << p3.Y() << endl << 30 << endl << 0 << endl; } } else { Standard_Failure::Raise("do it the generic way"); } } //str << "\" />"; out << str.str(); } catch (Standard_Failure) { printGeneric(c, id, out); } }
void SVGOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& out) { try { std::stringstream str; Handle_Geom_BSplineCurve spline = c.BSpline(); if (spline->Degree() > 3) { Standard_Real tol3D = 0.001; Standard_Integer maxDegree = 3, maxSegment = 10; Handle_BRepAdaptor_HCurve hCurve = new BRepAdaptor_HCurve(c); // approximate the curve using a tolerance Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C2,maxSegment,maxDegree); if (approx.IsDone() && approx.HasResult()) { // have the result spline = approx.Curve(); } } GeomConvert_BSplineCurveToBezierCurve crt(spline); Standard_Integer arcs = crt.NbArcs(); str << "<path d=\"M"; for (Standard_Integer i=1; i<=arcs; i++) { Handle_Geom_BezierCurve bezier = crt.Arc(i); Standard_Integer poles = bezier->NbPoles(); if (bezier->Degree() == 3) { if (poles != 4) Standard_Failure::Raise("do it the generic way"); gp_Pnt p1 = bezier->Pole(1); gp_Pnt p2 = bezier->Pole(2); gp_Pnt p3 = bezier->Pole(3); gp_Pnt p4 = bezier->Pole(4); if (i == 1) { str << p1.X() << "," << p1.Y() << " C" << p2.X() << "," << p2.Y() << " " << p3.X() << "," << p3.Y() << " " << p4.X() << "," << p4.Y() << " "; } else { str << "S" << p3.X() << "," << p3.Y() << " " << p4.X() << "," << p4.Y() << " "; } } else if (bezier->Degree() == 2) { if (poles != 3) Standard_Failure::Raise("do it the generic way"); gp_Pnt p1 = bezier->Pole(1); gp_Pnt p2 = bezier->Pole(2); gp_Pnt p3 = bezier->Pole(3); if (i == 1) { str << p1.X() << "," << p1.Y() << " Q" << p2.X() << "," << p2.Y() << " " << p3.X() << "," << p3.Y() << " "; } else { str << "T" << p3.X() << "," << p3.Y() << " "; } } else { Standard_Failure::Raise("do it the generic way"); } } str << "\" />"; out << str.str(); } catch (Standard_Failure) { printGeneric(c, id, out); } }
int convert_to_ifc(const Handle_Geom_Curve& c, IfcSchema::IfcCurve*& curve, bool advanced) { if (c->DynamicType() == STANDARD_TYPE(Geom_Line)) { IfcSchema::IfcDirection* d; IfcSchema::IfcCartesianPoint* p; Handle_Geom_Line line = Handle_Geom_Line::DownCast(c); if (!convert_to_ifc(line->Position().Location(), p, advanced)) { return 0; } if (!convert_to_ifc(line->Position().Direction(), d, advanced)) { return 0; } IfcSchema::IfcVector* v = new IfcSchema::IfcVector(d, 1.); curve = new IfcSchema::IfcLine(p, v); return 1; } else if (c->DynamicType() == STANDARD_TYPE(Geom_Circle)) { IfcSchema::IfcAxis2Placement3D* ax; Handle_Geom_Circle circle = Handle_Geom_Circle::DownCast(c); convert_to_ifc(circle->Position(), ax, advanced); curve = new IfcSchema::IfcCircle(ax, circle->Radius()); return 1; } else if (c->DynamicType() == STANDARD_TYPE(Geom_Ellipse)) { IfcSchema::IfcAxis2Placement3D* ax; Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(c); convert_to_ifc(ellipse->Position(), ax, advanced); curve = new IfcSchema::IfcEllipse(ax, ellipse->MajorRadius(), ellipse->MinorRadius()); return 1; } #ifdef USE_IFC4 else if (c->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve)) { Handle_Geom_BSplineCurve bspline = Handle_Geom_BSplineCurve::DownCast(c); IfcSchema::IfcCartesianPoint::list::ptr points(new IfcSchema::IfcCartesianPoint::list); TColgp_Array1OfPnt poles(1, bspline->NbPoles()); bspline->Poles(poles); for (int i = 1; i <= bspline->NbPoles(); ++i) { IfcSchema::IfcCartesianPoint* p; if (!convert_to_ifc(poles.Value(i), p, advanced)) { return 0; } points->push(p); } IfcSchema::IfcKnotType::IfcKnotType knot_spec = opencascade_knotspec_to_ifc(bspline->KnotDistribution()); std::vector<int> mults; std::vector<double> knots; std::vector<double> weights; TColStd_Array1OfInteger bspline_mults(1, bspline->NbKnots()); TColStd_Array1OfReal bspline_knots(1, bspline->NbKnots()); TColStd_Array1OfReal bspline_weights(1, bspline->NbPoles()); bspline->Multiplicities(bspline_mults); bspline->Knots(bspline_knots); bspline->Weights(bspline_weights); opencascade_array_to_vector(bspline_mults, mults); opencascade_array_to_vector(bspline_knots, knots); opencascade_array_to_vector(bspline_weights, weights); bool rational = false; for (std::vector<double>::const_iterator it = weights.begin(); it != weights.end(); ++it) { if ((*it) != 1.) { rational = true; break; } } if (rational) { curve = new IfcSchema::IfcRationalBSplineCurveWithKnots( bspline->Degree(), points, IfcSchema::IfcBSplineCurveForm::IfcBSplineCurveForm_UNSPECIFIED, bspline->IsClosed(), false, mults, knots, knot_spec, weights ); } else { curve = new IfcSchema::IfcBSplineCurveWithKnots( bspline->Degree(), points, IfcSchema::IfcBSplineCurveForm::IfcBSplineCurveForm_UNSPECIFIED, bspline->IsClosed(), false, mults, knots, knot_spec ); } return 1; } #endif return 0; }