MeshProperties.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) Juergen Riegel         <juergen.riegel@web.de>          *
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 #ifndef _PreComp_
00026 #endif
00027 
00028 #include <CXX/Objects.hxx>
00029 #include <Base/Console.h>
00030 #include <Base/Exception.h>
00031 #include <Base/Writer.h>
00032 #include <Base/Reader.h>
00033 #include <Base/Stream.h>
00034 
00035 #include "Core/MeshKernel.h"
00036 #include "Core/MeshIO.h"
00037 #include "Core/Iterator.h"
00038 
00039 #include "MeshProperties.h"
00040 #include "Mesh.h"
00041 #include "MeshPy.h"
00042 
00043 using namespace Mesh;
00044 
00045 TYPESYSTEM_SOURCE(Mesh::PropertyNormalList, App::PropertyVectorList);
00046 TYPESYSTEM_SOURCE(Mesh::PropertyCurvatureList , App::PropertyLists);
00047 TYPESYSTEM_SOURCE(Mesh::PropertyMeshKernel , App::PropertyComplexGeoData);
00048 
00049 void PropertyNormalList::transform(const Base::Matrix4D &mat)
00050 {
00051     // A normal vector is only a direction with unit length, so we only need to rotate it
00052     // (no translations or scaling)
00053 
00054     // Extract scale factors (assumes an orthogonal rotation matrix)
00055     // Use the fact that the length of the row vectors of R are all equal to 1
00056     // And that scaling is applied after rotating
00057     double s[3];
00058     s[0] = sqrt(mat[0][0] * mat[0][0] + mat[0][1] * mat[0][1] + mat[0][2] * mat[0][2]);
00059     s[1] = sqrt(mat[1][0] * mat[1][0] + mat[1][1] * mat[1][1] + mat[1][2] * mat[1][2]);
00060     s[2] = sqrt(mat[2][0] * mat[2][0] + mat[2][1] * mat[2][1] + mat[2][2] * mat[2][2]);
00061 
00062     // Set up the rotation matrix: zero the translations and make the scale factors = 1
00063     Base::Matrix4D rot;
00064     rot.setToUnity();
00065     for (unsigned short i = 0; i < 3; i++) {
00066         for (unsigned short j = 0; j < 3; j++) {
00067             rot[i][j] = mat[i][j] / s[i];
00068         }
00069     }
00070 
00071     aboutToSetValue();
00072 
00073     // Rotate the normal vectors
00074     for (int ii=0; ii<getSize(); ii++) {
00075         set1Value(ii, rot * operator[](ii));
00076     }
00077 
00078     hasSetValue();
00079 
00080 }
00081 
00082 // ----------------------------------------------------------------------------
00083 
00084 PropertyCurvatureList::PropertyCurvatureList()
00085 {
00086 
00087 }
00088 
00089 PropertyCurvatureList::~PropertyCurvatureList()
00090 {
00091 
00092 }
00093 
00094 void PropertyCurvatureList::setValue(const CurvatureInfo& lValue)
00095 {
00096     aboutToSetValue();
00097     _lValueList.resize(1);
00098     _lValueList[0]=lValue;
00099     hasSetValue();
00100 }
00101 
00102 void PropertyCurvatureList::setValues(const std::vector<CurvatureInfo>& lValues)
00103 {
00104     aboutToSetValue();
00105     _lValueList=lValues;
00106     hasSetValue();
00107 }
00108 
00109 std::vector<float> PropertyCurvatureList::getCurvature( int mode ) const
00110 {
00111     const std::vector<Mesh::CurvatureInfo>& fCurvInfo = getValues();
00112     std::vector<float> fValues;
00113     fValues.reserve(fCurvInfo.size());
00114 
00115     // Mean curvature
00116     if (mode == MeanCurvature) {
00117         for ( std::vector<Mesh::CurvatureInfo>::const_iterator it=fCurvInfo.begin();it!=fCurvInfo.end(); ++it )
00118         {
00119             fValues.push_back( 0.5f*(it->fMaxCurvature+it->fMinCurvature) );
00120         }
00121     }
00122     // Gaussian curvature
00123     else if (mode == GaussCurvature) {
00124         for ( std::vector<Mesh::CurvatureInfo>::const_iterator it=fCurvInfo.begin();it!=fCurvInfo.end(); ++it )
00125         {
00126             fValues.push_back( it->fMaxCurvature * it->fMinCurvature );
00127         }
00128     }
00129     // Maximum curvature
00130     else if (mode == MaxCurvature) {
00131         for ( std::vector<Mesh::CurvatureInfo>::const_iterator it=fCurvInfo.begin();it!=fCurvInfo.end(); ++it )
00132         {
00133           fValues.push_back( it->fMaxCurvature );
00134         }
00135     }
00136     // Minimum curvature
00137     else if (mode == MinCurvature) {
00138         for ( std::vector<Mesh::CurvatureInfo>::const_iterator it=fCurvInfo.begin();it!=fCurvInfo.end(); ++it )
00139         {
00140           fValues.push_back( it->fMinCurvature );
00141         }
00142     }
00143     // Absolute curvature
00144     else if (mode == AbsCurvature) {
00145         for ( std::vector<Mesh::CurvatureInfo>::const_iterator it=fCurvInfo.begin();it!=fCurvInfo.end(); ++it )
00146         {
00147             if ( fabs(it->fMaxCurvature) > fabs(it->fMinCurvature) )
00148                 fValues.push_back( it->fMaxCurvature );
00149             else
00150                 fValues.push_back( it->fMinCurvature );
00151         }
00152     }
00153 
00154     return fValues;
00155 }
00156 
00157 void PropertyCurvatureList::transform(const Base::Matrix4D &mat)
00158 {
00159     // The principal direction is only a vector with unit length, so we only need to rotate it
00160     // (no translations or scaling)
00161     
00162     // Extract scale factors (assumes an orthogonal rotation matrix)
00163     // Use the fact that the length of the row vectors of R are all equal to 1
00164     // And that scaling is applied after rotating
00165     double s[3];
00166     s[0] = sqrt(mat[0][0] * mat[0][0] + mat[0][1] * mat[0][1] + mat[0][2] * mat[0][2]);
00167     s[1] = sqrt(mat[1][0] * mat[1][0] + mat[1][1] * mat[1][1] + mat[1][2] * mat[1][2]);
00168     s[2] = sqrt(mat[2][0] * mat[2][0] + mat[2][1] * mat[2][1] + mat[2][2] * mat[2][2]);
00169     
00170     // Set up the rotation matrix: zero the translations and make the scale factors = 1
00171     Base::Matrix4D rot;
00172     rot.setToUnity();
00173     for (unsigned short i = 0; i < 3; i++) {
00174         for (unsigned short j = 0; j < 3; j++) {
00175             rot[i][j] = mat[i][j] / s[i];
00176         }
00177     }
00178 
00179     aboutToSetValue();
00180 
00181     // Rotate the principal directions
00182     for (int ii=0; ii<getSize(); ii++)
00183     {
00184         CurvatureInfo ci = operator[](ii);
00185         ci.cMaxCurvDir = rot * ci.cMaxCurvDir;
00186         ci.cMinCurvDir = rot * ci.cMinCurvDir;
00187         _lValueList[ii] = ci;
00188     }
00189 
00190     hasSetValue();
00191 }
00192 
00193 void PropertyCurvatureList::Save (Base::Writer &writer) const
00194 {
00195     if (!writer.isForceXML()) {
00196         writer.Stream() << writer.ind() << "<CurvatureList file=\"" << 
00197         writer.addFile(getName(), this) << "\"/>" << std::endl;
00198     }
00199 }
00200 
00201 void PropertyCurvatureList::Restore(Base::XMLReader &reader)
00202 {
00203     reader.readElement("CurvatureList");
00204     std::string file (reader.getAttribute("file") );
00205     
00206     if (!file.empty()) {
00207         // initate a file read
00208         reader.addFile(file.c_str(),this);
00209     }
00210 }
00211 
00212 void PropertyCurvatureList::SaveDocFile (Base::Writer &writer) const
00213 {
00214     Base::OutputStream str(writer.Stream());
00215     uint32_t uCt = (uint32_t)getSize();
00216     str << uCt;
00217     for (std::vector<CurvatureInfo>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
00218         str << it->fMaxCurvature << it->fMinCurvature;
00219         str << it->cMaxCurvDir.x << it->cMaxCurvDir.y << it->cMaxCurvDir.z;
00220         str << it->cMinCurvDir.x << it->cMinCurvDir.y << it->cMinCurvDir.z;
00221     }
00222 }
00223 
00224 void PropertyCurvatureList::RestoreDocFile(Base::Reader &reader)
00225 {
00226     Base::InputStream str(reader);
00227     uint32_t uCt=0;
00228     str >> uCt;
00229     std::vector<CurvatureInfo> values(uCt);
00230     for (std::vector<CurvatureInfo>::iterator it = values.begin(); it != values.end(); ++it) {
00231         str >> it->fMaxCurvature >> it->fMinCurvature;
00232         str >> it->cMaxCurvDir.x >> it->cMaxCurvDir.y >> it->cMaxCurvDir.z;
00233         str >> it->cMinCurvDir.x >> it->cMinCurvDir.y >> it->cMinCurvDir.z;
00234     }
00235 
00236     setValues(values);
00237 }
00238 
00239 PyObject* PropertyCurvatureList::getPyObject(void)
00240 {
00241     Py::List list;
00242     for (std::vector<CurvatureInfo>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
00243         Py::Tuple tuple(4);
00244         tuple.setItem(0, Py::Float(it->fMaxCurvature));
00245         tuple.setItem(1, Py::Float(it->fMinCurvature));
00246         Py::Tuple maxDir(3);
00247         maxDir.setItem(0, Py::Float(it->cMaxCurvDir.x));
00248         maxDir.setItem(1, Py::Float(it->cMaxCurvDir.y));
00249         maxDir.setItem(2, Py::Float(it->cMaxCurvDir.z));
00250         tuple.setItem(2, maxDir);
00251         Py::Tuple minDir(3);
00252         minDir.setItem(0, Py::Float(it->cMinCurvDir.x));
00253         minDir.setItem(1, Py::Float(it->cMinCurvDir.y));
00254         minDir.setItem(2, Py::Float(it->cMinCurvDir.z));
00255         tuple.setItem(3, minDir);
00256         list.append(tuple);
00257     }
00258 
00259     return Py::new_reference_to(list);
00260 }
00261 
00262 void PropertyCurvatureList::setPyObject(PyObject *value)
00263 {
00264     throw Py::AttributeError(std::string("This attribute is read-only"));
00265 }
00266 
00267 App::Property *PropertyCurvatureList::Copy(void) const
00268 {
00269     PropertyCurvatureList *p= new PropertyCurvatureList();
00270     p->_lValueList = _lValueList;
00271     return p;
00272 }
00273 
00274 void PropertyCurvatureList::Paste(const App::Property &from)
00275 {
00276     aboutToSetValue();
00277     _lValueList = dynamic_cast<const PropertyCurvatureList&>(from)._lValueList;
00278     hasSetValue();
00279 }
00280 
00281 // ----------------------------------------------------------------------------
00282 
00283 PropertyMeshKernel::PropertyMeshKernel()
00284   : _meshObject(new MeshObject()), meshPyObject(0)
00285 {
00286     // Note: Normally this property is a member of a document object, i.e. the setValue()
00287     // method gets called in the constructor of a sublcass of DocumentObject, e.g. Mesh::Feature.
00288     // This means that the created MeshObject here will be replaced and deleted immediately. 
00289     // However, we anyway create this object in case we use this class in another context.
00290 }
00291 
00292 PropertyMeshKernel::~PropertyMeshKernel()
00293 {
00294     if (meshPyObject) {
00295         // Note: Do not call setInvalid() of the Python binding 
00296         // because the mesh should still be accessible afterwards.
00297         meshPyObject->parentProperty = 0;
00298         Py_DECREF(meshPyObject);
00299     }
00300 }
00301 
00302 void PropertyMeshKernel::setValuePtr(MeshObject* mesh)
00303 {
00304     // use the tmp. object to guarantee that the referenced mesh is not destroyed
00305     // before calling hasSetValue()
00306     Base::Reference<MeshObject> tmp(_meshObject);
00307     aboutToSetValue();
00308     _meshObject = mesh;
00309     hasSetValue();
00310 }
00311 
00312 void PropertyMeshKernel::setValue(const MeshObject& mesh)
00313 {
00314     aboutToSetValue();
00315     *_meshObject = mesh;
00316     hasSetValue();
00317 }
00318 
00319 void PropertyMeshKernel::setValue(const MeshCore::MeshKernel& mesh)
00320 {
00321     aboutToSetValue();
00322     _meshObject->setKernel(mesh);
00323     hasSetValue();
00324 }
00325 
00326 void PropertyMeshKernel::swapMesh(MeshObject& mesh)
00327 {
00328     aboutToSetValue();
00329     _meshObject->swap(mesh);
00330     hasSetValue();
00331 }
00332 
00333 void PropertyMeshKernel::swapMesh(MeshCore::MeshKernel& mesh)
00334 {
00335     aboutToSetValue();
00336     _meshObject->swap(mesh);
00337     hasSetValue();
00338 }
00339 
00340 const MeshObject& PropertyMeshKernel::getValue(void)const 
00341 {
00342     return *_meshObject;
00343 }
00344 
00345 const MeshObject* PropertyMeshKernel::getValuePtr(void)const 
00346 {
00347     return (MeshObject*)_meshObject;
00348 }
00349 
00350 const Data::ComplexGeoData* PropertyMeshKernel::getComplexData() const
00351 {
00352     return (MeshObject*)_meshObject;
00353 }
00354 
00355 Base::BoundBox3d PropertyMeshKernel::getBoundingBox() const
00356 {
00357     return _meshObject->getBoundBox();
00358 }
00359 
00360 void PropertyMeshKernel::getFaces(std::vector<Base::Vector3d> &aPoints,
00361                                   std::vector<Data::ComplexGeoData::Facet> &aTopo,
00362                                   float accuracy, uint16_t flags) const
00363 {
00364     _meshObject->getFaces(aPoints, aTopo, accuracy, flags);
00365 }
00366 
00367 unsigned int PropertyMeshKernel::getMemSize (void) const
00368 {
00369     unsigned int size = 0;
00370     size += _meshObject->getMemSize();
00371     
00372     return size;
00373 }
00374 
00375 MeshObject* PropertyMeshKernel::startEditing()
00376 {
00377     aboutToSetValue();
00378     return (MeshObject*)_meshObject;
00379 }
00380 
00381 void PropertyMeshKernel::finishEditing()
00382 {
00383     hasSetValue();
00384 }
00385 
00386 void PropertyMeshKernel::transformGeometry(const Base::Matrix4D &rclMat)
00387 {
00388     aboutToSetValue();
00389     _meshObject->transformGeometry(rclMat);
00390     hasSetValue();
00391 }
00392 
00393 void PropertyMeshKernel::deletePointIndices( const std::vector<unsigned long>& inds )
00394 {
00395     aboutToSetValue();
00396     _meshObject->deletePoints(inds);
00397     hasSetValue();
00398 }
00399 
00400 void PropertyMeshKernel::deleteFacetIndices( const std::vector<unsigned long>& inds )
00401 {
00402     aboutToSetValue();
00403     _meshObject->deleteFacets(inds);
00404     hasSetValue();
00405 }
00406 
00407 void PropertyMeshKernel::setPointIndices(const std::vector<std::pair<unsigned long, Base::Vector3f> >& inds)
00408 {
00409     aboutToSetValue();
00410     MeshCore::MeshKernel& kernel = _meshObject->getKernel();
00411     for (std::vector<std::pair<unsigned long, Base::Vector3f> >::const_iterator it = inds.begin(); it != inds.end(); ++it)
00412         kernel.SetPoint(it->first, it->second);
00413     hasSetValue();
00414 }
00415 
00416 void PropertyMeshKernel::append(const std::vector<MeshCore::MeshFacet>& rFaces,
00417                                 const std::vector<Base::Vector3f>& rPoints)
00418 {
00419     aboutToSetValue();
00420     _meshObject->addFacets(rFaces, rPoints);
00421     hasSetValue();
00422 }
00423 
00424 void PropertyMeshKernel::createSegment(const std::vector<unsigned long>& segm)
00425 {
00426     aboutToSetValue();
00427     _meshObject->addSegment(segm);
00428     hasSetValue();
00429 }
00430 
00431 void PropertyMeshKernel::smooth(int iter, float d_max)
00432 {
00433     aboutToSetValue();
00434     _meshObject->smooth(iter, d_max);
00435     hasSetValue();
00436 }
00437 
00438 void PropertyMeshKernel::clear()
00439 {
00440     // clear the underlying mesh kernel and free any allocated memory
00441     aboutToSetValue();
00442     _meshObject->clear();
00443     hasSetValue();
00444 }
00445 
00446 void PropertyMeshKernel::harmonizeNormals()
00447 {
00448     aboutToSetValue();
00449     _meshObject->harmonizeNormals();
00450     hasSetValue();
00451 }
00452 
00453 void PropertyMeshKernel::removeNonManifolds()
00454 {
00455     aboutToSetValue();
00456     _meshObject->removeNonManifolds();
00457     hasSetValue();
00458 }
00459 
00460 void PropertyMeshKernel::validateIndices()
00461 {
00462     aboutToSetValue();
00463     _meshObject->validateIndices();
00464     hasSetValue();
00465 }
00466 
00467 void PropertyMeshKernel::validateDegenerations()
00468 {
00469     aboutToSetValue();
00470     _meshObject->validateDegenerations();
00471     hasSetValue();
00472 }
00473 
00474 void PropertyMeshKernel::validateDeformations(float fMaxAngle)
00475 {
00476     aboutToSetValue();
00477     _meshObject->validateDeformations(fMaxAngle);
00478     hasSetValue();
00479 }
00480 
00481 void PropertyMeshKernel::removeDuplicatedFacets()
00482 {
00483     aboutToSetValue();
00484     _meshObject->removeDuplicatedFacets();
00485     hasSetValue();
00486 }
00487 
00488 void PropertyMeshKernel::removeDuplicatedPoints()
00489 {
00490     aboutToSetValue();
00491     _meshObject->removeDuplicatedPoints();
00492     hasSetValue();
00493 }
00494 
00495 void PropertyMeshKernel::removeSelfIntersections()
00496 {
00497     aboutToSetValue();
00498     _meshObject->removeSelfIntersections();
00499     hasSetValue();
00500 }
00501 
00502 void PropertyMeshKernel::removeFoldsOnSurface()
00503 {
00504     aboutToSetValue();
00505     _meshObject->removeFoldsOnSurface();
00506     hasSetValue();
00507 }
00508 
00509 PyObject *PropertyMeshKernel::getPyObject(void)
00510 {
00511     if (!meshPyObject) {
00512         meshPyObject = new MeshPy(&*_meshObject);
00513         meshPyObject->setConst(); // set immutable
00514         meshPyObject->parentProperty = this;
00515     }
00516 
00517     Py_INCREF(meshPyObject);
00518     return meshPyObject;
00519 }
00520 
00521 void PropertyMeshKernel::setPyObject(PyObject *value)
00522 {
00523     if (PyObject_TypeCheck(value, &(MeshPy::Type))) {
00524         MeshPy* mesh = static_cast<MeshPy*>(value);
00525         // Do not allow to reassign the same instance
00526         if (&(*this->_meshObject) != mesh->getMeshObjectPtr()) {
00527             // Note: Copy the content, do NOT reference the same mesh object
00528             setValue(*(mesh->getMeshObjectPtr()));
00529         }
00530     }
00531     else if (PyList_Check(value)) {
00532         // new instance of MeshObject
00533         Py::List triangles(value);
00534         MeshObject* mesh = MeshObject::createMeshFromList(triangles);
00535         setValuePtr(mesh);
00536     }
00537     else {
00538         std::string error = std::string("type must be 'Mesh', not ");
00539         error += value->ob_type->tp_name;
00540         throw Py::TypeError(error);
00541     }
00542 }
00543 
00544 void PropertyMeshKernel::Save (Base::Writer &writer) const
00545 {
00546     if (writer.isForceXML()) {
00547         writer.Stream() << writer.ind() << "<Mesh>" << std::endl;
00548         MeshCore::MeshOutput saver(_meshObject->getKernel());
00549         saver.SaveXML(writer);
00550     }
00551     else {
00552         writer.Stream() << writer.ind() << "<Mesh file=\"" << 
00553         writer.addFile("MeshKernel.bms", this) << "\"/>" << std::endl;
00554     }
00555 }
00556 
00557 void PropertyMeshKernel::Restore(Base::XMLReader &reader)
00558 {
00559     reader.readElement("Mesh");
00560     std::string file (reader.getAttribute("file") );
00561     
00562     if (file.empty()) {
00563         // read XML
00564         MeshCore::MeshKernel kernel;
00565         MeshCore::MeshInput restorer(kernel);
00566         restorer.LoadXML(reader);
00567 
00568         // avoid to duplicate the mesh in memory
00569         MeshCore::MeshPointArray points;
00570         MeshCore::MeshFacetArray facets;
00571         kernel.Adopt(points, facets);
00572 
00573         aboutToSetValue();
00574         _meshObject->getKernel().Adopt(points, facets);
00575         hasSetValue();
00576     } 
00577     else {
00578         // initate a file read
00579         reader.addFile(file.c_str(),this);
00580     }
00581 }
00582 
00583 void PropertyMeshKernel::SaveDocFile (Base::Writer &writer) const
00584 {
00585     _meshObject->save(writer.Stream());
00586 }
00587 
00588 void PropertyMeshKernel::RestoreDocFile(Base::Reader &reader)
00589 {
00590     aboutToSetValue();
00591     _meshObject->load(reader);
00592     hasSetValue();
00593 }
00594 
00595 App::Property *PropertyMeshKernel::Copy(void) const
00596 {
00597     // Note: Copy the content, do NOT reference the same mesh object
00598     PropertyMeshKernel *prop = new PropertyMeshKernel();
00599     *(prop->_meshObject) = *(this->_meshObject);
00600     return prop;
00601 }
00602 
00603 void PropertyMeshKernel::Paste(const App::Property &from)
00604 {
00605     // Note: Copy the content, do NOT reference the same mesh object
00606     aboutToSetValue();
00607     const PropertyMeshKernel& prop = dynamic_cast<const PropertyMeshKernel&>(from);
00608     *(this->_meshObject) = *(prop._meshObject);
00609     hasSetValue();
00610 }

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