PyObject* BSplineCurvePy::getPolesAndWeights(PyObject * args) { if (!PyArg_ParseTuple(args, "")) return 0; try { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); TColgp_Array1OfPnt p(1,curve->NbPoles()); curve->Poles(p); TColStd_Array1OfReal w(1,curve->NbPoles()); curve->Weights(w); Py::List poles; for (Standard_Integer i=p.Lower(); i<=p.Upper(); i++) { gp_Pnt pnt = p(i); double weight = w(i); Py::Tuple t(4); t.setItem(0, Py::Float(pnt.X())); t.setItem(1, Py::Float(pnt.Y())); t.setItem(2, Py::Float(pnt.Z())); t.setItem(3, Py::Float(weight)); poles.append(t); } return Py::new_reference_to(poles); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
//! 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->NbPoles() == 2) { result = true; } return result; }
PyObject* BSplineCurvePy::getWeight(PyObject * args) { int index; if (!PyArg_ParseTuple(args, "i", &index)) return 0; try { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); Standard_OutOfRange_Raise_if (index < 1 || index > curve->NbPoles() , "Weight index out of range"); double weight = curve->Weight(index); return Py_BuildValue("d", weight); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
PyObject* BSplineCurvePy::getWeights(PyObject * args) { if (!PyArg_ParseTuple(args, "")) return 0; try { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); TColStd_Array1OfReal w(1,curve->NbPoles()); curve->Weights(w); Py::List weights; for (Standard_Integer i=w.Lower(); i<=w.Upper(); i++) { weights.append(Py::Float(w(i))); } return Py::new_reference_to(weights); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
PyObject* BSplineCurvePy::getPole(PyObject * args) { int index; if (!PyArg_ParseTuple(args, "i", &index)) return 0; try { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); Standard_OutOfRange_Raise_if (index < 1 || index > curve->NbPoles(), "Pole index out of range"); gp_Pnt pnt = curve->Pole(index); Base::VectorPy* vec = new Base::VectorPy(Base::Vector3d( pnt.X(), pnt.Y(), pnt.Z())); return vec; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
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; }
PyObject* BSplineCurvePy::getPoles(PyObject * args) { if (!PyArg_ParseTuple(args, "")) return 0; try { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); TColgp_Array1OfPnt p(1,curve->NbPoles()); curve->Poles(p); Py::List poles; for (Standard_Integer i=p.Lower(); i<=p.Upper(); i++) { gp_Pnt pnt = p(i); Base::VectorPy* vec = new Base::VectorPy(Base::Vector3d( pnt.X(), pnt.Y(), pnt.Z())); poles.append(Py::Object(vec)); } return Py::new_reference_to(poles); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
Py::Int BSplineCurvePy::getNbPoles(void) const { Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast (getGeometryPtr()->handle()); return Py::Int(curve->NbPoles()); }
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); } } }
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; }