From 6f83c26127510dc0f245f97177b363361a4b5a59 Mon Sep 17 00:00:00 2001 From: =?utf8?q?C=C3=A9dric=20Aguerre?= Date: Tue, 21 Oct 2014 12:04:06 +0200 Subject: [PATCH] Add field interpolation to GUI --- idl/MEDDataManager.idl | 28 +- src/MEDOP/cmp/CMakeLists.txt | 5 +- src/MEDOP/cmp/MEDDataManager_i.cxx | 134 +++- src/MEDOP/cmp/MEDDataManager_i.hxx | 12 +- src/MEDOP/gui/DatasourceController.cxx | 92 ++- src/MEDOP/gui/DatasourceController.hxx | 8 +- src/MEDOP/gui/MED_images.ts | 4 + src/MEDOP/gui/MED_msg_en.ts | 53 ++ src/MEDOP/gui/MED_msg_fr.ts | 53 ++ src/MEDOP/gui/XmedConsoleDriver.cxx | 9 +- src/MEDOP/gui/dialogs/CMakeLists.txt | 8 +- .../gui/dialogs/DlgChangeUnderlyingMesh.ui | 10 +- src/MEDOP/gui/dialogs/DlgInterpolateField.cxx | 104 +++ src/MEDOP/gui/dialogs/DlgInterpolateField.hxx | 46 ++ src/MEDOP/gui/dialogs/DlgInterpolateField.ui | 655 ++++++++++++++++++ src/MEDOP/gui/dialogs/GenericDialog.ui | 67 +- src/MEDOP/res/CMakeLists.txt | 2 +- src/MEDOP/res/datasource_interpolateField.png | Bin 0 -> 836 bytes src/MEDOP/res/testfiles/smooth_surface.med | Bin 0 -> 40797 bytes .../testfiles/smooth_surface_and_field.med | Bin 0 -> 16209 bytes src/MEDOP/tui/xmedpy/driver_pvis.py | 50 +- src/MEDOP/tui/xmedpy/fieldtools.py | 33 +- 22 files changed, 1271 insertions(+), 102 deletions(-) create mode 100644 src/MEDOP/gui/dialogs/DlgInterpolateField.cxx create mode 100644 src/MEDOP/gui/dialogs/DlgInterpolateField.hxx create mode 100644 src/MEDOP/gui/dialogs/DlgInterpolateField.ui create mode 100644 src/MEDOP/res/datasource_interpolateField.png create mode 100644 src/MEDOP/res/testfiles/smooth_surface.med create mode 100644 src/MEDOP/res/testfiles/smooth_surface_and_field.med diff --git a/idl/MEDDataManager.idl b/idl/MEDDataManager.idl index ce1202018..51be0e61f 100644 --- a/idl/MEDDataManager.idl +++ b/idl/MEDDataManager.idl @@ -50,7 +50,7 @@ module MEDOP * point that aggregate a list of fields that relie on the same mesh * with the same type (the fields in a timeseries differ by their * time step). - * + * * Then you could have a field with no fieldseries associated but * directly associated to a mesh. That is typically the case of * fields created by MED operations: if you operate tow fields @@ -101,9 +101,18 @@ module MEDOP typedef sequence FieldHandlerList; typedef sequence FieldIdList; + struct InterpolationParameters { + double precision; + double defaultValue; + boolean reverse; + string method; + string nature; + string intersectionType; + }; + interface MEDDataManager: SALOME::GenericObj { - + //========================================================== // Datasource management //========================================================== @@ -112,7 +121,7 @@ module MEDOP //========================================================== // Mesh data management //========================================================== - + MeshHandler getMesh(in long meshId) raises (SALOME::SALOME_Exception); MeshHandlerList getMeshList(in long datasourceId); @@ -136,16 +145,19 @@ module MEDOP void updateFieldMetadata(in long fieldHandlerId, - in string fieldname, - in long iteration, - in long order, - in string source); + in string fieldname, + in long iteration, + in long order, + in string source); //void saveFields(in FieldHandlerList fieldHandlerList, in string filepath); void changeUnderlyingMesh(in long fieldHandlerId, in long meshHandlerId) raises (SALOME::SALOME_Exception); - + + FieldHandler interpolateField(in long fieldHandlerId, in long meshHandlerId, in InterpolationParameters params) + raises (SALOME::SALOME_Exception); + //========================================================== // General purpose data management //========================================================== diff --git a/src/MEDOP/cmp/CMakeLists.txt b/src/MEDOP/cmp/CMakeLists.txt index 2849b66eb..f55ccecbd 100644 --- a/src/MEDOP/cmp/CMakeLists.txt +++ b/src/MEDOP/cmp/CMakeLists.txt @@ -47,9 +47,10 @@ SET(COMMON_LIBS ${KERNEL_SalomeKernelHelpers} ${KERNEL_SalomeLifeCycleCORBA} ${KERNEL_SALOMELocalTrace} - ${KERNEL_SALOMEBasics} + ${KERNEL_SALOMEBasics} ${KERNEL_SalomeGenericObj} medcoupling + medcouplingremapper interpkernel ${MEDFILE_C_LIBRARIES} ${HDF5_LIBRARIES} @@ -57,7 +58,7 @@ SET(COMMON_LIBS ${PLATFORM_LIBRARIES} ) -# This undefines the macros MIN and MAX which are specified in the windows headers +# This undefines the macros MIN and MAX which are specified in the windows headers IF(WIN32) SET(COMMON_FLAGS "${COMMON_FLAGS} -DNOMINMAX") ENDIF(WIN32) diff --git a/src/MEDOP/cmp/MEDDataManager_i.cxx b/src/MEDOP/cmp/MEDDataManager_i.cxx index efd9b7af6..66115b422 100644 --- a/src/MEDOP/cmp/MEDDataManager_i.cxx +++ b/src/MEDOP/cmp/MEDDataManager_i.cxx @@ -79,7 +79,7 @@ std::string MEDDataManager_i::source_to_file(const char * source) */ MEDOP::DatasourceHandler * MEDDataManager_i::addDatasource(const char *filepath) { - // We first check that this datasource is not already registered + // We first check that this datasource is not already registered long sourceid = getDatasourceId(filepath); if ( sourceid != LONG_UNDEFINED ) { // The file is already registered under the identifier sourceid @@ -121,7 +121,7 @@ MEDOP::DatasourceHandler * MEDDataManager_i::addDatasource(const char *filepath) for (int iField = 0; iField < nbOfFields; iField++) { const char * fieldName = fieldNames[iField].c_str(); LOG("-- name of field " << iField << " = " << fieldName); - + // A field name could identify several MEDCoupling fields, that // differ by their spatial discretization on the mesh (values on // cells, values on nodes, ...). This spatial discretization is @@ -186,13 +186,13 @@ MEDOP::DatasourceHandler * MEDDataManager_i::addDatasource(const char *filepath) } } } - + return new MEDOP::DatasourceHandler(*datasourceHandler); } long MEDDataManager_i::getDatasourceId(const char *filepath) { std::string uri(file_to_source(filepath)); - DatasourceHandlerMapIterator it = _datasourceHandlerMap.begin(); + DatasourceHandlerMapIterator it = _datasourceHandlerMap.begin(); while ( it != _datasourceHandlerMap.end() ) { if ( strcmp(it->second->uri,uri.c_str()) == 0 ) { return it->first; @@ -268,7 +268,7 @@ MEDOP::FieldseriesHandlerList * MEDDataManager_i::getFieldseriesListOnMesh(CORBA /*! * A fieldseries is a timeseries of fields. Then the list of fields is - * the different time iterations defined for the specified field id. + * the different time iterations defined for the specified field id. */ MEDOP::FieldHandlerList * MEDDataManager_i::getFieldListInFieldseries(CORBA::Long fieldseriesId) { @@ -359,32 +359,32 @@ void MEDDataManager_i::saveFields(const char * filepath, if ( fieldIdList.length() == 0 ) { throw KERNEL::createSalomeException("No fields to save"); } - + // Consider the first field to initiate the med file CORBA::Long fieldHandlerId = fieldIdList[0]; MEDOP::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId); - MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler); + MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler); try { bool writeFromScratch = true; MEDLoader::WriteField(filepath, fieldDouble, writeFromScratch); - + writeFromScratch = false; for(CORBA::ULong i=1; ifirst); } } - + MEDOP::FieldIdList fieldIdList; fieldIdList.length(listId.size()); for (int i=0; isaveFields(filepath, fieldIdList); - } + } catch (const SALOME::SALOME_Exception & ex) { throw ex; } catch (const std::exception& ex) { - std::string message = + std::string message = std::string("Error when saving file ") + std::string(filepath) + std::string(" : ") + ex.what(); throw KERNEL::createSalomeException(message.c_str()); @@ -501,16 +501,16 @@ MEDCouplingUMesh * MEDDataManager_i::getUMesh(long meshHandlerId) { myMesh = _meshMap[meshHandlerId]; } else { // The mesh is not loaded yet ==> load it and register it in the map - LOG("getUMesh: the mesh must be loaded. meshid="<sourceid; - std::string filepath(source_to_file((_datasourceHandlerMap[sourceid])->uri)); + std::string filepath(source_to_file((_datasourceHandlerMap[sourceid])->uri)); const char * meshName = _meshHandlerMap[meshHandlerId]->name; int meshDimRelToMax = 0; myMesh = MEDLoader::ReadUMeshFromFile(filepath,meshName,meshDimRelToMax); @@ -525,7 +525,7 @@ MEDCouplingUMesh * MEDDataManager_i::getUMesh(long meshHandlerId) { */ long MEDDataManager_i::getUMeshId(const MEDCouplingMesh * mesh) { bool found = false; - MeshMapIterator it = _meshMap.begin(); + MeshMapIterator it = _meshMap.begin(); while ( it != _meshMap.end() ) { found = (it->second == mesh); if (found) { @@ -625,7 +625,7 @@ MEDOP::FieldHandler * MEDDataManager_i::addField(MEDCouplingFieldDouble * fieldD // variables are updated by this function call. This is the mean to // retrieve the iteration and order of the field. double timestamp = fieldDouble->getTime(iteration, order); - + // For the fields that are created in memory (by operations for // example), the convention for the source attribute is to specify // the fielddouble name, because this name describes the operation @@ -659,13 +659,13 @@ MEDOP::FieldHandler * MEDDataManager_i::addField(MEDCouplingFieldDouble * fieldD else { fieldHandler->meshid = meshHandlerId; } - + _fieldHandlerMap[fieldHandler->id] = fieldHandler; _fieldDoubleMap[fieldHandler->id] = fieldDouble; // >>> WARNING: CORBA structure assignement specification ==> return // >>> a deep copy to avoid the destruction of the fieldHandler // >>> registered in the map (assignement acts as a destructor for - // >>> CORBA struct). + // >>> CORBA struct). return new MEDOP::FieldHandler(*fieldHandler); } @@ -700,7 +700,7 @@ void MEDDataManager_i::updateFieldMetadata(CORBA::Long fieldHandlerId, * new mesh is not identical to the old one. */ void MEDDataManager_i::changeUnderlyingMesh(CORBA::Long fieldHandlerId, CORBA::Long meshHandlerId) { - + MEDOP::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId); MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler); MEDCouplingMesh * newMesh = getUMesh(meshHandlerId); @@ -724,6 +724,92 @@ void MEDDataManager_i::changeUnderlyingMesh(CORBA::Long fieldHandlerId, CORBA::L // synchronized } +INTERP_KERNEL::IntersectionType MEDDataManager_i::_getIntersectionType(const char* intersType) { + std::string type(intersType); + if (type == "Triangulation") { + return INTERP_KERNEL::Triangulation; + } + else if (type == "Convex") { + return INTERP_KERNEL::Convex; + } + else if (type == "Geometric2D") { + return INTERP_KERNEL::Geometric2D; + } + else if (type == "PointLocator") { + return INTERP_KERNEL::PointLocator; + } + else if (type == "Barycentric") { + return INTERP_KERNEL::Barycentric; + } + else if (type == "BarycentricGeo2D") { + return INTERP_KERNEL::BarycentricGeo2D; + } + + std::string message("Error when trying to interpolate field: "); + message.append("Unrecognized intersection type: "); + message.append(type); + throw KERNEL::createSalomeException(message.c_str()); +} + +ParaMEDMEM::NatureOfField MEDDataManager_i::_getNatureOfField(const char* fieldNature) { + std::string nature(fieldNature); + if (nature == "NoNature") { + return NoNature; + } + else if (nature == "ConservativeVolumic") { + return ConservativeVolumic; + } + else if (nature == "Integral") { + return Integral; + } + else if (nature == "IntegralGlobConstraint") { + return IntegralGlobConstraint; + } + else if (nature == "RevIntegral") { + return RevIntegral; + } + + std::string message("Error when trying to interpolate field: "); + message.append("Unrecognized field nature: "); + message.append(nature); + throw KERNEL::createSalomeException(message.c_str()); +} + +MEDOP::FieldHandler* MEDDataManager_i::interpolateField(CORBA::Long fieldHandlerId, CORBA::Long meshHandlerId, const MEDOP::InterpolationParameters& params) { + MEDOP::FieldHandler* fieldHandler = getFieldHandler(fieldHandlerId); + MEDCouplingFieldDouble* sourceField = getFieldDouble(fieldHandler); + MEDCouplingMesh* sourceMesh = getUMesh(fieldHandler->meshid); + MEDCouplingMesh* targetMesh = getUMesh(meshHandlerId); + + double precision = params.precision; + INTERP_KERNEL::IntersectionType interpType = this->_getIntersectionType(params.intersectionType); + std::string method(params.method); + double defaultValue = params.defaultValue; + bool reverse = params.reverse; + ParaMEDMEM::NatureOfField nature = this->_getNatureOfField(params.nature); + + // 1. Build remapper between sourceMesh and targetMesh (compute interpolation matrix) + MEDCouplingRemapper remapper; + remapper.setPrecision(precision); + remapper.setIntersectionType(interpType); + remapper.prepare(sourceMesh, targetMesh, method.c_str()); + + // 2. Apply interpolation to the field + sourceField->setNature(nature); + MEDCouplingFieldDouble* targetField = NULL; + if (reverse) { + targetField = remapper.reverseTransferField(sourceField, defaultValue); + } else { + targetField = remapper.transferField(sourceField, defaultValue); + } + targetField->setMesh(targetMesh); + targetField->setName(targetMesh->getName() + "_field"); + + // 3. Create and register field handler + MEDOP::FieldHandler* fieldResultHandler = this->addField(targetField, this->getUMeshId(targetField->getMesh())); + return fieldResultHandler; +} + /*! @@ -731,7 +817,7 @@ void MEDDataManager_i::changeUnderlyingMesh(CORBA::Long fieldHandlerId, CORBA::L * the server side (data in the SALOME container). */ void MEDDataManager_i::serverlog() { - + LOG("==== Field Handler Map ===================================================="); LOG("Size = "<<_fieldHandlerMap.size()); FieldHandlerMapIterator fhmIt; diff --git a/src/MEDOP/cmp/MEDDataManager_i.hxx b/src/MEDOP/cmp/MEDDataManager_i.hxx index 8a04315ad..96820420c 100644 --- a/src/MEDOP/cmp/MEDDataManager_i.hxx +++ b/src/MEDOP/cmp/MEDDataManager_i.hxx @@ -26,6 +26,7 @@ #include CORBA_SERVER_HEADER(MEDDataManager) #include "SALOME_GenericObj_i.hh" +#include "MEDCouplingRemapper.hxx" #include "MEDCouplingUMesh.hxx" #include "MEDCouplingFieldDouble.hxx" using namespace ParaMEDMEM; @@ -61,7 +62,7 @@ class MEDOP_EXPORT MEDDataManager_i: public POA_MEDOP::MEDDataManager, { public: - // + // // =========================================================== // Functions specified in the IDL interface // =========================================================== @@ -73,7 +74,7 @@ public: // ----------------------------------------------------------- // Mesh management MEDOP::MeshHandlerList * getMeshList(CORBA::Long datasourceId); - MEDOP::MeshHandler * getMesh(CORBA::Long meshId); + MEDOP::MeshHandler * getMesh(CORBA::Long meshId); // ----------------------------------------------------------- // Field management @@ -97,13 +98,14 @@ public: const char * source); void changeUnderlyingMesh(CORBA::Long fieldHandlerId, CORBA::Long meshHandlerId); + MEDOP::FieldHandler* interpolateField(CORBA::Long fieldHandlerId, CORBA::Long meshHandlerId, const MEDOP::InterpolationParameters& params); void setEventListenerIOR(const char * ior); char * getEventListenerIOR(); void serverlog(); - // + // // =========================================================== // Other public functions (non available via CORBA) // =========================================================== @@ -155,6 +157,10 @@ private: MEDCouplingUMesh * getUMesh(long meshHandlerId); long getUMeshId(const MEDCouplingMesh * mesh); + + INTERP_KERNEL::IntersectionType _getIntersectionType(const char* intersType); + ParaMEDMEM::NatureOfField _getNatureOfField(const char* fieldNature); + }; #endif // _MED_DATAMANAGER_I_HXX_ diff --git a/src/MEDOP/gui/DatasourceController.cxx b/src/MEDOP/gui/DatasourceController.cxx index 414431bf4..ca0d90b6d 100644 --- a/src/MEDOP/gui/DatasourceController.cxx +++ b/src/MEDOP/gui/DatasourceController.cxx @@ -44,11 +44,15 @@ DatasourceController::DatasourceController(StandardApp_Module * salomeModule) { STDLOG("Creating a DatasourceController"); _salomeModule = salomeModule; _studyEditor = new SALOME_AppStudyEditor(_salomeModule->getApp()); - _dlgChangeUnderlyingMesh = new DlgChangeUnderlyingMesh(_studyEditor); + _dlgChangeUnderlyingMesh = new DlgChangeUnderlyingMesh(_studyEditor); connect(_dlgChangeUnderlyingMesh,SIGNAL(inputValidated()), this, SLOT(OnChangeUnderlyingMeshInputValidated())); + _dlgInterpolateField = new DlgInterpolateField(_studyEditor); + connect(_dlgInterpolateField,SIGNAL(inputValidated()), + this, SLOT(OnInterpolateFieldInputValidated())); + } DatasourceController::~DatasourceController() { @@ -106,6 +110,11 @@ void DatasourceController::createActions() { actionId = _salomeModule->createStandardAction(label,this,SLOT(OnChangeUnderlyingMesh()),icon); _salomeModule->addActionInPopupMenu(actionId); + label = tr("LAB_INTERPOLATE_FIELD"); + icon = tr("ICO_DATASOURCE_INTERPOLATE_FIELD"); + actionId = _salomeModule->createStandardAction(label,this,SLOT(OnInterpolateField()),icon); + _salomeModule->addActionInPopupMenu(actionId); + } /** @@ -348,6 +357,13 @@ void DatasourceController::OnUseInWorkspace() { MEDOP::FieldHandler * fieldHandler = MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId); + if (! fieldHandler) { + QMessageBox::warning(_salomeModule->getApp()->desktop(), + tr("Operation not allowed"), + tr("No field is defined")); + return; + } + QString alias(fieldHandler->fieldname); DlgAlias dialog; dialog.setAlias(alias); @@ -406,7 +422,6 @@ void DatasourceController::OnUseInWorkspace() { } } - void DatasourceController::OnChangeUnderlyingMesh() { // We need a studyEditor updated on the active study _studyEditor->updateActiveStudy(); @@ -456,6 +471,79 @@ void DatasourceController::OnChangeUnderlyingMeshInputValidated() { // Tag the item to prevent double import //_studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true); +} + +void DatasourceController::OnInterpolateField() { + // We need a studyEditor updated on the active study + _studyEditor->updateActiveStudy(); + + // Get the selected objects in the study (SObject). In case of a + // multiple selection, we consider only the first item. At least one + // item must be selected. + SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects(); + if ( listOfSObject->size() > 0 ) { + SALOMEDS::SObject_var soField = listOfSObject->at(0); + int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID); + // _GBO_ : the dialog should not be modal, so that we can choose a + // mesh in the browser. Then we have to emit a signal from the + // dialog.accept, connected to a slot of the DatasourceControler + _dlgInterpolateField->setFieldId(fieldId); + Qt::WindowFlags flags = _dlgInterpolateField->windowFlags(); + _dlgInterpolateField->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); + _dlgInterpolateField->open(); + } +} + +void DatasourceController::OnInterpolateFieldInputValidated() { + MEDOP::InterpolationParameters params; + params.precision = _dlgInterpolateField->getPrecision(); + STDLOG("precision = " << params.precision); + params.defaultValue = _dlgInterpolateField->getDefaultValue(); + STDLOG("defaultValue = " << params.defaultValue); + params.reverse = _dlgInterpolateField->getReverse(); + STDLOG("reverse = " << params.reverse); + params.intersectionType = _dlgInterpolateField->getIntersectionType().c_str(); + STDLOG("intersectionType = " << params.intersectionType); + params.method = _dlgInterpolateField->getMethod().c_str(); + STDLOG("method = " << params.method); + params.nature = _dlgInterpolateField->getFieldNature().c_str(); + STDLOG("nature = " << params.nature); + + int meshId = _dlgInterpolateField->getMeshId(); + STDLOG("meshId = " << ToString(meshId)); + int fieldId = _dlgInterpolateField->getFieldId(); + MEDOP::FieldHandler* fieldHandler = MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId); + + // We don't modify the original field but create first a duplicate + // MEDOP::FieldHandler* duplicate = MEDOPFactoryClient::getCalculator()->dup(*fieldHandler); + //MEDOPFactoryClient::getDataManager()->changeUnderlyingMesh(duplicate->id, meshId); + MEDOP::FieldHandler* result = NULL; + try { + result = MEDOPFactoryClient::getDataManager()->interpolateField(fieldId, meshId, params); + } + catch(...) { + STDLOG("Unable to process field interpolation; please check interpolation parameters"); + QMessageBox::critical(_salomeModule->getApp()->desktop(), + tr("Operation failed"), + tr("Unable to process field interpolation; please check interpolation parameters")); + return; + } + // Request once more the duplicate to update the meta-data on this + // client side + // duplicate = MEDOPFactoryClient::getDataManager()->getFieldHandler(duplicate->id); + + // >>> + // WARN: the following is a temporary code for test purpose + // Automatically add in ws + DatasourceEvent * event = new DatasourceEvent(); + event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT; + XmedDataObject * dataObject = new XmedDataObject(); + dataObject->setFieldHandler(*result); + event->objectdata = dataObject; + emit datasourceSignal(event); + // Note that this signal is processed by the WorkspaceController + // // Tag the item to prevent double import + // //_studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true); } diff --git a/src/MEDOP/gui/DatasourceController.hxx b/src/MEDOP/gui/DatasourceController.hxx index 42c5b4eea..f64ee4fcf 100644 --- a/src/MEDOP/gui/DatasourceController.hxx +++ b/src/MEDOP/gui/DatasourceController.hxx @@ -17,7 +17,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Guillaume Boulant (EDF) +// Author : Guillaume Boulant (EDF) #ifndef DATASOURCE_CONTROLLER_H #define DATASOURCE_CONTROLLER_H @@ -31,6 +31,7 @@ #include "XmedDataModel.hxx" #include "DlgChangeUnderlyingMesh.hxx" +#include "DlgInterpolateField.hxx" #include "MEDOPGUI.hxx" // // The DatasourceController defines data structures and classes to @@ -48,7 +49,7 @@ // transmit an object AND an alias. typedef struct { enum EventType { - // + // EVENT_IMPORT_OBJECT, // Simply import the object in the workspace EVENT_USE_OBJECT, // Import in the workspace AND define a proxy // variable in the tui console to use it @@ -77,6 +78,7 @@ public: public slots: // Callback connected to dialog box validation signals void OnChangeUnderlyingMeshInputValidated(); + void OnInterpolateFieldInputValidated(); signals: void datasourceSignal(const DatasourceEvent * event); @@ -88,6 +90,7 @@ protected slots: void OnVisualize(); void OnUseInWorkspace(); void OnChangeUnderlyingMesh(); + void OnInterpolateField(); private: @@ -95,6 +98,7 @@ private: SALOME_AppStudyEditor * _studyEditor; DlgChangeUnderlyingMesh * _dlgChangeUnderlyingMesh; + DlgInterpolateField * _dlgInterpolateField; }; diff --git a/src/MEDOP/gui/MED_images.ts b/src/MEDOP/gui/MED_images.ts index 3b312eda6..62a6afbc5 100644 --- a/src/MEDOP/gui/MED_images.ts +++ b/src/MEDOP/gui/MED_images.ts @@ -19,6 +19,10 @@ ICO_DATASOURCE_CHANGE_MESH datasource_changeUnderlyingMesh.png + + ICO_DATASOURCE_INTERPOLATE_FIELD + datasource_interpolateField.png + ICO_DATASOURCE_EXPAND_FIELD datasource_expandfield.png diff --git a/src/MEDOP/gui/MED_msg_en.ts b/src/MEDOP/gui/MED_msg_en.ts index 40c9b6961..4008c8a7b 100644 --- a/src/MEDOP/gui/MED_msg_en.ts +++ b/src/MEDOP/gui/MED_msg_en.ts @@ -43,6 +43,11 @@ LAB_CHANGE_MESH Change underlying mesh + + + LAB_INTERPOLATE_FIELD + Interpolate field + IMPORT_MED_FIELDS @@ -121,6 +126,54 @@ You must select a mesh in the explorer and clic the button Mesh + + DlgInterpolateField + + + SELECT_MESH + You must select a mesh in the explorer and clic the button Mesh + + + + TARGET_MESH_GT + Target mesh -> + + + + MSG_EXPLORER + (Explorer provides a view on MED data sources (mesh and fields) referenced in data space) + + + + LABEL_PRECISION + Interpolator precision + + + + LABEL_INTERSECTION_TYPE + Intersection type + + + + LABEL_METHOD + Interpolation method + + + + LABEL_DEFAULT_VALUE + Default value of resulting field + + + + LABEL_REVERSE + Reverse interpolation ? + + + + LABEL_NATURE + Field nature + + DlgImageToMed diff --git a/src/MEDOP/gui/MED_msg_fr.ts b/src/MEDOP/gui/MED_msg_fr.ts index 9ba8ffcb7..2254d0549 100644 --- a/src/MEDOP/gui/MED_msg_fr.ts +++ b/src/MEDOP/gui/MED_msg_fr.ts @@ -43,6 +43,11 @@ LAB_CHANGE_MESH Changer le maillage sous-jacent + + + LAB_INTERPOLATE_FIELD + Interpoler le champ + IMPORT_MED_FIELDS @@ -121,6 +126,54 @@ Vous devez sélectionner un maillage dans l'explorateur et cliquer sur le bouton Maillage + + DlgInterpolateField + + + SELECT_MESH + Vous devez sélectionner un maillage dans l'explorateur et cliquer sur le bouton Maillage + + + + TARGET_MESH_GT + Maillage cible -> + + + + MSG_EXPLORER + (L'explorateur fournit une vue des données MED (maillage et champs) référencées dans l'espace des données) + + + + LABEL_PRECISION + Précision de l'interpolateur + + + + LABEL_INTERSECTION_TYPE + Type d'intersection + + + + LABEL_METHOD + Méthode d'interpolation + + + + LABEL_DEFAULT_VALUE + Valeur par défaut du champ résultant + + + + LABEL_REVERSE + Interpolation inverse ? + + + + LABEL_NATURE + Nature du champ + + DlgImageToMed diff --git a/src/MEDOP/gui/XmedConsoleDriver.cxx b/src/MEDOP/gui/XmedConsoleDriver.cxx index 99c0d7f30..ab3217b3f 100644 --- a/src/MEDOP/gui/XmedConsoleDriver.cxx +++ b/src/MEDOP/gui/XmedConsoleDriver.cxx @@ -16,7 +16,7 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Guillaume Boulant (EDF) +// Author : Guillaume Boulant (EDF) #include "XmedConsoleDriver.hxx" #include "Utils_SALOME_Exception.hxx" @@ -39,7 +39,7 @@ XmedConsoleDriver::XmedConsoleDriver(SalomeApp_Application * application) { * instructions are sent once. */ void XmedConsoleDriver::setup() { - + if ( !_importXmedDone ) { QStringList commands; // First import xmed to initialize the main objects, in particular @@ -52,6 +52,11 @@ void XmedConsoleDriver::setup() { // A last one to clear the console screen //commands+="wipe"; + // start PVServer and show render view + commands+="import pvsimple as pvs"; + commands+=""; + //commands+="pvs.ShowParaviewView()"; + this->exec(commands); _importXmedDone = true; } diff --git a/src/MEDOP/gui/dialogs/CMakeLists.txt b/src/MEDOP/gui/dialogs/CMakeLists.txt index 7b550727b..cad22cc20 100644 --- a/src/MEDOP/gui/dialogs/CMakeLists.txt +++ b/src/MEDOP/gui/dialogs/CMakeLists.txt @@ -26,6 +26,7 @@ SET(MEDOPGUI_dialogs_FORMS DlgAlias.ui DlgUseInWorkspace.ui DlgChangeUnderlyingMesh.ui + DlgInterpolateField.ui DlgImageToMed.ui ) QT4_WRAP_UI(MEDOPGUI_dialogs_FORMS_HEADERS ${MEDOPGUI_dialogs_FORMS}) @@ -35,6 +36,7 @@ SET(MEDOPGUI_dialogs_FILES DlgAlias.hxx DlgUseInWorkspace.hxx DlgChangeUnderlyingMesh.hxx + DlgInterpolateField.hxx DlgImageToMed.hxx ) QT4_WRAP_CPP(MEDOPGUI_dialogs_HEADERS_MOC ${MEDOPGUI_dialogs_FILES}) @@ -55,12 +57,13 @@ SET(MEDOPGUI_dialogs_SOURCES DlgAlias.cxx DlgUseInWorkspace.cxx DlgChangeUnderlyingMesh.cxx + DlgInterpolateField.cxx DlgImageToMed.cxx ) ADD_LIBRARY(MEDOPGUI_dialogs SHARED ${MEDOPGUI_dialogs_SOURCES} ${MEDOPGUI_dialogs_HEADERS_MOC} ${MEDOPGUI_dialogs_FORMS_HEADERS}) -TARGET_LINK_LIBRARIES(MEDOPGUI_dialogs ${CAS_KERNEL} ${QT_LIBRARIES} ${KERNEL_SalomeIDLKernel} - ${GUI_SalomeGuiHelpers} ${OMNIORB_LIBRARIES} ${GUI_qtx} ${GUI_suit} ${PLATFORM_LIBRARIES} +TARGET_LINK_LIBRARIES(MEDOPGUI_dialogs ${CAS_KERNEL} ${QT_LIBRARIES} ${KERNEL_SalomeIDLKernel} + ${GUI_SalomeGuiHelpers} ${OMNIORB_LIBRARIES} ${GUI_qtx} ${GUI_suit} ${PLATFORM_LIBRARIES} ${KERNEL_SalomeLifeCycleCORBA} ${KERNEL_SalomeKernelHelpers} ${GUI_SalomeGuiHelpers}) INSTALL(TARGETS MEDOPGUI_dialogs DESTINATION ${SALOME_INSTALL_LIBS}) @@ -76,4 +79,3 @@ INSTALL(TARGETS dlgTester DESTINATION ${SALOME_INSTALL_BINS}) FILE(GLOB COMMON_HEADERS_HXX "${CMAKE_CURRENT_SOURCE_DIR}/*.hxx") INSTALL(FILES ${COMMON_HEADERS_HXX} DESTINATION ${SALOME_INSTALL_HEADERS}) - diff --git a/src/MEDOP/gui/dialogs/DlgChangeUnderlyingMesh.ui b/src/MEDOP/gui/dialogs/DlgChangeUnderlyingMesh.ui index cad5ce3cb..f4bf310c5 100644 --- a/src/MEDOP/gui/dialogs/DlgChangeUnderlyingMesh.ui +++ b/src/MEDOP/gui/dialogs/DlgChangeUnderlyingMesh.ui @@ -6,10 +6,16 @@ 0 0 - 479 - 429 + 420 + 350 + + + 420 + 350 + + FORM diff --git a/src/MEDOP/gui/dialogs/DlgInterpolateField.cxx b/src/MEDOP/gui/dialogs/DlgInterpolateField.cxx new file mode 100644 index 000000000..1d49c9072 --- /dev/null +++ b/src/MEDOP/gui/dialogs/DlgInterpolateField.cxx @@ -0,0 +1,104 @@ +#include "DlgInterpolateField.hxx" +#include "DatasourceConstants.hxx" + +#include +#include +#include + +DlgInterpolateField::DlgInterpolateField(SALOME_AppStudyEditor * studyEditor, + QDialog * parent) + : GenericDialog(parent) +{ + ui.setupUi(this->getPanel()); + _meshId=-1; + _studyEditor = studyEditor; + + QDoubleValidator* precisionValidator = new QDoubleValidator(1e-15, 1e-1, 1, this); + precisionValidator->setNotation(QDoubleValidator::ScientificNotation); + this->ui.lineEditPrecision->setValidator(precisionValidator); + this->ui.lineEditPrecision->setText("1e-12"); + + QDoubleValidator* defaultValueValidator = new QDoubleValidator(this); + this->ui.lineEditDefaultValue->setValidator(defaultValueValidator); + this->ui.lineEditDefaultValue->setText("0"); + + QStringList intersectionTypes; + intersectionTypes << "Triangulation" << "Convex" << "Geometric2D" << "PointLocator" << "Barycentric" << "BarycentricGeo2D"; + this->ui.comboBoxIntersType->addItems(intersectionTypes); + + QStringList methods; + methods << "P0P0" << "P0P1" << "P1P0" << "P1P1" << "P2P0"; + this->ui.comboBoxMethod->addItems(methods); + + QStringList natures; + natures << "NoNature" << "ConservativeVolumic" << "Integral" << "IntegralGlobConstraint" << "RevIntegral"; + this->ui.comboBoxNature->addItems(natures); + + connect(this->ui.btnSelectMesh, SIGNAL(clicked()), this, SLOT(OnSelectMesh())); + this->setWindowTitle("Field interpolation"); + this->getPanel()->adjustSize(); + this->adjustSize(); +} + +/** This reset the dialog for a new selection */ +void DlgInterpolateField::setFieldId(int fieldId) { + _fieldId = fieldId; + _meshId=-1; + this->ui.txtMesh->setText(QString("")); +} +int DlgInterpolateField::getFieldId() { + return _fieldId; +} + +int DlgInterpolateField::getMeshId() { + return _meshId; +} + +double DlgInterpolateField::getPrecision() { + return this->ui.lineEditPrecision->text().toDouble(); +} + +double DlgInterpolateField::getDefaultValue() { + return this->ui.lineEditDefaultValue->text().toDouble(); +} + +bool DlgInterpolateField::getReverse() { + return this->ui.checkBoxReverse->isChecked(); +} + +std::string DlgInterpolateField::getIntersectionType() { + return this->ui.comboBoxIntersType->currentText().toStdString(); +} + +std::string DlgInterpolateField::getMethod() { + return this->ui.comboBoxMethod->currentText().toStdString(); +} + +std::string DlgInterpolateField::getFieldNature() { + return this->ui.comboBoxNature->currentText().toStdString(); +} + +void DlgInterpolateField::accept() { + if ( _meshId == -1 ) { + QMessageBox::warning(this, + tr("Data verification"), + tr("You must select a mesh in the explorer and clic the button Mesh")); + } + else { + GenericDialog::accept(); + emit inputValidated(); + } +} + +void DlgInterpolateField::OnSelectMesh() { + SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects(); + if ( listOfSObject->size() > 0 ) { + SALOMEDS::SObject_var soMesh = listOfSObject->at(0); + // _GBO_ TODO: we should test here if it is a mesh (attribute in + // the sobject) + _meshId = _studyEditor->getParameterInt(soMesh,OBJECT_ID); + const char * meshname = _studyEditor->getName(soMesh); + this->ui.txtMesh->setText(QString(meshname)); + } + +} diff --git a/src/MEDOP/gui/dialogs/DlgInterpolateField.hxx b/src/MEDOP/gui/dialogs/DlgInterpolateField.hxx new file mode 100644 index 000000000..b4220997c --- /dev/null +++ b/src/MEDOP/gui/dialogs/DlgInterpolateField.hxx @@ -0,0 +1,46 @@ +#ifndef _DlgInterpolateField_HXX +#define _DlgInterpolateField_HXX + +#include +#include "ui_DlgInterpolateField.h" +#include "GenericDialog.hxx" + +#include +#include "MEDOPGUIdialogs.hxx" + +class MEDOPGUI_DIALOGS_EXPORT DlgInterpolateField : public GenericDialog +{ + Q_OBJECT + +public: + DlgInterpolateField(SALOME_AppStudyEditor * studyEditor, QDialog *parent = 0); + + void setFieldId(int fieldId); + int getFieldId(); + int getMeshId(); + + double getPrecision(); + double getDefaultValue(); + bool getReverse(); + std::string getIntersectionType(); + std::string getMethod(); + std::string getFieldNature(); + +signals: + void inputValidated(); + +protected slots: + void OnSelectMesh(); + + private: + void accept(); + int _meshId; + + SALOME_AppStudyEditor * _studyEditor; + int _fieldId; + + Ui_DlgInterpolateField ui; // instance of the class defined in ui_dlgInterpolateField.hxx +}; + + +#endif // _DlgInterpolateField_HXX diff --git a/src/MEDOP/gui/dialogs/DlgInterpolateField.ui b/src/MEDOP/gui/dialogs/DlgInterpolateField.ui new file mode 100644 index 000000000..ea069b53d --- /dev/null +++ b/src/MEDOP/gui/dialogs/DlgInterpolateField.ui @@ -0,0 +1,655 @@ + + + DlgInterpolateField + + + + 0 + 0 + 550 + 450 + + + + + 0 + 0 + + + + + 550 + 450 + + + + FORM + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + Sans Serif + true + + + + SELECT_MESH + + + true + + + + + + + 7 + + + + + TARGET_MESH_GT + + + + + + + + + + + + + true + + + + MSG_EXPLORER + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + LABEL_PRECISION + + + + + + + true + + + + 0 + 0 + + + + + 225 + 16777215 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + LABEL_INTERSECTION_TYPE + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + LABEL_METHOD + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + LABEL_DEFAULT_VALUE + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + LABEL_REVERSE + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + LABEL_NATURE + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + diff --git a/src/MEDOP/gui/dialogs/GenericDialog.ui b/src/MEDOP/gui/dialogs/GenericDialog.ui index c18fc4a69..058f5bed7 100644 --- a/src/MEDOP/gui/dialogs/GenericDialog.ui +++ b/src/MEDOP/gui/dialogs/GenericDialog.ui @@ -1,49 +1,62 @@ - + + GenericDialog - - + + 0 0 - 400 - 300 + 260 + 164 - + + + 0 + 0 + + + DIALOG - - - 9 - - + + 6 + + 9 + - - - 0 - - + + 6 + + 0 + - - + + + + 0 + 0 + + + QFrame::StyledPanel - + QFrame::Raised - - + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -59,11 +72,11 @@ GenericDialog accept() - + 248 254 - + 157 274 @@ -75,11 +88,11 @@ GenericDialog reject() - + 316 260 - + 286 274 diff --git a/src/MEDOP/res/CMakeLists.txt b/src/MEDOP/res/CMakeLists.txt index 2ce2792ea..60a339ea8 100644 --- a/src/MEDOP/res/CMakeLists.txt +++ b/src/MEDOP/res/CMakeLists.txt @@ -22,6 +22,7 @@ ADD_SUBDIRECTORY(testfiles) SET(MED_RESOURCES_FILES datasource_add.png datasource_changeUnderlyingMesh.png + datasource_interpolateField.png datasource_expandfield.png datasource_field.png datasource_mesh.png @@ -37,4 +38,3 @@ SET(MED_RESOURCES_FILES workspace_save.png ) INSTALL(FILES ${MED_RESOURCES_FILES} DESTINATION ${SALOME_MED_INSTALL_RES_DATA}) - diff --git a/src/MEDOP/res/datasource_interpolateField.png b/src/MEDOP/res/datasource_interpolateField.png new file mode 100644 index 0000000000000000000000000000000000000000..97b7c97d35d37ace24486c24ee3c72186a8319e7 GIT binary patch literal 836 zcmV-K1H1f*P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i^(_ z2r~pc_}{Al00P8GL_t(2&rOm`PZLoXK)-M9o$0itw6v7cLZhuvAiPvCAdjHNC<~2B zP}GHSZ~O_ypWr`WVWNpKt_(&XF+L&+@=%Hhh>&7!OBta^OUumMdtEd!p7qID9UQoJ z7XSbd000COK{S}KJM5&aE4{X2B^v^mObG}f0U%(}27xFLQ3zckO(puh!P>SHp`HAp z>elP04yz_J0fqEmR{(&nCeHB)A_^{$32a^a))@V2E0sJa-N6f; z@%EwNaa$@jUsdt_#O%b`P~NQ+SPveR+GZa+PpKcE<%$(Y*P=lWc*c-F5Xy}td1vSzttXe zxtb#r7+G0JQShIC^jqKg18Z+`n?E-TxqVq#>er{*C!?rHwnnF~+3P>owHmoJGH#|f zlGxGzm~rGFRrp=5GBcZceVr{F(NfH!IQ%YWbIn0Z&y?9R`lhh>ajw!CrN_E!$~~mD zO4m}$?XmZ=6y>`_%Ey*uvPt@D-M?DpDr z<`UnQ9()lDWR#?T2N$6^LM6@t5s5tadEPUVC|_QBR@Z}yS`7d1Bfww4gg^4{nsQ+P O0000x literal 0 HcmV?d00001 diff --git a/src/MEDOP/res/testfiles/smooth_surface.med b/src/MEDOP/res/testfiles/smooth_surface.med new file mode 100644 index 0000000000000000000000000000000000000000..56d7e4d6d65a7a14ff08eca6b587ad30542db609 GIT binary patch literal 40797 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 literal 0 HcmV?d00001 diff --git a/src/MEDOP/res/testfiles/smooth_surface_and_field.med b/src/MEDOP/res/testfiles/smooth_surface_and_field.med new file mode 100644 index 0000000000000000000000000000000000000000..226ce3b216111215c1ea59651e5db10942314ce3 GIT binary patch literal 16209 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 Glm7wPf<%r0 literal 0 HcmV?d00001 diff --git a/src/MEDOP/tui/xmedpy/driver_pvis.py b/src/MEDOP/tui/xmedpy/driver_pvis.py index 51f40e9b6..e7ed30e0e 100644 --- a/src/MEDOP/tui/xmedpy/driver_pvis.py +++ b/src/MEDOP/tui/xmedpy/driver_pvis.py @@ -17,7 +17,7 @@ # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -# Author : Guillaume Boulant (EDF) +# Author : Guillaume Boulant (EDF) import MEDCoupling __mapTypeOfField2ParavisLabel={ @@ -39,7 +39,7 @@ def pvis_typeOfFieldLabel(typeOfField): try: return __mapTypeOfField2ParavisLabel[typeOfField] except IndexError, e: - return "UNCKNOWN" + return "UNKNOWN" def pvis_scalarmap(filename,meshname,fieldname,typeOfField,iteration=-1): """ @@ -47,22 +47,44 @@ def pvis_scalarmap(filename,meshname,fieldname,typeOfField,iteration=-1): load from a med file using the PARAVIS module. """ import pvsimple - + reader = pvsimple.MEDReader( FileName=filename ) - # For fiels defined on cells, it seems to be required to specify - # the type of fields + + representation = pvsimple.Show() if typeOfField == MEDCoupling.ON_CELLS: - reader.Groups = ["GROUP/%s/%s/No_Group"%(meshname,pvis_typeOfFieldLabel(typeOfField))] + representation.ColorArrayName = ("CELLS", fieldname) + data = reader.CellData + else: + representation.ColorArrayName = ("POINTS", fieldname) + data = reader.PointData + + # :TODO: Determine nb components + nb_cmp = 1 + mode = "Magnitude" # "Component" if nb_cmp > 1 - representation = pvsimple.GetDisplayProperties(reader) - representation.ColorArrayName = fieldname + # Get data range (mini/maxi) + for n in range(data.GetNumberOfArrays()): + if data.GetArray(n).GetName() == fieldname: + mini,maxi = data.GetArray(n).GetRange() - lookupTable = pvsimple.GetLookupTableForArray( - fieldname, 1, NanColor=[0.25, 0.0, 0.0], - RGBPoints=[25.0, 0.23, 0.30, 0.754, 245.0, 0.71, 0.016, 0.15], - VectorMode='Magnitude', ColorSpace='Diverging', ScalarRangeInitialized=1.0 ) - representation.LookupTable = lookupTable + stepvalue = (maxi-mini)/100. # 100 steps + # Build Lookup table + RGBPoints = [mini, 0.0, 0.0, 1.0, maxi, 1.0, 0.0, 0.0] + nb = int((maxi-mini)/stepvalue)-1 + Table = pvsimple.GetLookupTableForArray("", nb_cmp, VectorMode=mode, ColorSpace='HSV') + Table.Discretize = 1 + Table.NumberOfTableValues = nb + Table.RGBPoints = RGBPoints + + representation.Representation = 'Surface' + representation.LookupTable = Table + + # Build scalar bar + scalarbar = pvsimple.CreateScalarBar(LabelFormat = '%.1f',Title= "",LabelFontSize=12,Enabled=1,LookupTable=Table,TitleFontSize=12,LabelColor=[0.0, 0.0, 0.0],TitleColor=[0.0, 0.0, 0.0],) + pvsimple.SetActiveSource(reader) + pvsimple.GetRenderView().Representations.append(scalarbar) + pvsimple.SetActiveSource(reader) pvsimple.Render() return True @@ -78,7 +100,7 @@ def TEST_scalarmap(): properties.testFieldName, properties.testTypeOfField, properties.testFieldIt) - + if __name__ == "__main__": TEST_scalarmap() diff --git a/src/MEDOP/tui/xmedpy/fieldtools.py b/src/MEDOP/tui/xmedpy/fieldtools.py index 532e22a2e..6fa6c32d8 100644 --- a/src/MEDOP/tui/xmedpy/fieldtools.py +++ b/src/MEDOP/tui/xmedpy/fieldtools.py @@ -17,7 +17,7 @@ # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -# Author : Guillaume Boulant (EDF) +# Author : Guillaume Boulant (EDF) # # =================================================================== @@ -29,7 +29,7 @@ import xmed from xmed.fieldproxy import FieldProxy, newFieldProxy - + # =================================================================== # Operations on fields @@ -87,7 +87,7 @@ def status(local=True,remote=False): if len(fieldHandlerList) > 0: status+="(use 'f=get(id)' to get a field in the current context)" - + return status # For simpler typing, one can create a python command for status @@ -104,7 +104,7 @@ class ListFields(object): # remote metadata on the engine (MEDCouplingFieldDouble) are # displayed by the stat command. Otherwise, only the local # metadata are displayed. - + def __repr__(self): return status(self.__local, self.__remote) @@ -121,13 +121,13 @@ def load(medFileName=filepath): """ This function indicates that we want to use the fields from the specified med file. The fields meta-data are loaded in the engine - part of the module. To get a fieldproxy on a field, call the get + part of the module. To get a fieldproxy on a field, call the get function with the id of the required field. To display the whole list of fields loaded in the engine, type 'ls' (la verbose). """ xmed.dataManager.addDatasource(filepath) print status(local=False,remote=True) - + def get(fieldHandlerId): """ This return a field proxy on the field identified by the specified @@ -163,22 +163,31 @@ VIEWER_VISU = "VISU" VIEWER_PARAVIS = "PARAVIS" VIEWER_DEFAULT = VIEWER_PARAVIS -VIEWER_TMP_FILE = "/tmp/medop_viewer.med" +import tempfile def view_using_paravis(aFieldProxy): + temp = tempfile.NamedTemporaryFile(prefix="medop_viewer", suffix='.med', delete=False) + # __GBO__ TO BE IMPROVED: we used a tmp file in this first step of # development, but we should used at last a MEDCoupling corba # object (see how to use the stuff in PARAVIS/src/Plugins) - xmed.dataManager.saveFields(VIEWER_TMP_FILE, [aFieldProxy.id]) - + xmed.dataManager.saveFields(temp.name, [aFieldProxy.id]) + from xmed.driver_pvis import pvis_scalarmap - pvis_scalarmap(VIEWER_TMP_FILE, + pvis_scalarmap(temp.name, aFieldProxy.meshname, aFieldProxy.fieldname, aFieldProxy.type, aFieldProxy.iteration) + temp.close() +# def view_using_visu(aFieldProxy): + # No more used + raise Exception("view_using_visu: No more used") + + VIEWER_TMP_FILE = "/tmp/medop_viewer.med" + # __GBO__ TO BE IMPROVED: we used a tmp file in this first step of # development, but we should used at last a MEDCoupling corba # object (see how to use the stuff in PARAVIS/src/Plugins) @@ -200,7 +209,7 @@ def view_using_visu(aFieldProxy): iteration) if result is False: xmed.err("the field can't be displayed") - + def view(aFieldProxy, using=VIEWER_DEFAULT): """ This displays a 3D view of the field using VISU or PARAVIS, @@ -213,4 +222,4 @@ def view(aFieldProxy, using=VIEWER_DEFAULT): view_using_paravis(aFieldProxy) else: view_using_visu(aFieldProxy) - + -- 2.30.2