/*************************************************************************** * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2008 * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include #include #include #include #include #include #include #include #include #include "TopoShape.h" #include "TopoShapeSolidPy.h" #include "TopoShapeWirePy.h" #include "TopoShapeFacePy.h" #include "TopoShapeFacePy.cpp" #include "BezierSurfacePy.h" #include "BSplineSurfacePy.h" #include "PlanePy.h" #include "CylinderPy.h" #include "ConePy.h" #include "SpherePy.h" #include "OffsetSurfacePy.h" #include "SurfaceOfRevolutionPy.h" #include "SurfaceOfExtrusionPy.h" #include "ToroidPy.h" using namespace Part; // returns a string which represent the object e.g. when printed in python std::string TopoShapeFacePy::representation(void) const { std::stringstream str; str << ""; return str.str(); } PyObject *TopoShapeFacePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper { // create a new instance of TopoShapeFacePy and the Twin object return new TopoShapeFacePy(new TopoShape); } // constructor method int TopoShapeFacePy::PyInit(PyObject* args, PyObject* /*kwd*/) { PyObject *pW; if (PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pW)) { try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->_Shape; if (sh.IsNull()) { PyErr_SetString(PyExc_Exception, "cannot create face out of empty wire"); return -1; } if (sh.ShapeType() == TopAbs_WIRE) { BRepBuilderAPI_MakeFace mkFace(TopoDS::Wire(sh)); getTopoShapePtr()->_Shape = mkFace.Face(); return 0; } else if (sh.ShapeType() == TopAbs_FACE) { getTopoShapePtr()->_Shape = sh; return 0; } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return -1; } } PyErr_Clear(); PyObject *surf, *bound=0; if (PyArg_ParseTuple(args, "O!|O!", &(GeometryPy::Type), &surf, &(PyList_Type), &bound)) { try { Handle_Geom_Surface S = Handle_Geom_Surface::DownCast (static_cast(surf)->getGeometryPtr()->handle()); if (S.IsNull()) { PyErr_SetString(PyExc_TypeError, "geometry is not a valid surface"); return -1; } BRepBuilderAPI_MakeFace mkFace(S #if OCC_VERSION_HEX >= 0x060502 , Precision::Confusion() #endif ); if (bound) { Py::List list(bound); for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { PyObject* item = (*it).ptr(); if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { const TopoDS_Shape& sh = static_cast(item)->getTopoShapePtr()->_Shape; if (sh.ShapeType() == TopAbs_WIRE) mkFace.Add(TopoDS::Wire(sh)); else { PyErr_SetString(PyExc_TypeError, "shape is not a wire"); return -1; } } else { PyErr_SetString(PyExc_TypeError, "item is not a shape"); return -1; } } } getTopoShapePtr()->_Shape = mkFace.Face(); return 0; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return -1; } } PyErr_Clear(); if (PyArg_ParseTuple(args, "O!", &(PyList_Type), &bound)) { try { std::vector wires; Py::List list(bound); for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { PyObject* item = (*it).ptr(); if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { const TopoDS_Shape& sh = static_cast(item)->getTopoShapePtr()->_Shape; if (sh.ShapeType() == TopAbs_WIRE) wires.push_back(TopoDS::Wire(sh)); else Standard_Failure::Raise("shape is not a wire"); } else Standard_Failure::Raise("shape is not a wire"); } if (!wires.empty()) { BRepBuilderAPI_MakeFace mkFace(wires.front()); for (std::vector::iterator it = wires.begin()+1; it != wires.end(); ++it) mkFace.Add(*it); getTopoShapePtr()->_Shape = mkFace.Face(); return 0; } else { Standard_Failure::Raise("no wires in list"); } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return -1; } } PyErr_SetString(PyExc_Exception, "wire or list of wires expected"); return -1; } PyObject* TopoShapeFacePy::makeOffset(PyObject *args) { float dist; if (!PyArg_ParseTuple(args, "f",&dist)) return 0; const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepOffsetAPI_MakeOffset mkOffset(f); mkOffset.Perform(dist); return new TopoShapePy(new TopoShape(mkOffset.Shape())); } PyObject* TopoShapeFacePy::valueAt(PyObject *args) { double u,v; if (!PyArg_ParseTuple(args, "dd",&u,&v)) return 0; const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); BRepLProp_SLProps prop(adapt,u,v,0,Precision::Confusion()); const gp_Pnt& V = prop.Value(); return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z())); } PyObject* TopoShapeFacePy::normalAt(PyObject *args) { double u,v; if (!PyArg_ParseTuple(args, "dd",&u,&v)) return 0; const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); BRepLProp_SLProps prop(adapt,u,v,1,Precision::Confusion()); if (prop.IsNormalDefined()) { gp_Pnt pnt; gp_Vec vec; // handles the orientation state of the shape BRepGProp_Face(f).Normal(u,v,pnt,vec); return new Base::VectorPy(new Base::Vector3d(vec.X(),vec.Y(),vec.Z())); } else { PyErr_SetString(PyExc_Exception, "normal not defined"); return 0; } } PyObject* TopoShapeFacePy::tangentAt(PyObject *args) { double u,v; if (!PyArg_ParseTuple(args, "dd",&u,&v)) return 0; gp_Dir dir; Py::Tuple tuple(2); const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); BRepLProp_SLProps prop(adapt,u,v,1,Precision::Confusion()); if (prop.IsTangentUDefined()) { prop.TangentU(dir); tuple.setItem(0, Py::Vector(Base::Vector3d(dir.X(),dir.Y(),dir.Z()))); } else { PyErr_SetString(PyExc_Exception, "tangent in u not defined"); return 0; } if (prop.IsTangentVDefined()) { prop.TangentV(dir); tuple.setItem(1, Py::Vector(Base::Vector3d(dir.X(),dir.Y(),dir.Z()))); } else { PyErr_SetString(PyExc_Exception, "tangent in v not defined"); return 0; } return Py::new_reference_to(tuple); } PyObject* TopoShapeFacePy::curvatureAt(PyObject *args) { double u,v; if (!PyArg_ParseTuple(args, "dd",&u,&v)) return 0; Py::Tuple tuple(2); const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion()); if (prop.IsCurvatureDefined()) { tuple.setItem(0, Py::Float(prop.MinCurvature())); tuple.setItem(1, Py::Float(prop.MaxCurvature())); } else { PyErr_SetString(PyExc_Exception, "curvature not defined"); return 0; } return Py::new_reference_to(tuple); } PyObject* TopoShapeFacePy::derivative1At(PyObject *args) { double u,v; if (!PyArg_ParseTuple(args, "dd",&u,&v)) return 0; Py::Tuple tuple(2); const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); try { BRepLProp_SLProps prop(adapt,u,v,1,Precision::Confusion()); const gp_Vec& vecU = prop.D1U(); tuple.setItem(0, Py::Vector(Base::Vector3d(vecU.X(),vecU.Y(),vecU.Z()))); const gp_Vec& vecV = prop.D1V(); tuple.setItem(1, Py::Vector(Base::Vector3d(vecV.X(),vecV.Y(),vecV.Z()))); return Py::new_reference_to(tuple); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return 0; } } PyObject* TopoShapeFacePy::derivative2At(PyObject *args) { double u,v; if (!PyArg_ParseTuple(args, "dd",&u,&v)) return 0; Py::Tuple tuple(2); const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); try { BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion()); const gp_Vec& vecU = prop.D2U(); tuple.setItem(0, Py::Vector(Base::Vector3d(vecU.X(),vecU.Y(),vecU.Z()))); const gp_Vec& vecV = prop.D2V(); tuple.setItem(1, Py::Vector(Base::Vector3d(vecV.X(),vecV.Y(),vecV.Z()))); return Py::new_reference_to(tuple); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return 0; } } PyObject* TopoShapeFacePy::isPartOfDomain(PyObject *args) { double u,v; if (!PyArg_ParseTuple(args, "dd",&u,&v)) return 0; const TopoDS_Face& face = TopoDS::Face(getTopoShapePtr()->_Shape); double tol; //double u1, u2, v1, v2, dialen; tol = Precision::Confusion(); try { //BRepTools::UVBounds(face, u1, u2, v1, v2); //dialen = (u2-u1)*(u2-u1) + (v2-v1)*(v2-v1); //dialen = sqrt(dialen)/400.0; //tol = std::max(dialen, tol); BRepTopAdaptor_FClass2d CL(face,tol); TopAbs_State state = CL.Perform(gp_Pnt2d(u,v)); if (state == TopAbs_ON || state == TopAbs_IN) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return 0; } } PyObject* TopoShapeFacePy::makeHalfSpace(PyObject *args) { PyObject* pPnt; if (!PyArg_ParseTuple(args, "O!",&(Base::VectorPy::Type),&pPnt)) return 0; try { Base::Vector3d pt = Py::Vector(pPnt,false).toVector(); BRepPrimAPI_MakeHalfSpace mkHS(TopoDS::Face(this->getTopoShapePtr()->_Shape), gp_Pnt(pt.x,pt.y,pt.z)); return new TopoShapeSolidPy(new TopoShape(mkHS.Solid())); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return 0; } } Py::Object TopoShapeFacePy::getSurface() const { const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); switch(adapt.GetType()) { case GeomAbs_Plane: { GeomPlane* plane = new GeomPlane(); Handle_Geom_Plane this_surf = Handle_Geom_Plane::DownCast (plane->handle()); this_surf->SetPln(adapt.Plane()); return Py::Object(new PlanePy(plane),true); } case GeomAbs_Cylinder: { GeomCylinder* cylinder = new GeomCylinder(); Handle_Geom_CylindricalSurface this_surf = Handle_Geom_CylindricalSurface::DownCast (cylinder->handle()); this_surf->SetCylinder(adapt.Cylinder()); return Py::Object(new CylinderPy(cylinder),true); } case GeomAbs_Cone: { GeomCone* cone = new GeomCone(); Handle_Geom_ConicalSurface this_surf = Handle_Geom_ConicalSurface::DownCast (cone->handle()); this_surf->SetCone(adapt.Cone()); return Py::Object(new ConePy(cone),true); } case GeomAbs_Sphere: { GeomSphere* sphere = new GeomSphere(); Handle_Geom_SphericalSurface this_surf = Handle_Geom_SphericalSurface::DownCast (sphere->handle()); this_surf->SetSphere(adapt.Sphere()); return Py::Object(new SpherePy(sphere),true); } case GeomAbs_Torus: { GeomToroid* toroid = new GeomToroid(); Handle_Geom_ToroidalSurface this_surf = Handle_Geom_ToroidalSurface::DownCast (toroid->handle()); this_surf->SetTorus(adapt.Torus()); return Py::Object(new ToroidPy(toroid),true); } case GeomAbs_BezierSurface: { GeomBezierSurface* surf = new GeomBezierSurface(adapt.Bezier()); return Py::Object(new BezierSurfacePy(surf),true); } case GeomAbs_BSplineSurface: { GeomBSplineSurface* surf = new GeomBSplineSurface(adapt.BSpline()); return Py::Object(new BSplineSurfacePy(surf),true); } case GeomAbs_SurfaceOfRevolution: { Handle_Geom_Surface s = BRep_Tool::Surface(f); Handle_Geom_SurfaceOfRevolution rev = Handle_Geom_SurfaceOfRevolution::DownCast(s); if (!rev.IsNull()) { GeomSurfaceOfRevolution* surf = new GeomSurfaceOfRevolution(rev); return Py::Object(new SurfaceOfRevolutionPy(surf),true); } } case GeomAbs_SurfaceOfExtrusion: { Handle_Geom_Surface s = BRep_Tool::Surface(f); Handle_Geom_SurfaceOfLinearExtrusion ext = Handle_Geom_SurfaceOfLinearExtrusion::DownCast(s); if (!ext.IsNull()) { GeomSurfaceOfExtrusion* surf = new GeomSurfaceOfExtrusion(ext); return Py::Object(new SurfaceOfExtrusionPy(surf),true); } } case GeomAbs_OffsetSurface: { Handle_Geom_Surface s = BRep_Tool::Surface(f); Handle_Geom_OffsetSurface off = Handle_Geom_OffsetSurface::DownCast(s); if (!off.IsNull()) { GeomOffsetSurface* surf = new GeomOffsetSurface(off); return Py::Object(new OffsetSurfacePy(surf),true); } } case GeomAbs_OtherSurface: break; } throw Py::TypeError("undefined surface type"); } PyObject* TopoShapeFacePy::setTolerance(PyObject *args) { double tol; if (!PyArg_ParseTuple(args, "d", &tol)) return 0; BRep_Builder aBuilder; const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); aBuilder.UpdateFace(f, tol); Py_Return; } Py::Float TopoShapeFacePy::getTolerance(void) const { const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); return Py::Float(BRep_Tool::Tolerance(f)); } void TopoShapeFacePy::setTolerance(Py::Float tol) { BRep_Builder aBuilder; const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); aBuilder.UpdateFace(f, (double)tol); } Py::Tuple TopoShapeFacePy::getParameterRange(void) const { const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->_Shape); BRepAdaptor_Surface adapt(f); double u1 = adapt.FirstUParameter(); double u2 = adapt.LastUParameter(); double v1 = adapt.FirstVParameter(); double v2 = adapt.LastVParameter(); Py::Tuple t(4); t.setItem(0, Py::Float(u1)); t.setItem(1, Py::Float(u2)); t.setItem(2, Py::Float(v1)); t.setItem(3, Py::Float(v2)); return t; } Py::Object TopoShapeFacePy::getWire(void) const { const TopoDS_Shape& clSh = getTopoShapePtr()->_Shape; if (clSh.IsNull()) throw Py::Exception("Null shape"); if (clSh.ShapeType() == TopAbs_FACE) { TopoDS_Face clFace = (TopoDS_Face&)clSh; TopoDS_Wire clWire = ShapeAnalysis::OuterWire(clFace); return Py::Object(new TopoShapeWirePy(new TopoShape(clWire)),true); } else throw Py::Exception("Internal error, TopoDS_Shape is not a face!"); return Py::Object(); } Py::Object TopoShapeFacePy::getCenterOfMass(void) const { GProp_GProps props; BRepGProp::SurfaceProperties(getTopoShapePtr()->_Shape, props); gp_Pnt c = props.CentreOfMass(); return Py::Vector(Base::Vector3d(c.X(),c.Y(),c.Z())); } PyObject *TopoShapeFacePy::getCustomAttributes(const char* attr) const { return 0; } int TopoShapeFacePy::setCustomAttributes(const char* attr, PyObject *obj) { return 0; }