diff --git a/Common/Options.cpp b/Common/Options.cpp index 7442decd668cb0dda4aa34dca9d4781f4e486667..f8a430a4fe3d871733666c4937ef598864cf3456 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -5654,7 +5654,7 @@ double opt_view_timestep(OPT_ARGS_NUM) opt->timeStep = 0; else if(opt->timeStep < 0) opt->timeStep = data->getNumTimeSteps() - 1; - if(data->isAdaptive()) + if(data->getAdaptiveData()) data->getAdaptiveData()->changeResolution (opt->timeStep, opt->maxRecursionLevel, opt->targetError); if(view) view->setChanged(true); @@ -6297,7 +6297,7 @@ double opt_view_max_recursion_level(OPT_ARGS_NUM) GET_VIEW(0.); if(action & GMSH_SET) { opt->maxRecursionLevel = (int)val; - if(data && data->isAdaptive()){ + if(data && data->getAdaptiveData()){ data->getAdaptiveData()->changeResolution (opt->timeStep, opt->maxRecursionLevel, opt->targetError); view->setChanged(true); @@ -6320,7 +6320,7 @@ double opt_view_target_error(OPT_ARGS_NUM) GET_VIEW(0.); if(action & GMSH_SET) { opt->targetError = val; - if(data && data->isAdaptive()){ + if(data && data->getAdaptiveData()){ data->getAdaptiveData()->changeResolution (opt->timeStep, opt->maxRecursionLevel, opt->targetError); view->setChanged(true); diff --git a/Plugin/Levelset.cpp b/Plugin/Levelset.cpp index a6ed07b067fad5105fd68e7b7f47b3f3b475d5a2..86b86e6d623b4b663a7c84ddbe1317ec7cb80c71 100644 --- a/Plugin/Levelset.cpp +++ b/Plugin/Levelset.cpp @@ -418,7 +418,7 @@ void GMSH_LevelsetPlugin::_cutAndAddElements(PViewData *vdata, PViewData *wdata, PView *GMSH_LevelsetPlugin::execute(PView *v) { // for adapted views we can only run the plugin on one step at a time - if(v->getData()->isAdaptive()){ + if(v->getData()->getAdaptiveData()){ PViewOptions *opt = v->getOptions(); v->getData()->getAdaptiveData()->changeResolution (opt->timeStep, _recurLevel, _targetError, this); diff --git a/Plugin/Plugin.cpp b/Plugin/Plugin.cpp index 90d14984e843a208f1e4a435586b6c546434138a..a56e2b2178c74c3f4fd394a1c353bad387f404ad 100644 --- a/Plugin/Plugin.cpp +++ b/Plugin/Plugin.cpp @@ -96,7 +96,7 @@ PViewData *GMSH_PostPlugin::getPossiblyAdaptiveData(PView *view) { if(!view) return 0; PViewData *data = view->getData(); - if(data->isAdaptive() && data->getNumTimeSteps() > 1) + if(data->getAdaptiveData() && data->getNumTimeSteps() > 1) Msg::Warning("Using adapted data from view '%s': only the current time step (%d/%d) " "is available to the plugin", view->getData()->getName().c_str(), view->getOptions()->timeStep, data->getNumTimeSteps()); diff --git a/Post/OctreePost.cpp b/Post/OctreePost.cpp index 7cfaf012d31a1aa0ea7813c5dba57c633bf91aa8..b2d10e14790d8f2c09cedf697bc4862cf431e737 100644 --- a/Post/OctreePost.cpp +++ b/Post/OctreePost.cpp @@ -6,6 +6,7 @@ #include "Octree.h" #include "OctreePost.h" #include "PView.h" +#include "PViewData.h" #include "PViewDataList.h" #include "PViewDataGModel.h" #include "Numeric.h" @@ -219,22 +220,33 @@ OctreePost::~OctreePost() } OctreePost::OctreePost(PView *v) - : _SL(0), _VL(0), _TL(0), _ST(0), _VT(0), _TT(0), _SQ(0), _VQ(0), _TQ(0), - _SS(0), _VS(0), _TS(0), _SH(0), _VH(0), _TH(0), _SI(0), _VI(0), _TI(0), - _SY(0), _VY(0), _TY(0), - _theView(v), _theViewDataList(0), _theViewDataGModel(0) { - _theViewDataGModel = dynamic_cast<PViewDataGModel*>(_theView->getData()); + _create(v->getData(true)); // use adaptive data if available +} + +OctreePost::OctreePost(PViewData *data) +{ + _create(data); +} + +void OctreePost::_create(PViewData *data) +{ + _SL = _VL = _TL = _ST = _VT = _TT = _SQ = _VQ = _TQ = 0; + _SS = _VS = _TS = _SH = _VH = _TH = _SI = _VI = _TI = 0; + _SY = _VY = _TY = 0; + _theViewDataList = 0; + _theViewDataGModel = 0; + + _theViewDataGModel = dynamic_cast<PViewDataGModel*>(data); if(_theViewDataGModel) return; // the octree is already available in the model - // use adaptive data if available - _theViewDataList = dynamic_cast<PViewDataList*>(_theView->getData(true)); + _theViewDataList = dynamic_cast<PViewDataList*>(data); if(_theViewDataList){ PViewDataList *l = _theViewDataList; - if(l->haveInterpolationMatrices() && !_theView->getData()->isAdaptive()){ + if(l->haveInterpolationMatrices() && !l->isAdapted()){ Msg::Error("Cannot create octree for non-adapted high-order list-based view: you need"); Msg::Error("to select 'Adapt visualization grid' first"); return; @@ -403,9 +415,14 @@ bool OctreePost::searchScalar(double x, double y, double z, double *values, { double P[3] = {x, y, z}; - if(step < 0) - for(int i = 0; i < _theView->getData()->getNumTimeSteps(); i++) + if(step < 0){ + int numSteps = 1; + if(_theViewDataList) numSteps = _theViewDataList->getNumTimeSteps(); + else if(_theViewDataGModel) numSteps = _theViewDataGModel->getNumTimeSteps(); + for(int i = 0; i < numSteps; i++){ values[i] = 0.0; + } + } else values[0] = 0.0; @@ -450,9 +467,13 @@ bool OctreePost::searchVector(double x, double y, double z, double *values, { double P[3] = {x, y, z}; - if(step < 0) - for(int i = 0; i < 3 * _theView->getData()->getNumTimeSteps(); i++) + if(step < 0){ + int numSteps = 1; + if(_theViewDataList) numSteps = _theViewDataList->getNumTimeSteps(); + else if(_theViewDataGModel) numSteps = _theViewDataGModel->getNumTimeSteps(); + for(int i = 0; i < 3 * numSteps; i++) values[i] = 0.0; + } else for(int i = 0; i < 3; i++) values[i] = 0.0; @@ -482,9 +503,13 @@ bool OctreePost::searchTensor(double x, double y, double z, double *values, { double P[3] = {x, y, z}; - if(step < 0) - for(int i = 0; i < 9 * _theView->getData()->getNumTimeSteps(); i++) + if(step < 0){ + int numSteps = 1; + if(_theViewDataList) numSteps = _theViewDataList->getNumTimeSteps(); + else if(_theViewDataGModel) numSteps = _theViewDataGModel->getNumTimeSteps(); + for(int i = 0; i < 9 * numSteps; i++) values[i] = 0.0; + } else for(int i = 0; i < 9; i++) values[i] = 0.0; diff --git a/Post/OctreePost.h b/Post/OctreePost.h index 51f6b28a6d498b94b6b8050e032061e8cfc59b6e..078e45873cd5e317c0cf0b685b2002175a2b9579 100644 --- a/Post/OctreePost.h +++ b/Post/OctreePost.h @@ -9,6 +9,7 @@ #include "Octree.h" class PView; +class PViewData; class PViewDataList; class PViewDataGModel; @@ -22,16 +23,17 @@ class OctreePost Octree *_SH, *_VH, *_TH; Octree *_SI, *_VI, *_TI; Octree *_SY, *_VY, *_TY; - PView *_theView; PViewDataList *_theViewDataList; PViewDataGModel *_theViewDataGModel; + void _create(PViewData *data); bool _getValue(void *in, int dim, int nbNod, int nbComp, double P[3], int step, double *values, double *elementSize); bool _getValue(void *in, int nbComp, double P[3], int step, double *values, double *elementSize); public : - OctreePost(PView *); + OctreePost(PView *v); + OctreePost(PViewData *data); ~OctreePost(); // search for the value of the View at point x, y, z. Values are // interpolated using standard first order shape functions in the diff --git a/Post/PView.cpp b/Post/PView.cpp index 1e9e71deb439382194162b902c0a426ab599313d..8cc88c76f2942edf4e66c01d84d154005852cd55 100644 --- a/Post/PView.cpp +++ b/Post/PView.cpp @@ -192,7 +192,7 @@ void PView::setOptions(PViewOptions *val) PViewData *PView::getData(bool useAdaptiveIfAvailable) { - if(useAdaptiveIfAvailable && _data->isAdaptive() && !_data->isRemote()) + if(useAdaptiveIfAvailable && _data->getAdaptiveData() && !_data->isRemote()) return _data->getAdaptiveData()->getData(); else return _data; diff --git a/Post/PViewData.cpp b/Post/PViewData.cpp index d76ac09bee45148b28e0fa4f6f3a02358917bf2a..e222c79121f3699d7a966489a2fcfae4c451ee2c 100644 --- a/Post/PViewData.cpp +++ b/Post/PViewData.cpp @@ -7,11 +7,12 @@ #include "adaptiveData.h" #include "Numeric.h" #include "GmshMessage.h" +#include "OctreePost.h" std::map<std::string, interpolationMatrices> PViewData::_interpolationSchemes; PViewData::PViewData() - : _dirty(true), _fileIndex(0), _adaptive(0) + : _dirty(true), _fileIndex(0), _octree(0), _adaptive(0) { } @@ -22,6 +23,7 @@ PViewData::~PViewData() it != _interpolation.end(); it++) for(unsigned int i = 0; i < it->second.size(); i++) delete it->second[i]; + if(_octree) delete _octree; } bool PViewData::finalize(bool computeMinMax, const std::string &interpolationScheme) @@ -172,3 +174,31 @@ bool PViewData::combineSpace(nameData &nd) Msg::Error("Combine space is not implemented for this type of data"); return false; } + +bool PViewData::searchScalar(double x, double y, double z, double *values, + int step, double *size) +{ + if(!_octree) _octree = new OctreePost(this); + return _octree->searchScalar(x, y, z, values, step, size); +} + +bool PViewData::searchScalarWithTol(double x, double y, double z, double *values, + int step, double *size, double tol) +{ + if(!_octree) _octree = new OctreePost(this); + return _octree->searchScalarWithTol(x, y, z, values, step, size, tol); +} + +bool PViewData::searchVector(double x, double y, double z, double *values, + int step, double *size) +{ + if(!_octree) _octree = new OctreePost(this); + return _octree->searchVector(x, y, z, values, step, size); +} + +bool PViewData::searchTensor(double x, double y, double z, double *values, + int step, double *size) +{ + if(!_octree) _octree = new OctreePost(this); + return _octree->searchTensor(x, y, z, values, step, size); +} diff --git a/Post/PViewData.h b/Post/PViewData.h index 947f13f88080ffbf0bea59dd0b6f2d58593feb2a..c8583262a1d38a6913056ac02dcb37eaa9d373c2 100644 --- a/Post/PViewData.h +++ b/Post/PViewData.h @@ -19,6 +19,7 @@ class GModel; class GEntity; class MElement; class nameData; +class OctreePost; typedef std::map<int, std::vector<fullMatrix<double>*> > interpolationMatrices; @@ -33,6 +34,8 @@ class PViewData { std::string _fileName; // index of the view in the file int _fileIndex; + // octree for rapid search + OctreePost *_octree; protected: // adaptive visualization data @@ -184,9 +187,6 @@ class PViewData { // true if data is given at Gauss points (instead of vertices) virtual bool useGaussPoints(){ return false; } - // check if the view is adaptive - bool isAdaptive(){ return _adaptive ? true : false; } - // initialize/destroy adaptive data void initAdaptiveData(int step, int level, double tol); void destroyAdaptiveData(); @@ -225,6 +225,20 @@ class PViewData { // get MElement (if view supports it) virtual MElement *getElement(int step, int entity, int element); + // search for the value of the View at point x, y, z. Values are + // interpolated using standard first order shape functions in the + // post element. If several time steps are present, they are all + // interpolated unless time step is set to a different value than + // -1. + bool searchScalar(double x, double y, double z, double *values, + int step=-1, double *size=0); + bool searchScalarWithTol(double x, double y, double z, double *values, + int step=-1, double *size=0, double tol=1.e-2); + bool searchVector(double x, double y, double z, double *values, + int step=-1, double *size=0); + bool searchTensor(double x, double y, double z, double *values, + int step=-1, double *size=0); + // I/O routines virtual bool writeSTL(std::string fileName); virtual bool writeTXT(std::string fileName); diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp index e4c77edb602cec226abf67460efe91260e1bf07e..df6f0634258d7f78b52c009a66913f908fbb93d8 100644 --- a/Post/PViewDataGModel.cpp +++ b/Post/PViewDataGModel.cpp @@ -449,7 +449,7 @@ int PViewDataGModel::getNumNodes(int step, int ent, int ele) else{ if(e->getNumChildren()) return e->getNumChildren() * e->getChild(0)->getNumVertices(); - if(isAdaptive()) + if(getAdaptiveData()) return e->getNumVertices(); return e->getNumPrimaryVertices(); } diff --git a/Post/PViewDataList.cpp b/Post/PViewDataList.cpp index 31e9dff239af952faae07590ebf865539ddb507e..f512d319bc54ba9c4c9a680004ec5d8dad81bce5 100644 --- a/Post/PViewDataList.cpp +++ b/Post/PViewDataList.cpp @@ -11,7 +11,7 @@ #include "SmoothData.h" #include "Context.h" -PViewDataList::PViewDataList() +PViewDataList::PViewDataList(bool isAdapted) : PViewData(), NbTimeStep(0), Min(VAL_INF), Max(-VAL_INF), Time(0), NbSP(0), NbVP(0), NbTP(0), SP(0), VP(0), TP(0), NbSL(0), NbVL(0), NbTL(0), NbST(0), NbVT(0), NbTT(0), @@ -20,7 +20,7 @@ PViewDataList::PViewDataList() NbSY(0), NbVY(0), NbTY(0), NbT2(0), NbT3(0), _lastElement(-1), _lastDimension(-1), _lastNumNodes(-1), _lastNumComponents(-1), _lastNumValues(-1), _lastNumEdges(-1), - _lastType(-1), _lastXYZ(0), _lastVal(0) + _lastType(-1), _lastXYZ(0), _lastVal(0), _isAdapted(isAdapted) { for(int i = 0; i < 24; i++) _index[i] = 0; } diff --git a/Post/PViewDataList.h b/Post/PViewDataList.h index a3d52af75867b23e13ee755de0c6b1b8474ed1a5..aec85cba0d1da1b6f89e71abef09e3c8d76f7a44 100644 --- a/Post/PViewDataList.h +++ b/Post/PViewDataList.h @@ -47,6 +47,7 @@ class PViewDataList : public PViewData { int _lastElement, _lastDimension; int _lastNumNodes, _lastNumComponents, _lastNumValues, _lastNumEdges, _lastType; double *_lastXYZ, *_lastVal; + bool _isAdapted; void _stat(std::vector<double> &D, std::vector<char> &C, int nb); void _stat(std::vector<double> &list, int nbcomp, int nbelm, int nbnod, int type); void _setLast(int ele); @@ -56,8 +57,9 @@ class PViewDataList : public PViewData { double &x, double &y, double &z, double &style); int _getRawData(int idxtype, std::vector<double> **l, int **ne, int *nc, int *nn); public: - PViewDataList(); + PViewDataList(bool isAdapted=false); ~PViewDataList(){} + bool isAdapted(){ return _isAdapted; } bool finalize(bool computeMinMax=true, const std::string &interpolationScheme=""); int getNumTimeSteps(){ return NbTimeStep; } double getTime(int step); diff --git a/Post/adaptiveData.cpp b/Post/adaptiveData.cpp index b667d16cb5f0a78142dff5b09261ae95355697a4..38e86c223f257c75624294572a6fc09e5fc30c26 100644 --- a/Post/adaptiveData.cpp +++ b/Post/adaptiveData.cpp @@ -1192,7 +1192,7 @@ adaptiveData::adaptiveData(PViewData *data) _points(0), _lines(0), _triangles(0), _quadrangles(0), _tetrahedra(0), _hexahedra(0), _prisms(0) { - _outData = new PViewDataList(); + _outData = new PViewDataList(true); _outData->setName(data->getName() + "_adapted"); std::vector<fullMatrix<double>*> p; if(_inData->getNumPoints()){