PropertyTopoShape.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) Jürgen Riegel          (juergen.riegel@web.de) 2002     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <sstream>
00028 # include <BRepAdaptor_Curve.hxx>
00029 # include <BRepAdaptor_Surface.hxx>
00030 # include <BRepBndLib.hxx>
00031 # include <BRepBuilderAPI_GTransform.hxx>
00032 # include <Bnd_Box.hxx>
00033 # include <BRepTools.hxx>
00034 # include <BRepTools_ShapeSet.hxx>
00035 # include <BRepBuilderAPI_Copy.hxx>
00036 # include <TopTools_HSequenceOfShape.hxx>
00037 # include <TopTools_MapOfShape.hxx>
00038 # include <TopoDS.hxx>
00039 # include <TopoDS_Iterator.hxx>
00040 # include <TopExp.hxx>
00041 # include <Standard_Failure.hxx>
00042 # include <gp_GTrsf.hxx>
00043 # include <gp_Trsf.hxx>
00044 #endif
00045 
00046 
00047 #include <strstream>
00048 #include <Base/Console.h>
00049 #include <Base/Writer.h>
00050 #include <Base/Reader.h>
00051 #include <Base/Exception.h>
00052 #include <Base/FileInfo.h>
00053 #include <Base/Stream.h>
00054 #include <App/DocumentObject.h>
00055 
00056 #include "PropertyTopoShape.h"
00057 #include "TopoShapePy.h"
00058 #include "TopoShapeFacePy.h"
00059 #include "TopoShapeEdgePy.h"
00060 #include "TopoShapeWirePy.h"
00061 #include "TopoShapeVertexPy.h"
00062 #include "TopoShapeSolidPy.h"
00063 #include "TopoShapeShellPy.h"
00064 #include "TopoShapeCompSolidPy.h"
00065 #include "TopoShapeCompoundPy.h"
00066 
00067 using namespace Part;
00068 
00069 TYPESYSTEM_SOURCE(Part::PropertyPartShape , App::PropertyComplexGeoData);
00070 
00071 PropertyPartShape::PropertyPartShape()
00072 {
00073 }
00074 
00075 PropertyPartShape::~PropertyPartShape()
00076 {
00077 }
00078 
00079 void PropertyPartShape::setValue(const TopoShape& sh)
00080 {
00081     aboutToSetValue();
00082     _Shape = sh;
00083     hasSetValue();
00084 }
00085 
00086 void PropertyPartShape::setValue(const TopoDS_Shape& sh)
00087 {
00088     aboutToSetValue();
00089     _Shape._Shape = sh;
00090     hasSetValue();
00091 }
00092 
00093 const TopoDS_Shape& PropertyPartShape::getValue(void)const 
00094 {
00095     return _Shape._Shape;
00096 }
00097 
00098 const TopoShape& PropertyPartShape::getShape() const
00099 {
00100     return this->_Shape;
00101 }
00102 
00103 const Data::ComplexGeoData* PropertyPartShape::getComplexData() const
00104 {
00105     return &(this->_Shape);
00106 }
00107 
00108 Base::BoundBox3d PropertyPartShape::getBoundingBox() const
00109 {
00110     Base::BoundBox3d box;
00111     if (_Shape._Shape.IsNull())
00112         return box;
00113     try {
00114         // If the shape is empty an exception may be thrown
00115         Bnd_Box bounds;
00116         BRepBndLib::Add(_Shape._Shape, bounds);
00117         bounds.SetGap(0.0);
00118         Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
00119         bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
00120 
00121         box.MinX = xMin;
00122         box.MaxX = xMax;
00123         box.MinY = yMin;
00124         box.MaxY = yMax;
00125         box.MinZ = zMin;
00126         box.MaxZ = zMax;
00127     }
00128     catch (Standard_Failure) {
00129     }
00130 
00131     return box;
00132 }
00133 
00134 void PropertyPartShape::getFaces(std::vector<Base::Vector3d> &aPoints,
00135                                  std::vector<Data::ComplexGeoData::Facet> &aTopo,
00136                                  float accuracy, uint16_t flags) const
00137 {
00138     _Shape.getFaces(aPoints, aTopo, accuracy, flags);
00139 }
00140 
00141 void PropertyPartShape::transformGeometry(const Base::Matrix4D &rclTrf)
00142 {
00143     aboutToSetValue();
00144     _Shape.transformGeometry(rclTrf);
00145     hasSetValue();
00146 }
00147 
00148 PyObject *PropertyPartShape::getPyObject(void)
00149 {
00150     const TopoDS_Shape& sh = _Shape._Shape;
00151     if (sh.IsNull())
00152         return new TopoShapePy(new TopoShape(sh));
00153 
00154     TopAbs_ShapeEnum type = sh.ShapeType();
00155     switch (type)
00156     {
00157     case TopAbs_COMPOUND:
00158         return new TopoShapeCompoundPy(new TopoShape(sh));
00159     case TopAbs_COMPSOLID:
00160         return new TopoShapeCompSolidPy(new TopoShape(sh));
00161     case TopAbs_SOLID:
00162         return new TopoShapeSolidPy(new TopoShape(sh));
00163     case TopAbs_SHELL:
00164         return new TopoShapeShellPy(new TopoShape(sh));
00165     case TopAbs_FACE:
00166         return new TopoShapeFacePy(new TopoShape(sh));
00167     case TopAbs_WIRE:
00168         return new TopoShapeWirePy(new TopoShape(sh));
00169     case TopAbs_EDGE:
00170         return new TopoShapeEdgePy(new TopoShape(sh));
00171     case TopAbs_VERTEX:
00172         return new TopoShapeVertexPy(new TopoShape(sh));
00173     case TopAbs_SHAPE:
00174     default:
00175         return new TopoShapePy(new TopoShape(sh));
00176         break;
00177     }
00178 }
00179 
00180 void PropertyPartShape::setPyObject(PyObject *value)
00181 {
00182     if (PyObject_TypeCheck(value, &(TopoShapePy::Type))) {
00183         TopoShapePy *pcObject = static_cast<TopoShapePy*>(value);
00184         setValue(*pcObject->getTopoShapePtr());
00185     }
00186     else {
00187         std::string error = std::string("type must be 'Shape', not ");
00188         error += value->ob_type->tp_name;
00189         throw Py::TypeError(error);
00190     }
00191 }
00192 
00193 App::Property *PropertyPartShape::Copy(void) const
00194 {
00195     PropertyPartShape *prop = new PropertyPartShape();
00196     prop->_Shape = this->_Shape;
00197     if (!_Shape._Shape.IsNull()) {
00198         BRepBuilderAPI_Copy copy(_Shape._Shape);
00199         prop->_Shape._Shape = copy.Shape();
00200     }
00201 
00202     return prop;
00203 }
00204 
00205 void PropertyPartShape::Paste(const App::Property &from)
00206 {
00207     aboutToSetValue();
00208     _Shape = dynamic_cast<const PropertyPartShape&>(from)._Shape;
00209     hasSetValue();
00210 }
00211 
00212 unsigned int PropertyPartShape::getMemSize (void) const
00213 {
00214     return _Shape.getMemSize();
00215 }
00216 
00217 void PropertyPartShape::Save (Base::Writer &writer) const
00218 {
00219     if(!writer.isForceXML()) {
00220         //See SaveDocFile(), RestoreDocFile()
00221         writer.Stream() << writer.ind() << "<Part file=\"" 
00222                         << writer.addFile("PartShape.brp", this)
00223                         << "\"/>" << std::endl;
00224     }
00225 }
00226 
00227 void PropertyPartShape::Restore(Base::XMLReader &reader)
00228 {
00229     reader.readElement("Part");
00230     std::string file (reader.getAttribute("file") );
00231 
00232     if (!file.empty()) {
00233         // initate a file read
00234         reader.addFile(file.c_str(),this);
00235     }
00236 }
00237 
00238 void PropertyPartShape::SaveDocFile (Base::Writer &writer) const
00239 {
00240     // If the shape is empty we simply store nothing. The file size will be 0 which
00241     // can be checked when reading in the data.
00242     if (_Shape._Shape.IsNull())
00243         return;
00244     // NOTE: Cleaning the triangulation may cause problems on some algorithms like BOP
00245     // Before writing to the project we clean all triangulation data to save memory
00246     // BRepTools::Clean(_Shape._Shape);
00247 
00248     // create a temporary file and copy the content to the zip stream
00249     // once the tmp. filename is known use always the same because otherwise
00250     // we may run into some problems on the Linux platform
00251     static Base::FileInfo fi(Base::FileInfo::getTempFileName());
00252 
00253     if (!BRepTools::Write(_Shape._Shape,(const Standard_CString)fi.filePath().c_str())) {
00254         // Note: Do NOT throw an exception here because if the tmp. file could
00255         // not be created we should not abort.
00256         // We only print an error message but continue writing the next files to the
00257         // stream...
00258         App::PropertyContainer* father = this->getContainer();
00259         if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
00260             App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
00261             Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n", 
00262                 obj->Label.getValue(),fi.filePath().c_str());
00263         }
00264         else {
00265             Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
00266         }
00267     }
00268 
00269     Base::ifstream file(fi, std::ios::in | std::ios::binary);
00270     if (file){
00271         unsigned long ulSize = 0; 
00272         std::streambuf* buf = file.rdbuf();
00273         if (buf) {
00274             unsigned long ulCurr;
00275             ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
00276             ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
00277             buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
00278         }
00279 
00280         // read in the ASCII file and write back to the stream
00281         std::strstreambuf sbuf(ulSize);
00282         file >> &sbuf;
00283         writer.Stream() << &sbuf;
00284     }
00285 
00286     file.close();
00287     // remove temp file
00288     fi.deleteFile();
00289 }
00290 
00291 void PropertyPartShape::RestoreDocFile(Base::Reader &reader)
00292 {
00293     BRep_Builder builder;
00294 
00295     // create a temporary file and copy the content from the zip stream
00296     Base::FileInfo fi(Base::FileInfo::getTempFileName());
00297 
00298     // read in the ASCII file and write back to the file stream
00299     Base::ofstream file(fi, std::ios::out | std::ios::binary);
00300     unsigned long ulSize = 0; 
00301     if (reader) {
00302         std::streambuf* buf = file.rdbuf();
00303         reader >> buf;
00304         file.flush();
00305         ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
00306     }
00307     file.close();
00308 
00309     // Read the shape from the temp file, if the file is empty the stored shape was already empty.
00310     // If it's still empty after reading the (non-empty) file there must occurred an error.
00311     TopoDS_Shape shape;
00312     if (ulSize > 0) {
00313         if (!BRepTools::Read(shape, (const Standard_CString)fi.filePath().c_str(), builder)) {
00314             // Note: Do NOT throw an exception here because if the tmp. created file could
00315             // not be read it's NOT an indication for an invalid input stream 'reader'.
00316             // We only print an error message but continue reading the next files from the
00317             // stream...
00318             App::PropertyContainer* father = this->getContainer();
00319             if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
00320                 App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
00321                 Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n", 
00322                     fi.filePath().c_str(),obj->Label.getValue());
00323             }
00324             else {
00325                 Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str());
00326             }
00327         }
00328     }
00329 
00330     // delete the temp file
00331     fi.deleteFile();
00332 
00333     setValue(shape);
00334 }
00335 
00336 // -------------------------------------------------------------------------
00337 
00338 TYPESYSTEM_SOURCE(Part::PropertyFilletEdges , App::PropertyLists);
00339 
00340 PropertyFilletEdges::PropertyFilletEdges()
00341 {
00342 }
00343 
00344 PropertyFilletEdges::~PropertyFilletEdges()
00345 {
00346 }
00347 
00348 void PropertyFilletEdges::setValue(int id, double r1, double r2)
00349 {
00350     aboutToSetValue();
00351     _lValueList.resize(1);
00352     _lValueList[0].edgeid = id;
00353     _lValueList[0].radius1 = r1;
00354     _lValueList[0].radius2 = r2;
00355     hasSetValue();
00356 }
00357 
00358 void PropertyFilletEdges::setValues(const std::vector<FilletElement>& values)
00359 {
00360     aboutToSetValue();
00361     _lValueList = values;
00362     hasSetValue();
00363 }
00364 
00365 PyObject *PropertyFilletEdges::getPyObject(void)
00366 {
00367     Py::List list(getSize());
00368     std::vector<FilletElement>::const_iterator it;
00369     int index = 0;
00370     for (it = _lValueList.begin(); it != _lValueList.end(); ++it) {
00371         Py::Tuple ent(3);
00372         ent.setItem(0, Py::Int(it->edgeid));
00373         ent.setItem(1, Py::Float(it->radius1));
00374         ent.setItem(2, Py::Float(it->radius2));
00375         list[index++] = ent;
00376     }
00377 
00378     return Py::new_reference_to(list);
00379 }
00380 
00381 void PropertyFilletEdges::setPyObject(PyObject *value)
00382 {
00383     Py::List list(value);
00384     std::vector<FilletElement> values;
00385     values.reserve(list.size());
00386     for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
00387         FilletElement fe;
00388         Py::Tuple ent(*it);
00389         fe.edgeid = (int)Py::Int(ent.getItem(0));
00390         fe.radius1 = (double)Py::Float(ent.getItem(1));
00391         fe.radius2 = (double)Py::Float(ent.getItem(2));
00392         values.push_back(fe);
00393     }
00394 
00395     setValues(values);
00396 }
00397 
00398 void PropertyFilletEdges::Save (Base::Writer &writer) const
00399 {
00400     if (!writer.isForceXML()) {
00401         writer.Stream() << writer.ind() << "<FilletEdges file=\"" << writer.addFile(getName(), this) << "\"/>" << std::endl;
00402     }
00403 }
00404 
00405 void PropertyFilletEdges::Restore(Base::XMLReader &reader)
00406 {
00407     reader.readElement("FilletEdges");
00408     std::string file (reader.getAttribute("file") );
00409 
00410     if (!file.empty()) {
00411         // initate a file read
00412         reader.addFile(file.c_str(),this);
00413     }
00414 }
00415 
00416 void PropertyFilletEdges::SaveDocFile (Base::Writer &writer) const
00417 {
00418     Base::OutputStream str(writer.Stream());
00419     uint32_t uCt = (uint32_t)getSize();
00420     str << uCt;
00421     for (std::vector<FilletElement>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
00422         str << it->edgeid << it->radius1 << it->radius2;
00423     }
00424 }
00425 
00426 void PropertyFilletEdges::RestoreDocFile(Base::Reader &reader)
00427 {
00428     Base::InputStream str(reader);
00429     uint32_t uCt=0;
00430     str >> uCt;
00431     std::vector<FilletElement> values(uCt);
00432     for (std::vector<FilletElement>::iterator it = values.begin(); it != values.end(); ++it) {
00433         str >> it->edgeid >> it->radius1 >> it->radius2;
00434     }
00435     setValues(values);
00436 }
00437 
00438 App::Property *PropertyFilletEdges::Copy(void) const
00439 {
00440     PropertyFilletEdges *p= new PropertyFilletEdges();
00441     p->_lValueList = _lValueList;
00442     return p;
00443 }
00444 
00445 void PropertyFilletEdges::Paste(const Property &from)
00446 {
00447     aboutToSetValue();
00448     _lValueList = dynamic_cast<const PropertyFilletEdges&>(from)._lValueList;
00449     hasSetValue();
00450 }

Generated on Wed Nov 23 19:00:31 2011 for FreeCAD by  doxygen 1.6.1