diff --git a/doc/salome/examples/filters_ex39.py b/doc/salome/examples/filters_ex39.py index 2d3c907d6..6a2ddd507 100644 --- a/doc/salome/examples/filters_ex39.py +++ b/doc/salome/examples/filters_ex39.py @@ -1,4 +1,4 @@ -# Elements of a domain +# "Elements of a domain" filter and "Renumber" hypothesis import salome, SMESH salome.salome_init() @@ -22,7 +22,15 @@ mesh = smesh.Mesh( boxes ) mesh.Segment(box1).NumberOfSegments( 5 ) # to have different nb of elements on the boxes mesh.Segment(box2).NumberOfSegments( 10 ) mesh.Quadrangle() -mesh.Hexahedron() +ijkAlgo = mesh.Hexahedron() + +# Use Renumber hypothesis to get hexahedra and nodes numbered like in a structured mesh. +# k axis of box1 will be ( 100,100,0 ) - ( 100,100,100 ) +# k axis of box2 will be ( 0,0,0 ) - (0,0,100), by default +v000 = geompy.MakeVertex( 100,100,0, theName='v000' ) # can use box sub-vertex or standalone one +v001 = geompy.GetVertexNearPoint( box1, geompy.MakeVertex(100,100,100), theName='v001') +ijkAlgo.Renumber([ smeshBuilder.BlockCS( box1, v000, v001 ) ]) + mesh.Compute() # Create filters with FT_ConnectedElements criterion by pointing a domain in different ways: diff --git a/doc/salome/gui/SMESH/images/block_renumber_hyp.png b/doc/salome/gui/SMESH/images/block_renumber_hyp.png new file mode 100644 index 000000000..4c610f787 Binary files /dev/null and b/doc/salome/gui/SMESH/images/block_renumber_hyp.png differ diff --git a/doc/salome/gui/SMESH/input/3d_meshing_hypo.rst b/doc/salome/gui/SMESH/input/3d_meshing_hypo.rst new file mode 100644 index 000000000..bef317c09 --- /dev/null +++ b/doc/salome/gui/SMESH/input/3d_meshing_hypo.rst @@ -0,0 +1,42 @@ +.. _a3d_meshing_hypo_page: + +********************* +3D Meshing Hypotheses +********************* + +.. _max_element_volume_hypo: + +Max Element Volume hypothesis +############################# + +**Max Element Volume** hypothesis is applied for meshing of 3D objects composing your geometrical object. Definition of this hypothesis consists of setting the **maximum volume** of 3D meshing elements (depending on the chosen meshing algorithm it can be **hexahedrons** or **tetrahedrons**), which will compose the mesh of these 3D objects. + +.. image:: ../images/a-maxelvolume.png + :align: center + +**See Also** a sample TUI Script of a :ref:`tui_max_element_volume` operation. + +.. _block_renumber_hypo: + +Renumber hypothesis +################### + +**Renumber** hypothesis is applied for meshing of 3D objects along with **Hexahedron (i,j,k)** algorithm. + +Order and hence numbering of hexahedral elements in the structured mesh generated by **Hexahedron (ijk)** algorithm depends on the order of faces in a block geometry. Nodes are not in a structured order, since geometrical edges and faces are discretized before construction of hexahedra. **Renumber** hypothesis allows for getting hexahedra and nodes ordered like in a structured grid. + +.. image:: ../images/block_renumber_hyp.png + :align: center + +**Renumber** hypothesis allows to define direction of **i, j** and **k** axes of a block. For that you specify two vertices of the block + +* **Vertex (0,0,0)** located at the origin of the block local coordinate system. +* **Vertex (0,0,1)** located at the end of **k** axis of the block. + +Axes **i** and **j** are found automatically using the right-hand rule. + +For blocks with edges parallel to the axes of global coordinate system, their local coordinate system by default is defined as having axes parallel to the global ones. So, for such blocks specification of vertices is optional, it is enough just to assign **Renumber** hypothesis. + +**See Also** a sample TUI Script of a :ref:`tui_block_renumber` operation. + + diff --git a/doc/salome/gui/SMESH/input/about_hypo.rst b/doc/salome/gui/SMESH/input/about_hypo.rst index df935f3d7..a4609d905 100644 --- a/doc/salome/gui/SMESH/input/about_hypo.rst +++ b/doc/salome/gui/SMESH/input/about_hypo.rst @@ -16,7 +16,7 @@ In **MESH** there are: * :ref:`a1d_meshing_hypo_page` for meshing of **edges** * :ref:`a2d_meshing_hypo_page` for meshing of **faces** -* :ref:`3D Hypothesis ` for meshing of **volumes** +* :ref:`a3d_meshing_hypo_page` for meshing of **volumes** * :ref:`additional_hypo_page` **Table of Contents** @@ -26,6 +26,6 @@ In **MESH** there are: 1d_meshing_hypo.rst 2d_meshing_hypo.rst - 3D: Max Element Volume hypothesis + 3d_meshing_hypo.rst additional_hypo.rst diff --git a/doc/salome/gui/SMESH/input/cartesian_algo.rst b/doc/salome/gui/SMESH/input/cartesian_algo.rst index 345872871..76b150e7e 100644 --- a/doc/salome/gui/SMESH/input/cartesian_algo.rst +++ b/doc/salome/gui/SMESH/input/cartesian_algo.rst @@ -59,6 +59,8 @@ This dialog allows to define * You can specify the **Coordinates** of grid nodes. **Insert** button inserts a node at **Step** distance (negative or positive) from the selected node. **Delete** button removes the selected node. Double click on a coordinate in the list enables its edition. **Note** that node coordinates are measured along directions of axes that can differ from the directions of the Global Coordinate System. * You can define the **Spacing** of a grid as an algebraic formula *f(t)* where *t* is a position along a grid axis normalized at [0.0,1.0]. *f(t)* must be non-negative at 0. <= *t* <= 1. The whole extent of geometry can be divided into ranges with their own spacing formulas to apply; a t varies between 0.0 and 1.0 within each **Range**. **Insert** button divides a selected range into two. **Delete** button adds the selected sub-range to the previous one. Double click on a range in the list enables edition of its right boundary. Double click on a function in the list enables its edition. + +.. note:: The actual grid spacing can slightly differ from the defined one. This is done for the best fitting of polyhedrons and for a better mesh quality on the interval boundaries. For example, if a constant **Spacing** is defined along an axis, the actual grid will fill the shape's dimension L along this axis with round number of equal cells: Spacing_actual = L / round( L / Spacing_defined ). * **Fixed Point** group allows defining an exact location of a grid node in the direction defined by spacing. The following cases are possible: diff --git a/doc/salome/gui/SMESH/input/max_element_volume_hypo.rst b/doc/salome/gui/SMESH/input/max_element_volume_hypo.rst deleted file mode 100644 index 5f835fc6b..000000000 --- a/doc/salome/gui/SMESH/input/max_element_volume_hypo.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _max_element_volume_hypo_page: - -***************************** -Max Element Volume hypothesis -***************************** - -**Max Element Volume** hypothesis is applied for meshing of 3D objects composing your geometrical object. Definition of this hypothesis consists of setting the **maximum volume** of 3D meshing elements (depending on the chosen meshing algorithm it can be **hexahedrons** or **tetrahedrons**), which will compose the mesh of these 3D objects. - -.. image:: ../images/a-maxelvolume.png - :align: center - -**See Also** a sample TUI Script of a :ref:`tui_max_element_volume` operation. - - diff --git a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.rst b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.rst index facc0fdc1..fd676a358 100644 --- a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.rst +++ b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.rst @@ -34,6 +34,10 @@ and hypotheses. * :ref:`tui_max_element_volume` hypothesis * :ref:`Viscous layers ` hypotheses +* Hexahedron (i,j,k) 3D algorithm + + * :ref:`tui_block_renumber` + * :ref:`tui_projection` * :ref:`Extrusion 3D ` algorithm * :ref:`Radial Prism ` algorithm @@ -136,6 +140,16 @@ Length from Edges :download:`Download this script <../../../examples/defining_hypotheses_ex07.py>` +.. _tui_block_renumber: + +Renumber 3D hypothesis +====================== + +.. literalinclude:: ../../../examples/filters_ex39.py + :language: python + +:download:`Download this script <../../../examples/filters_ex39.py>` + Defining Additional Hypotheses ############################## diff --git a/idl/SMESH_BasicHypothesis.idl b/idl/SMESH_BasicHypothesis.idl index 0f7edc5f6..a6b6882cc 100644 --- a/idl/SMESH_BasicHypothesis.idl +++ b/idl/SMESH_BasicHypothesis.idl @@ -1089,6 +1089,25 @@ module StdMeshers raises (SALOME::SALOME_Exception); }; + + /*! + * interface of "Renumber" hypothesis used by Hexahedron(ijk) algorithm + * to renumber mesh of a block to be structured-like + */ + struct BlockCS // Local coordinate system of a block + { + GEOM::GEOM_Object solid; + GEOM::GEOM_Object vertex000; + GEOM::GEOM_Object vertex001; + }; + typedef sequence blockcs_array; + + interface StdMeshers_BlockRenumber : SMESH::SMESH_Hypothesis + { + void SetBlocksOrientation( in blockcs_array blockCS ); + blockcs_array GetBlocksOrientation(); + }; + /*! * StdMeshers_SegmentAroundVertex_0D: interface of "SegmentAroundVertex" algorithm */ diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index fe0d107fb..1a5619a10 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -203,6 +203,7 @@ SET(SMESH_RESOURCES_FILES mesh_tree_hypo_projection_2d.png mesh_tree_hypo_projection_3d.png mesh_tree_hypo_quadratic.png + mesh_tree_hypo_renumber.png mesh_tree_hypo_segment.png mesh_tree_hypo_source_3d_shape.png mesh_tree_hypo_source_edge.png diff --git a/resources/StdMeshers.xml.in b/resources/StdMeshers.xml.in index d70cdd45e..8baf92e0a 100644 --- a/resources/StdMeshers.xml.in +++ b/resources/StdMeshers.xml.in @@ -226,6 +226,11 @@ icon-id ="mesh_hypo_length.png" dim ="3"/> + + @@ -390,11 +395,13 @@ input ="QUAD" output ="HEXA,PENTA" need-geom="false" + hypos ="BlockRenumber" opt-hypos="ViscousLayers" dim ="3"> Hexa_3D=Hexahedron(algo=smeshBuilder.Hexa) ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetFaces(1),SetFaces(2),SetMethod(),SetGroupName()) + BlockRenumber=Renumber(GetBlocksOrientation()) diff --git a/resources/mesh_tree_hypo_renumber.png b/resources/mesh_tree_hypo_renumber.png new file mode 100644 index 000000000..0d2714f90 Binary files /dev/null and b/resources/mesh_tree_hypo_renumber.png differ diff --git a/src/DriverCGNS/DriverCGNS_Read.cxx b/src/DriverCGNS/DriverCGNS_Read.cxx index 967628af2..fc1ba5120 100644 --- a/src/DriverCGNS/DriverCGNS_Read.cxx +++ b/src/DriverCGNS/DriverCGNS_Read.cxx @@ -1073,14 +1073,14 @@ Driver_Mesh::Status DriverCGNS_Read::Perform() PGetNodesFun getNodesFun = 0; if ( elemType == SMDSAbs_Face && meshDim == 3 ) switch ( axis ) { - case 0: getNodesFun = & TZoneData::IFaceNodes; - case 1: getNodesFun = & TZoneData::JFaceNodes; - case 2: getNodesFun = & TZoneData::KFaceNodes; + case 0: getNodesFun = & TZoneData::IFaceNodes; break; + case 1: getNodesFun = & TZoneData::JFaceNodes; break; + case 2: getNodesFun = & TZoneData::KFaceNodes; break; } else if ( elemType == SMDSAbs_Edge && meshDim == 2 ) switch ( axis ) { - case 0: getNodesFun = & TZoneData::IEdgeNodes; - case 1: getNodesFun = & TZoneData::JEdgeNodes; + case 0: getNodesFun = & TZoneData::IEdgeNodes; break; + case 1: getNodesFun = & TZoneData::JEdgeNodes; break; } if ( !getNodesFun ) { @@ -1103,14 +1103,14 @@ Driver_Mesh::Status DriverCGNS_Read::Perform() PGetNodesFun getNodesFun = 0; if ( elemType == SMDSAbs_Face ) switch ( axis ) { - case 0: getNodesFun = & TZoneData::IFaceNodes; - case 1: getNodesFun = & TZoneData::JFaceNodes; - case 2: getNodesFun = & TZoneData::KFaceNodes; + case 0: getNodesFun = & TZoneData::IFaceNodes; break; + case 1: getNodesFun = & TZoneData::JFaceNodes; break; + case 2: getNodesFun = & TZoneData::KFaceNodes; break; } else if ( elemType == SMDSAbs_Edge && meshDim == 2 ) switch ( axis ) { - case 0: getNodesFun = & TZoneData::IEdgeNodes; - case 1: getNodesFun = & TZoneData::JEdgeNodes; + case 0: getNodesFun = & TZoneData::IEdgeNodes; break; + case 1: getNodesFun = & TZoneData::JEdgeNodes; break; } if ( !getNodesFun ) { @@ -1129,9 +1129,9 @@ Driver_Mesh::Status DriverCGNS_Read::Perform() PAddElemFun addElemFun = 0; switch ( meshDim ) { - case 1: addElemFun = & add_BAR_2; - case 2: addElemFun = & add_QUAD_4; - case 3: addElemFun = & add_HEXA_8; + case 1: addElemFun = & add_BAR_2; break; + case 2: addElemFun = & add_QUAD_4; break; + case 3: addElemFun = & add_HEXA_8; break; } int elemID = meshInfo.NbElements(); const SMDS_MeshElement* elem = 0; diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index b7d9737dd..e71853f0f 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -1406,10 +1406,8 @@ bool SMESH_Mesh::HasDuplicatedGroupNamesMED() * \param [in] theAutoGroups - boolean parameter for creating/not creating * the groups Group_On_All_Nodes, Group_On_All_Faces, ... ; * the typical use is auto_groups=false. - * \param [in] theMinor - define the minor version (y, where version is x.y.z) of MED file format. - * The theMinor must be between 0 and the current minor version of MED file library. - * If theMinor is equal to -1, the minor version is not changed (default). - * The major version (x, where version is x.y.z) cannot be changed. + * \param [in] theVersion - define the minor (xy, where version is x.y.z) of MED file format. + * If theVersion is equal to -1, the minor version is not changed (default). * \param [in] meshPart - mesh data to export * \param [in] theAutoDimension - if \c true, a space dimension of a MED mesh can be either * - 1D if all mesh nodes lie on OX coordinate axis, or @@ -2026,6 +2024,16 @@ bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const return theShape.IsSame(_myMeshDS->ShapeToMesh() ); } +//======================================================================= +//function : GetShapeByEntry +//purpose : return TopoDS_Shape by its study entry +//======================================================================= + +TopoDS_Shape SMESH_Mesh::GetShapeByEntry(const std::string& entry) const +{ + return _callUp ? _callUp->GetShapeByEntry( entry ) : TopoDS_Shape(); +} + //============================================================================= /*! * diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index 27b54ed47..18c11c894 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -214,6 +214,9 @@ class SMESH_EXPORT SMESH_Mesh bool IsNotConformAllowed() const; bool IsMainShape(const TopoDS_Shape& theShape) const; + + TopoDS_Shape GetShapeByEntry(const std::string& entry) const; + /*! * \brief Return list of ancestors of theSubShape in the order * that lower dimension shapes come first @@ -342,6 +345,7 @@ class SMESH_EXPORT SMESH_Mesh virtual void HypothesisModified( int hypID, bool updateIcons )=0; virtual void Load()=0; virtual bool IsLoaded()=0; + virtual TopoDS_Shape GetShapeByEntry(const std::string& entry)=0; virtual ~TCallUp() {} }; void SetCallUp( TCallUp * upCaller ); diff --git a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx index a228b87e0..8256f8883 100644 --- a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx +++ b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx @@ -605,7 +605,7 @@ QString SMESHGUI_GenericHypothesisCreator::helpPage() const else if ( aHypType == "MaxElementArea") aHelpFileName = "2d_meshing_hypo.html#max-element-area-anchor"; else if ( aHypType == "MaxElementVolume") - aHelpFileName = "max_element_volume_hypo.html"; + aHelpFileName = "3d_meshing_hypo.html#max-element-volume-hypothesis"; else if ( aHypType == "StartEndLength") aHelpFileName = "1d_meshing_hypo.html#start-and-end-length-anchor"; else if ( aHypType == "Deflection1D") diff --git a/src/SMESHGUI/SMESH_msg_fr.ts b/src/SMESHGUI/SMESH_msg_fr.ts index 4c3783713..e0b412da3 100644 --- a/src/SMESHGUI/SMESH_msg_fr.ts +++ b/src/SMESHGUI/SMESH_msg_fr.ts @@ -29,7 +29,7 @@ MED_VX_FILES_FILTER - Fichiers MED %1 + fichiers MED %1 STL_FILES_FILTER @@ -133,11 +133,11 @@ COMPERR_ALGO_FAILED - L'algorithme n'a pas abouti + L'algorithme n'a pas abouti COMPERR_BAD_INPUT_MESH - Le maillage d'entrée est invalide + Le maillage d'entrée est invalide COMPERR_BAD_SHAPE @@ -149,7 +149,7 @@ COMPERR_MEMORY_PB - Problème d'affectation de la mémoire + Problème d'affectation de la mémoire COMPERR_OCC_EXCEPTION @@ -157,7 +157,7 @@ COMPERR_OK - Pas d'erreur + Pas d'erreur COMPERR_SLM_EXCEPTION @@ -181,16 +181,16 @@ COMPERR_NO_MESH_ON_SHAPE - Aucun élément n'est associé à une sous-shape + Aucun élément n'est associé à une sous-shape COMPERR_BAD_PARMETERS - Paramètres d'entrée invalides + Paramètres d'entrée invalides EDITERR_NO_MEDIUM_ON_GEOM - Certains nœuds milieux (affichés en magenta) ne sont pas placés - sur la géométrie pour éviter d'obtenir des élements distordus. + Certain nœuds milieux (affichés en magenta) ne sont pas placés + sur la géométrie pour éviter d'obtenir des élements distordus. SMESH_GEOM @@ -202,11 +202,11 @@ ELEMENT_ID - ID de l'élément + ID de l'élément ELEMENT_IDS - IDs de l'élément + IDs de l'élément FREE_BORDERS @@ -218,7 +218,7 @@ GEOM_BY_MESH_ELEM_SELECTION - Trouver la géométrie en choisissant l'élément de maillage + Trouver la géométrie en choisissant l'élément de maillage GLOBAL_ALGO @@ -302,7 +302,7 @@ MEN_COLORS - Paramètres d'affichage + Paramètres d'affichage MEN_COMPUTE @@ -446,7 +446,7 @@ MEN_DISP_ENT - Montrer l'entité + Montrer l'entité MEN_ELEM0D @@ -490,7 +490,7 @@ MEN_EDIT_GEOMGROUP_AS_GROUP - Editer un groupe en tant qu'autonome + Editer un groupe en tant qu'autonome MEN_EDIT_HYPO @@ -646,11 +646,11 @@ MEN_BARE_BORDER_VOLUME - Volumes sans éléments de peau + Volumes avec éléments de peau 2D manquants MEN_BARE_BORDER_FACE - Faces sans éléments de peau + Faces avec éléments de peau 1D manquants MEN_OVER_CONSTRAINED_VOLUME @@ -856,18 +856,6 @@ TOP_MEASURE_VOLUME Volume - - MEN_MEASURE_ANGLE - Angle - - - STB_MEASURE_ANGLE - Mesure de l'angle défini par 3 noœds - - - TOP_MEASURE_ANGLE - Angle - MEN_MOVE Déplacer un nœud @@ -886,11 +874,11 @@ MEN_NUM_ELEMENTS - Montrer les numéros des éléments + Montrer les n° des éléments MEN_NUM_NODES - Montrer les numéros des nœuds + Montrer les n° des nœuds MEN_ORIENT @@ -1014,7 +1002,7 @@ DISTRIBUTION_NB_ENT - Nombre d'entités + TODO MEN_REVOLUTION @@ -1074,7 +1062,7 @@ MEN_SKEW - Inclinaison d'angle + Inclinaison d'angle MEN_SMOOTH @@ -1122,7 +1110,7 @@ MEN_DUPLICATE_NODES - Dupliquer les nœuds et/ou les éléments + Dupliquer les nœuds MEN_TRANSF @@ -1162,11 +1150,7 @@ MEN_UNDERLYING_ELEMS - Groupe basé sur les nœuds d'autres groupes - - - MEN_FACE_GROUPS_BY_EDGES - Groupes de faces séparées par des arêtes vives + Groupe des entités sous-jacentes MEN_UPDATE @@ -1198,7 +1182,7 @@ MEN_SPLIT_TO_TETRA - Eclater en tétraèdres + Explosion en tétraèdres TOP_SPLIT_TO_TETRA @@ -1226,19 +1210,19 @@ MESHERS_FILE_CANT_OPEN - Impossible d'ouvrir le fichier de ressource + Impossible d'ouvrir le fichier de ressource MESHERS_FILE_CHECK_VARIABLE - Vérifier la variable d'environnement SMESH_MeshersList + Vérifier la variable d'environnement SMESH_MeshersList MESHERS_FILE_NO_VARIABLE - La variable d'environnement SMESH_MeshersList n'est pas définie + La variable d'environnement SMESH_MeshersList n'est pas définie MESH_IS_NOT_SELECTED - Il n'y a pas de maillage sélectionné. + Il n'y a pas de maillage sélectionné. Choisissez un maillage et essayez de nouveau @@ -1263,8 +1247,8 @@ Choisissez un maillage et essayez de nouveau GROUP_NAME_IS_EMPTY - Le nom du groupe n'est pas indiqué. -Indiquez le nom d'un nouveau groupe à créer ou choisissez un groupe existant. + Le nom du groupe n'est pas indiqué. +Indiquez le nom d'un nouveau groupe à créer ou choisissez un groupe existant. MESH_GEOM_GRP_CHOSEN @@ -1286,7 +1270,7 @@ Voulez-vous le convertir en un groupe autonome ? NON_SMESH_OBJECTS_SELECTED - Certains objets sélectionnés n'appartiennent pas au composant %1. + Certains objets sélectionnés n'appartiennent pas au composant %1. PREVIEW @@ -1294,7 +1278,7 @@ Voulez-vous le convertir en un groupe autonome ? SKEW_ELEMENTS - Inclinaison d'angle + Inclinaison d'angle SMESHGUI_INVALID_PARAMETERS @@ -1351,20 +1335,20 @@ Merci de les corriger, puis essayez de nouveau SMESH_ADD_HYPOTHESIS_TITLE - Attribution d'une hypothèse + Attribution d'une hypothèse SMESH_ADD_HYP_WRN - "%1" est attribué, mais : + "%1" est attribué, mais: SMESH_ADD_OCTA - Ajouter un prisme hexagonal + Ajouter un prisme hexagonale SMESH_ADD_OCTA_TITLE - Ajouter un prisme hexagonal + Ajouter un prisme hexagonale SMESH_ADD_POLYGON @@ -1452,7 +1436,7 @@ Merci de les corriger, puis essayez de nouveau SMESH_ADD_SUBMESH - Construction d'un sous-maillage + Construction d'un sous-maillage SMESH_ADD_TETRAS @@ -1520,7 +1504,7 @@ Merci de les corriger, puis essayez de nouveau SMESH_BAD_MESH_SELECTION - La sélection du maillage n'est pas valide + La sélection du maillage n'est pas valide SMESH_BOUNDARYEDGES @@ -1556,11 +1540,11 @@ Merci de les corriger, puis essayez de nouveau SMESH_BUT_CREATE - Créer + &Créer SMESH_BUT_DELETE - Effacer + Eff&acer SMESH_BUT_FILTER @@ -1572,7 +1556,7 @@ Merci de les corriger, puis essayez de nouveau SMESH_BUT_NEW - Nouveau + Nou&veau SMESH_BUT_NO @@ -1604,7 +1588,7 @@ Merci de les corriger, puis essayez de nouveau SMESH_CANT_ADD_HYP - Impossible d'attribuer "%1": + Impossible d'attribuer "%1": @@ -1634,7 +1618,7 @@ Merci de les corriger, puis essayez de nouveau SMESH_EVALUATE_SUCCEED - L'évaluation du maillage a réussi + L'évaluation du maillage a réussi SMESH_CONTENT @@ -1643,7 +1627,7 @@ Merci de les corriger, puis essayez de nouveau SMESH_CONTINUE_MESH_VISUALIZATION La système semble manquer de mémoire pour visualiser le maillage, -ce qui peut faire planter l'application. Voulez-vous continuer la visualisation ? +ce qui peut faire planter l'application. Voulez-vous continuer la visualisation ? SMESH_COORDINATES @@ -1703,7 +1687,7 @@ ce qui peut faire planter l'application. Voulez-vous continuer la visualisation SMESH_DRS_2 - Le fichier MED contient des rangées de nombre d'éléments superposées, donc les nombres de ce fichier ne sont pas pris en compte + Le fichier MED contient des rangées de nombre d'éléments superposées, donc les nombres de ce fichier ne sont pas pris en compte SMESH_DRS_3 @@ -1711,15 +1695,15 @@ ce qui peut faire planter l'application. Voulez-vous continuer la visualisation SMESH_DRS_4 - Le fichier MED contient des éléments en connectivité descendante. Ils n'ont pas été lu. + Le fichier MED contient des éléments en connectivité descendante. Ils n'ont pas été lu. SMESH_DRS_5 - Le fichier n'est pas correct, des données sont manquantes + Le fichier n'est pas correct, des données sont manquantes SMESH_DRS_EMPTY - Le fichier est vide, il n'y a rien à publier + Le fichier est vide, il n'y a rien à publier SMESH_DX @@ -1771,7 +1755,7 @@ ce qui peut faire planter l'application. Voulez-vous continuer la visualisation SMESH_EDIT_GEOMGROUP_AS_GROUP_TITLE - Editer un groupe en tant qu'autonome + Editer un groupe en tant qu'autonome SMESH_EDIT_HYPOTHESES @@ -1795,7 +1779,7 @@ ce qui peut faire planter l'application. Voulez-vous continuer la visualisation SMESH_ELEMENT_TYPE - Type de l'élément + Type de l'élément SMESH_ERROR @@ -1807,15 +1791,15 @@ ce qui peut faire planter l'application. Voulez-vous continuer la visualisation SMESH_EXPORT_FAILED - Impossible d'exporter le maillage. -Vérifiez l'espace disponible sur le disque. + Impossible d'exporter le maillage. +Vérifiez l'espace disponible sur le disque. SMESH_EXPORT_MED_DUPLICATED_GRP Il y a des noms de groupes dupliqués dans le maillage "%1". -Vous pouvez annuler l'exportation et les renommer, +Vous pouvez annuler l'exportation et les renommer, si non des noms de groupes au fichier MED résultant -ne correspondront pas aux noms de l'étude. +ne correspondront pas aux noms de l'étude. Voulez-vous continuer ? @@ -1831,7 +1815,7 @@ Voulez-vous continuer ? SMESH_EXPORT_MED_VERSION_COLLISION - La version MED du fichier "%1" n'est pas connue + La version MED du fichier "%1" n'est pas connue ou ne correspond pas à la version choisie. Ecraser le fichier ? @@ -1844,7 +1828,7 @@ Ecraser le fichier ? EXPORT_NOT_SUPPORTED - A l'export du maillage avec le nom "%1" vers %2 + A l'export du maillage avec le nom "%1" vers %2 %3 sera ignoré. Voulez-vous continuer ? @@ -1854,7 +1838,7 @@ Voulez-vous continuer ? SMESH_EXTRUSION_TO_DISTANCE - Distance de l'extrusion + Distance de l'extrusion SMESH_EXTRUSION_ALONG_VECTOR @@ -1874,7 +1858,7 @@ Voulez-vous continuer ? SMESH_FEATUREANGLE - Montrer l'angle + Montrer l'angle SMESH_FEATUREEDGES @@ -1975,24 +1959,24 @@ Voulez-vous le réécrire ou y ajouter les données exportées ? SMESH_HYP_1 - Il manque une hypothèse à l'algorithme + Il manque une hypothèse à l'algorithme SMESH_HYP_10 - L'hypothèse ne correspond pas aux dimensions du sous-maillage + L'hypothèse ne correspond pas aux dimensions du sous-maillage SMESH_HYP_11 - La géométrie n'est ni la géométrie principale, ni un de ses sous-objets, ni un groupe valide + La géométrie n'est ni la géométrie principale, ni un de ses sous-objets, ni un groupe valide SMESH_HYP_12 - La géométrie ne correspond pas à l'algorithme -Référez-vous à la documentation sur l'algorithme et la géométrie supportée + La géométrie ne correspond pas à l'algorithme +Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_HYP_13 - L'algorithme ne peut pas opérer sans géométrie + L'algorithme ne peut pas opérer sans géométrie SMESH_HYP_2 @@ -2000,23 +1984,23 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_HYP_3 - L'hypothèse contient une valeur de paramètre incorrecte + L'hypothèse contient une valeur de paramètre incorrecte SMESH_HYP_4 - Le sous-maillage n'est pas pris en compte parce qu'il y a un algorithme de dimension supérieure pour générer les éléments %1D + Le sous-maillage n'est pas pris en compte parce qu'il y a un algorithme de dimension supérieure pour générer les éléments %1D SMESH_HYP_5 - L'algorithme l'emporte sur les algorithme(s) de dimensions inférieures en générant les éléments de toutes les dimensions + L'algorithme l'emporte sur les algorithme(s) de dimensions inférieures en générant les éléments de toutes les dimensions SMESH_HYP_6 - Erreur critique inconnue lors de la définition de l'hypothèse + Erreur critique inconnue lors de la définition de l'hypothèse SMESH_HYP_7 - L'hypothèse ne correspond pas à la situation actuelle + L'hypothèse ne correspond pas à la situation actuelle SMESH_HYP_8 @@ -2024,7 +2008,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_HYP_9 - L'hypothèse d'une telle dimension est déjà attribuée à la géométrie + L'hypothèse d'une telle dimension est déjà attribuée à la géométrie SMESH_ID_DIAGONAL @@ -2048,7 +2032,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_INCORRECT_INPUT - Les données d'entrée ne sont pas correctes + Les données d'entrée ne sont pas correctes SMESH_INFORMATION @@ -2064,7 +2048,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_INSUFFICIENT_DATA - La valeur d'entrée n'est pas suffisante + La valeur d'entrée n'est pas suffisante SMESH_LABELS @@ -2160,11 +2144,11 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_NO_ELEMENTS_DETECTED - Il n'y a aucun élément à fusionner. + Il n'y a aucun élément à fusionner. SMESH_NO_NODES_DETECTED - Il n'y a aucun nœud à fusionner + Il n'y a aucun nœud à fusionner SMESH_MERGE_NODES @@ -2316,7 +2300,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_NO_MESH_VISUALIZATION - Il n'y a pas assez de mémoire pour visualiser le maillage + Il n'y a pas assez de mémoire pour visualiser le maillage SMESH_NUMBEROFCOLORS @@ -2324,7 +2308,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_NUMBEROFLABELS - Nombre d'étiquettes : + Nombre d'étiquettes : SMESH_NUMBEROFSTEPS @@ -2360,7 +2344,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_OPERATION_FAILED - L'opération n'a pas abouti + L'opération n'a pas abouti SMESH_OCTA @@ -2388,11 +2372,11 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_ORIENTATION_ELEMENTS_TITLE - Changer l'orientation + Changer l'orientation SMESH_OUTLINE_COLOR - Couleur de l'objet maillage + Couleur de l'objet maillage SMESH_PARAMETERS @@ -2508,7 +2492,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_PREFERENCES_SCALARBAR - Préférences de la barre d'échelle + Préférences de la barre d'échelle SMESH_PREF_SELECTION @@ -2524,7 +2508,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_PROPERTIES_SCALARBAR - Propriétés de la barre d'échelle + Propriétés de la barre d'échelle SMESH_PYRAMID @@ -2728,7 +2712,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_RM_HYP_WRN - "%1" n'est pas attribué, mais: + "%1" n'est pas attribué, mais: @@ -2737,11 +2721,11 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_ROTATION_TITLE - Rotation autour d'un axe + Rotation autour d'un axe SMESH_SCALARBAR - Barre d'échelle + Barre d'échelle SMESH_SEGMENTS @@ -2817,7 +2801,7 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_SCALE_TITLE - Transformation d'échelle + Transformation d'échelle SMESH_DUPLICATE_TITLE @@ -2829,19 +2813,19 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_SCALE_FACTOR - Facteur d'échelle : + Facteur d'échelle : SMESH_SCALE_FACTOR_X - Facteur d'échelle X : + Facteur d'échelle X : SMESH_SCALE_FACTOR_Y - Facteur d'échelle Y : + Facteur d'échelle Y : SMESH_SCALE_FACTOR_Z - Facteur d'échelle Z : + Facteur d'échelle Z : SMESH_TRANSPARENCY_OPAQUE @@ -2897,17 +2881,17 @@ Référez-vous à la documentation sur l'algorithme et la géométrie supportée SMESH_VISU_PROBLEM - Impossible de visualiser le maillage, probablement à cause d'un manque de mémoire + Impossible de visualiser le maillage, probablement à cause d'un manque de mémoire SMESH_VISU_PROBLEM_MEMORY - L'affichage du maillage a échoué, probablement à cause d'un manque de mémoire + L'affichage du maillage a échoué, probablement à cause d'un manque de mémoire SMESH_VISU_PROBLEM_CLEAR Impossible de visualiser le maillage, pas assez de la mémoire pour montrer le message, -donc toutes les données visuelles ont été supprimées pour ne pas planter l'application. -Enregistrez votre travail avant que l'application se plante +donc toutes les données visuelles ont été supprimées pour ne pas planter l'application. +Enregistrez votre travail avant que l'application se plante SMESH_VOLUME @@ -2931,7 +2915,7 @@ Enregistrez votre travail avant que l'application se plante SMESH_WRN_ALGORITHM_ALREADYEXIST - L'algorithme existe déjà + L'algorithme existe déjà SMESH_WRN_COMPUTE_FAILED @@ -2939,19 +2923,19 @@ Enregistrez votre travail avant que l'application se plante SMESH_WRN_EVALUATE_FAILED - Impossible d'évaluer le maillage + Impossible d'évaluer le maillage SMESH_WRN_EMPTY_NAME - Un nom vide n'est pas valide + Un nom vide n'est pas valide SMESH_WRN_HYPOTHESIS_ALREADYEXIST - L'hypothèse existe déjà + L'hypothèse existe déjà SMESH_WRN_HYPOTHESIS_NOTEXIST - L'hypothèse ou l'algorithme n'existent pas + L'hypothèse ou l'algorithme n'existent pas SMESH_WRN_MISSING_PARAMETERS @@ -2979,14 +2963,14 @@ Enregistrez votre travail avant que l'application se plante SMESH_WRN_SIZE_LIMIT_EXCEEDED - La présentation n'a pas été mise à jour automatiquement: + La présentation n'a pas été mise à jour automatiquement: la nouvelle taille du maillage (%1 éléments) dépasse la limite de taille actuelle (%2 éléments). Vérifiez la limite dans les préférences du module Mesh. SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED - La nouvelle taille de maillage (%1 éléments) dépasse l'actuelle taille limite de la mise à jour automatique (%2 éléments). + La nouvelle taille de maillage (%1 éléments) dépasse l'actuelle taille limite de la mise à jour automatique (%2 éléments). Les éléments suivants ne sont pas affichés: %3. Utilisez le menu "Visualiser une entité" pour les afficher. @@ -3021,27 +3005,27 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STATE_ALGO_MISSING - Il manque l'algorithme %3 %2D + Il manque l'algorithme %3 %2D STATE_HYP_BAD_GEOMETRY - L'algorithme %3 %2D "%1" est attribué à une géométrie qui ne convient pas + L'algorithme %3 %2D "%1" est attribué à une géométrie qui ne convient pas STATE_HYP_BAD_PARAMETER - Il y a un paramètre incorrect dans l'hypothèse %3 %2D de l'algorithme "%1" + Il y a un paramètre incorrect dans l'hypothèse %3 %2D de l'algorithme "%1" STATE_HYP_MISSING - L'hypothèse %4D manque à l'algorithme %3 %2D "%1" + L'hypothèse %4D manque à l'algorithme %3 %2D "%1" STATE_HYP_NOTCONFORM - L'algorithme %3 %2D "%1" produit un maillage non-conforme: l'hypothèse globale "Maillage non conforme autorisé" doit être cochée + L'algorithme %3 %2D "%1" produit un maillage non-conforme: l'hypothèse globale "Maillage non conforme autorisé" doit être cochée STB_ADV_INFO - Monter l'information de base sur le maillage + Monter l'information de base sur le maillage STB_ALL @@ -3081,7 +3065,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_COLORS - Paramètres d'affichage + Paramètres d'affichage STB_COMPUTE @@ -3113,7 +3097,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_CONV_TO_QUAD - Convertir vers/depuis quadratique + Convertir vers/de quadratique STB_2D_FROM_3D @@ -3213,7 +3197,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_EDIT_GEOMGROUP_AS_GROUP - Editer un groupe en tant qu'autonome + Editer un groupe en tant qu'autonome STB_EDIT_HYPO @@ -3345,11 +3329,11 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_MAX_ELEMENT_LENGTH_2D - Diamètre de l'élément 2D + Diamètre de l'élément 2D STB_MAX_ELEMENT_LENGTH_3D - Diamètre de l'élément 3D + Diamètre de l'élément 3D STB_IMPORT_MED @@ -3533,11 +3517,11 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_SCALAR_BAR - Barre d'échelle + Barre d'échelle STB_SCALAR_BAR_PROP - Propriétés de la barre d'échelle + Propriétés de la barre d'échelle STB_SELECTION @@ -3565,7 +3549,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_SKEW - Inclinaison d'angle + Inclinaison d'angle STB_SMOOTH @@ -3637,13 +3621,9 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_UNDERLYING_ELEMS - Créer les groupes d'entités à partir des groupes existants de dimensions supérieures + Créer les groupes d'entités à partir des groupes existants de dimensions supérieures - STB_FACE_GROUPS_BY_EDGES - Créer les groupes de faces séparées par des arêtes vives - - STB_UPDATE Mettre à jour @@ -3673,11 +3653,11 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TB_ADD - Barre d'ajout d'éléments + Barre d'ajout d'éléments TB_ADDNON - Barre d'ajout d'éléments non linéaires + Barre d'ajout d'éléments non linéaires TB_REM @@ -3717,7 +3697,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TB_HYPO - Barre d'hypothèses + Barre d'hypothèses TB_MESH @@ -3729,7 +3709,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TB_INFO - Barre d'information + Barre d'information TB_ADD1D @@ -3781,7 +3761,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TOP_COLORS - Paramètres d'affichage + Paramètres d'affichage TOP_COMPUTE @@ -3913,11 +3893,11 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TOP_EDIT_GEOMGROUP_AS_GROUP - Editer un groupe en tant qu'autonome + Editer un groupe en tant qu'autonome TOP_EDIT_HYPO - Editer l'hypothèse + Editer l'hypothèse TOP_EDIT_MESHSUBMESH @@ -4221,11 +4201,11 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TOP_SCALAR_BAR - Barre d'échelle + Barre d'échelle TOP_SCALAR_BAR_PROP - Propriétés de la barre d'échelle + Propriétés de la barre d'échelle TOP_SELECTION @@ -4253,7 +4233,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TOP_SKEW - Inclinaison d'angle + Inclinaison d'angle TOP_SMOOTH @@ -4325,11 +4305,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TOP_UNDERLYING_ELEMS - Créer les groupes d'entités à partir des groupes existants de dimensions supérieures - - - TOP_FACE_GROUPS_BY_EDGES - Créer les groupes de faces séparées par des arêtes vives + Créer les groupes d'entités à partir des groupes existants de dimensions supérieures TOP_UPDATE @@ -4349,7 +4325,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TOP_WHAT_IS - Information sur l'élément de maillage + Information sur l'élément de maillage TOP_WIRE @@ -4373,7 +4349,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. MEN_FILE_INFO - Information sur le fichier du maillage + Information du fichier MED SMESH_WRN_NO_APPROPRIATE_SELECTION @@ -4397,7 +4373,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. SMESH_ERR_NOT_SUPPORTED_FORMAT - Le format de fichier n'est pas supporté + Le format de fichier n'est pas supporté SMESH_ERR_UNKNOWN_IMPORT_ERROR @@ -4405,11 +4381,11 @@ Utilisez le menu "Visualiser une entité" pour les afficher. SMESH_IMPORT_ERRORS - L'importation s'est terminée avec des erreurs + L'importation s'est terminée avec des erreurs SMESH_DRS_SOME_EMPTY - Un ou plusieurs fichiers de maillage sont vides, les données n'ont pas été publiées + Un ou plusieurs fichiers de maillage sont vides, les données n'ont pas été publiées NO_MESH_SELECTED @@ -4437,7 +4413,7 @@ Utilisez le menu "Visualiser une entité" pour les afficher. SMESH_PREF_area_precision - Précision de l'aire + Précision de l'aire FULL_RECOMPUTE_QUESTION @@ -4454,8 +4430,8 @@ Voulez-vous recalculer le maillage entier pour rejeter les modifications ? SMESH_PRECISION_HINT -Il est possible de modifier la précision de la valeur d'entrée -avec le paramètre '%1' des préférences du module Mesh. +Il est possible de modifier la précision de la valeur d'entrée +avec le paramètre '%1' des préférences du module Mesh. REMOVE_ORPHAN_NODES_QUESTION @@ -4491,7 +4467,7 @@ avec le paramètre '%1' des préférences du module Mesh. DEP_OBJECT - L'objet sélectionné a été utilisé pour en créer un autre. + L'objet sélectionné a été utilisé pour en créer un autre. Il ne peut pas être supprimé. @@ -4511,17 +4487,19 @@ Il ne peut pas être supprimé. Trier les items enfants - MEN_BREAK_SHAPER_LINK - Rompre le lien + MEN_BREAK_SHAPER_LINK + Rompre le lien - STB_BREAK_SHAPER_LINK - Rupture du lien avec le modèle Shaper + STB_BREAK_SHAPER_LINK + Rupture du lien avec le modèle Shaper MSG_BREAK_SHAPER_LINK - Un lien avec le modèle Shaper pour l'objet %1 sera rompu. - Continuer? + + Un lien avec le modèle Shaper pour l'objet %1 sera rompu. + Continuer? + MSG_WARN_ON_GEOM_MODIF @@ -4592,7 +4570,7 @@ Il ne peut pas être supprimé. SMESHGUI_FaceGroupsSeparatedByEdgesDlg CAPTION - Groupes de faces séparées par des arêtes vives + Groupes de faces séparées par une arête vive. SHARP_ANGLE @@ -4608,7 +4586,7 @@ Il ne peut pas être supprimé. NB_GROUPS_CREATED - %1 groupe(s) de faces créé(s) + %1 groupes de faces créé(s) @@ -4657,12 +4635,12 @@ Il ne peut pas être supprimé. SMESHGUI NOT_A_VTK_VIEWER - Cette commande n'est disponible qu'à partir d'une fenêtre VTK. + Cette commande n'est disponible qu'à partir d'une fenêtre VTK. Ouvrez une fenêtre VTK et essayez de nouveau PREF_AUTO_GROUPS - Créer les groupes automatiquement pour l'export MED + Créer les groupes automatiquement pour l'export MED PREF_SHOW_WARN @@ -4694,7 +4672,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_FORGET_MESH_AT_HYP_MODIF - Ne pas charger le maillage du fichier d'étude à la modification d'une hypothèse + Ne pas charger le maillage du fichier d'étude à la modification d'une hypothèse PREF_AUTO_UPDATE @@ -4702,7 +4680,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_UPDATE_LIMIT - Limite de taille (nombre d'éléments) + Limite de taille (nombre d'éléments) PREF_UPDATE_LIMIT_NOLIMIT @@ -4786,7 +4764,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_ELEMENT_COLOR - Couleur d'élément + Couleur d'élément PREF_FILL @@ -4826,7 +4804,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_ELEM_INFO_GRP_DETAILS - Afficher les détails des groupes dans la page d'information de dl'élément + Afficher les détails des groupes dans la page d'information de dl'élément PREF_DUMP_BASE_INFO @@ -4834,7 +4812,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_DUMP_ELEM_INFO - Copier les informations de l'élément + Copier les informations de l'élément PREF_DUMP_ADD_INFO @@ -4854,7 +4832,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau SMESH_PREF_GROUP_PRECISION - Précision des champs d'entrée + Précision des champs d'entrée SMESH_PREF_GROUP_PREVIEW @@ -4938,7 +4916,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_OBJECT_COLOR - Couleur d'objet + Couleur d'objet PREF_OUTLINE @@ -4994,7 +4972,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_COLOR_0D - Couleur d'elément 0D + Couleur d'elément 0D PREF_SIZE_0D @@ -5014,7 +4992,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_BALL_SCALE - Facteur d'échelle des éléments particulaires + Facteur d'échelle des éléments particulaires PREF_WIDTH @@ -5141,7 +5119,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau COMPOUND_MESH - Maillage d'assemblage + Maillage d'assemblage CREATE_COMMON_GROUPS @@ -5184,7 +5162,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau SMESHGUI_ChangeOrientationDlg CAPTION - Modifier l'orientation + Modifier l'orientation @@ -5207,7 +5185,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau MEMORY_LACK - Problème d'allocation de mémoire + Problème d'allocation de mémoire COMPUTE_WARNING @@ -5273,12 +5251,12 @@ Ouvrez une fenêtre VTK et essayez de nouveau CLEAR_SUBMESH_QUESTION Des sous-maillages temporaires ont été créés sur la géométrie sélectionnée -au cours de l'opération de prévisualisation. +au cours de l'opération de prévisualisation. Voulez-vous supprimer toutes ces sous-maillages ? SMESH_WRN_NOTHING_PREVIEW - La prévisualisation du maillage n'est pas disponible + La prévisualisation du maillage n'est pas disponible SMESH_REJECT_MESH_ORDER @@ -5348,12 +5326,12 @@ Sélectionner des éléments et essayer encore SMESHGUI_ConvToQuadOp MESH_IS_NOT_SELECTED - Le maillage n'est pas sélectionné + Le maillage n'est pas sélectionné Indiquez-le et essayez de nouveau REF_IS_NULL - Aucun maillage valide n'est sélectionné + Aucun maillage valide n'est sélectionné @@ -5372,29 +5350,29 @@ Indiquez-le et essayez de nouveau ERROR_OF_CREATION - Une erreur interne s'est produite au cours de la création du motif + Une erreur interne s'est produite au cours de la création du motif Vérifiez la validité des informations données ERROR_OF_SAVING - Une erreur interne s'est produite au cours de l'enregistrement du motif. -Vérifiez l'espace de disque disponible et vos droits d'écriture dans ce fichier + Une erreur interne s'est produite au cours de l'enregistrement du motif. +Vérifiez l'espace de disque disponible et vos droits d'écriture dans ce fichier ERR_LOADF_CANT_PROJECT - Impossible d'appliquer la projection des nœuds vers la face + Impossible d'appliquer la projection des nœuds vers la face ERR_LOADF_CLOSED_FACE - Impossible de créer un motif à partir d'une face avec une arête de couture + Impossible de créer un motif à partir d'une face avec une arête de couture ERR_LOADF_NARROW_FACE - Impossible de créer un motif à partir d'une face étroite + Impossible de créer un motif à partir d'une face étroite ERR_LOADV_BAD_SHAPE - Il n'est possible de créer un motif que d'une coque fermée ou d'un solide avec 6 faces + Il n'est possible de créer un motif que d'une coque fermée ou d'un solide avec 6 faces ERR_LOADV_COMPUTE_PARAMS @@ -5402,7 +5380,7 @@ Vérifiez l'espace de disque disponible et vos droits d'écriture dans ce fichie ERR_LOAD_EMPTY_SUBMESH - Il n'y a pas d'éléments pour créer de motif + Il n'y a pas d'éléments pour créer de motif MESH_OR_SUBMESH @@ -5471,7 +5449,7 @@ Vérifiez l'espace de disque disponible et vos droits d'écriture dans ce fichie NO_SELECTED_GROUPS - Il n'y a aucun groupe sélectionné + Il n'y a aucun groupe sélectionné Choisissez un groupe et essayez de nouveau @@ -5546,11 +5524,11 @@ Choisissez un groupe et essayez de nouveau SMESHGUI_ExtrusionAlongPathDlg BAD_SHAPE_TYPE - La géométrie choisie en tant que chemin n'est pas une arête + La géométrie choisie en tant que chemin n'est pas une arête CANT_GET_TANGENT - Impossible d'obtenir la tangente pour un des nœuds du chemin + Impossible d'obtenir la tangente pour un des nœuds du chemin EXTRUSION_ALONG_PATH @@ -5566,7 +5544,7 @@ Choisissez un groupe et essayez de nouveau NO_ELEMENTS_SELECTED - Aucun élément de maillage n'est sélectionné pour l'extrusion + Aucun élément de maillage n'est sélectionné pour l'extrusion SELECTED_PATH_IS_NOT_EDGE @@ -5614,7 +5592,7 @@ Choisissez un groupe et essayez de nouveau WRONG_ANGLES_NUMBER - Le nombre d'angles doit correspondre au nombre des nœuds du chemin + Le nombre d'angles doit correspondre au nombre des nœuds du chemin @@ -5656,7 +5634,7 @@ Choisissez un groupe et essayez de nouveau SMESHGUI_FilterDlg BAD_SHAPE_NAME - Il n'y a pas d'objet géométrique "%1" dans l'étude actuelle + Il n'y a pas d'objet géométrique "%1" dans l'étude actuelle Sélectionnez un objet valide et essayez de nouveau @@ -5665,7 +5643,7 @@ Sélectionnez un objet valide et essayez de nouveau EDGES_TLT - Filtre d'arêtes + Filtre d'arêtes FACES_TLT @@ -5681,11 +5659,11 @@ Sélectionnez un objet valide et essayez de nouveau ELEM0D_TLT - Filtre d'éléments 0D + Filtre d'éléments 0D BALL_TLT - Filtre d'éléments particulaires + Filtre d'éléments particulaires SELECTION @@ -5697,27 +5675,27 @@ Sélectionnez un objet valide et essayez de nouveau SHAPE_IS_NOT_A_CYLINDER - "%1" n'est pas une face cylindrique + "%1" n'est pas une face cylindrique Sélectionnez une face cylindrique et essayez de nouveau SHAPE_IS_NOT_A_FACE - "%1" n'est pas une face + "%1" n'est pas une face Sélectionnez une face et essayez de nouveau SHAPE_IS_NOT_A_PLANE - "%1" n'est pas un plan + "%1" n'est pas un plan Sélectionnez un plan et essayez de nouveau FACE_ID_NOT_SELECTED - Aucune face de maillage n'est sélectionnée. + Aucune face de maillage n'est sélectionnée. Indiquez-la et essayez de nouveau NOT_FACE_ID - "%1" ne correspond à aucun ID valide d'une face du maillage. + "%1" ne correspond à aucun ID valide d'une face du maillage. Sélectionnez une face et essayez de nouveau @@ -5779,7 +5757,7 @@ Indiquez un nom non-vide ERROR_FILTER_NAME - Le nom du filtre n'est pas unique + Le nom du filtre n'est pas unique Indiquez un autre nom @@ -5789,27 +5767,27 @@ Vérifiez le nom du fichier de la librairie et ses propriétés ERROR_OF_ADDING - Une erreur interne s'est produite à l'addition d'un nouveau filtre dans la librairie. + Une erreur interne s'est produite à l'addition d'un nouveau filtre dans la librairie. Vérifiez la validité des informations données ERROR_OF_COPYING - Une erreur interne s'est produite à la copie d'un filtre depuis la librairie. + Une erreur interne s'est produite à la copie d'un filtre depuis la librairie. Vérifiez la validité des informations données ERROR_OF_DELETING - Une erreur interne s'est produite lors de la suppression d'un filtre depuis la librairie. + Une erreur interne s'est produite lors de la suppression d'un filtre depuis la librairie. Vérifiez la validité des informations données ERROR_OF_EDITING - Une erreur interne s'est produite à l'édition d'un filtre dans la librairie. + Une erreur interne s'est produite à l'édition d'un filtre dans la librairie. Vérifiez la validité des informations données ERROR_OF_SAVING - Une erreur s'est produite à la sauvegarde de la librairie des filtres. + Une erreur s'est produite à la sauvegarde de la librairie des filtres. Vérifiez la validité des informations données @@ -5834,7 +5812,7 @@ Vérifiez la validité des informations données LIBRARY_IS_NOT_LOADED - La librairie n'est pas ouverte. Ouvrez la librairie et essayez de nouveau + La librairie n'est pas ouverte. Ouvrez la librairie et essayez de nouveau LIB_NAME @@ -5846,7 +5824,7 @@ Vérifiez la validité des informations données NO_PERMISSION - Vous n'avez pas la permission d'écrire dans ce fichier + Vous n'avez pas la permission d'écrire dans ce fichier OPEN_LIBRARY @@ -5953,7 +5931,7 @@ Vérifiez la validité des informations données CONNECTED_ELEMS - Eléments d'un domaine + Eléments d'un domaine NODE_CONN_NUMBER @@ -5961,11 +5939,11 @@ Vérifiez la validité des informations données NUMBEROFNODESINELEMENT - Nombre de nœuds dans l'élément + Nombre de nœuds dans l'élément COPY_FROM - Copier depuis ... + Copier de... CRITERION @@ -5989,7 +5967,7 @@ Vérifiez la validité des informations données ERROR - La valeur du seuil n'est pas valide. + La valeur du seuil n'est pas valide. Entrez une valeur correcte et essayez de nouveau @@ -6050,11 +6028,11 @@ Entrez une valeur correcte et essayez de nouveau MAX_ELEMENT_LENGTH_2D - Diamètre d'éléments 2D + Diamètre d'éléments 2D MAX_ELEMENT_LENGTH_3D - Diamètre d'éléments 3D + Diamètre d'éléments 3D MINIMUM_ANGLE @@ -6071,7 +6049,7 @@ Entrez une valeur correcte et essayez de nouveau GROUPCOLOR_ERROR - Impossible d'identifier la couleur du groupe + Impossible d'identifier la couleur du groupe Entrez une valeur correcte et essayez de nouveau @@ -6092,7 +6070,7 @@ Entrez une valeur correcte et essayez de nouveau RANGE_OF_IDS - Liste d'IDs + Liste d'IDs REMOVE @@ -6140,7 +6118,7 @@ Entrez une valeur correcte et essayez de nouveau ENTITY_TYPE - Type de l'entité + Type de l'entité ENTITY_TYPE_0 @@ -6307,13 +6285,13 @@ Entrez une valeur correcte et essayez de nouveau DIFF_MESHES - Les arguments de l'opération ne sont pas indiqués correctement + Les arguments de l'opération ne sont pas indiqués correctement Les groupes correspondent à des maillages différents Donnez des arguments valides et essayez de nouveau DIFF_TYPES - Les arguments de l'opération ne sont pas indiqués correctement + Les arguments de l'opération ne sont pas indiqués correctement Les groupes contiennent des éléments de types différents Donnez des arguments valides et essayez de nouveau @@ -6324,7 +6302,7 @@ Indiquez un nom non-vide et essayez de nouveau INCORRECT_ARGUMENTS - Les arguments de l'opération ne sont pas indiqués + Les arguments de l'opération ne sont pas indiqués Indiquez-les et essayez de nouveau @@ -6363,11 +6341,11 @@ Indiquez-les et essayez de nouveau SMESHGUI_DimGroupDlg CREATE_GROUP_OF_UNDERLYING_ELEMS - Créer un groupe d'entités sous-jacentes + Créer un groupe d'entités sous-jacentes ELEMENTS_TYPE - Type d'éléments + Type d'éléments UNDERLYING_ENTITIES_ONLY @@ -6451,11 +6429,11 @@ Indiquez-les et essayez de nouveau SMESHGUI_MakeNodeAtPointOp INVALID_ID - L'ID du nœud est invalide + L'ID du nœud est invalide INVALID_MESH - Le maillage à modifier n'est pas sélectionné + Le maillage à modifier n'est pas sélectionné @@ -6551,12 +6529,36 @@ Indiquez-les et essayez de nouveau CREATE_ALL_GROUPS Créer tous les groupes définis dans la géométrie + + 3D: Tetrahedralization + 3D : Tétraèdres + + + 3D: Mapped Hexahedralization + 3D : Hexaèdres réglés + + + 3D: Free Hexahedralization + 3D : Hexaèdres libres + + + 2D: Triangulation + 2D : Triangles + + + 2D: Mapped Quadrangulation + 2D : Quadrangles réglés + + + 2D: Free Quadrangulation + 2D : Quadrangles libres + SMESHGUI_MeshOp ALGORITHM_WITHOUT_HYPOTHESIS - L'algorithme pour la dimension %1 est défini mais l'hypothèse ne l'est pas + L'algorithme pour la dimension %1 est défini mais l'hypothèse ne l'est pas EDIT_SUBMESH_QUESTION @@ -6565,22 +6567,22 @@ Voulez-vous éditer ce sous-maillage? SUBMESH_NOT_ALLOWED - Créer un sous-maillage ignoré par l'algorithme global n'a pas de sens "%1" + Créer un sous-maillage ignoré par l'algorithme global n'a pas de sens "%1" GEOMETRY_OBJECT_IS_NOT_DEFINED_MESH - La géométrie n'est pas définie. + La géométrie n'est pas définie. Voulez-vous créer un maillage vide sans algorithme ni hypothèse ? GEOMETRY_OBJECT_IS_NOT_DEFINED_SUBMESH - L'objet géométrique n'est pas défini. + L'objet géométrique n'est pas défini. Merci de le spécifier et essayer de nouveau GEOMETRY_OBJECT_IS_NULL - L'objet géométrique est nul + L'objet géométrique est nul HYPOTHESES_AND_ALGORITHMS_ARE_NOT_DEFINED @@ -6588,19 +6590,19 @@ Merci de le spécifier et essayer de nouveau HYPOTHESIS_WITHOUT_ALGORITHM - L'hypothèse est définie pour la dimension %1 mais l'algorithme n'est pas défini + L'hypothèse est définie pour la dimension %1 mais l'algorithme n'est pas défini IMPORTED_MESH - Le maillage n'est pas construit sur une géométrie + Le maillage n'est pas construit sur une géométrie INVALID_SUBSHAPE - L'objet géométrique n'est pas un sous-objet de l'objet maillé + L'objet géométrique n'est pas un sous-objet de l'objet maillé MESH_IS_NOT_DEFINED - Le maillage n'est pas défini + Le maillage n'est pas défini Spécifiez-le et essayez de nouveau @@ -6639,16 +6641,16 @@ Indiquez un nom valide et essayez de nouveau THERE_IS_NO_OBJECT_FOR_EDITING - Il n'y a pas d'objet à éditer. + Il n'y a pas d'objet à éditer. Sélectionnez un maillage ou un sous-maillage et essayez de nouveau CONCURRENT_SUBMESH_APPEARS -L'algorithme assigné a la même priorité que celui assigné à un +L'algorithme assigné a la même priorité que celui assigné à un sous-maillage adjacent; ainsi l'algorithme à utiliser pour mailler la -frontière partagée par les deux sous-maillages n'est pas défini. -Voulez-vous définir l'ordre de calcul des sous-maillages ? +frontière partagée par les deux sous-maillages n'est pas défini. +Voulez-vous définir l'ordre de calcul des sous-maillages ? @@ -6676,8 +6678,8 @@ Il est probable que le fichier est corrompu ou contient un autre type de motif ERROR_OF_OPENING - Il est impossible d'ouvrir le fichier. -Vérifiez s'il existe et si vous avez l'autorisation + Il est impossible d'ouvrir le fichier. +Vérifiez s'il existe et si vous avez l'autorisation ERROR_OF_READING @@ -6687,7 +6689,7 @@ Vérifiez le contenu du fichier ERR_READ_3D_COORD Il est impossible de charger le motif -Les coordonnées des points 3D sont en dehors de l'intervalle [0,1] +Les coordonnées des points 3D sont en dehors de l'intervalle [0,1] ERR_READ_BAD_INDEX @@ -6697,12 +6699,12 @@ Un index de point invalide a été detecté ERR_READ_BAD_KEY_POINT Il est impossible de charger le motif -Le point-clef n'est pas situé sur la frontière +Le point-clef n'est pas situé sur la frontière ERR_READ_ELEM_POINTS Il est impossible de charger le motif -Le nombre de points de l'élément est invalide +Le nombre de points de l'élément est invalide ERR_READ_NB_POINTS @@ -6712,12 +6714,12 @@ Il est impossible de lire le nombre de points dans le fichier ERR_READ_NO_ELEMS Il est impossible de charger le motif -Il ne contient pas d'éléments +Il ne contient pas d'éléments ERR_READ_NO_KEYPOINT Il est impossible de charger le motif -Le motif 2D n'a pas de point-clef +Le motif 2D n'a pas de point-clef ERR_READ_POINT_COORDS @@ -6779,7 +6781,7 @@ Il y a trop peu de points dans le fichier REVERSE - Inverser l'ordre des points-clefs + Inverser l'ordre des points-clefs VERTEX @@ -6798,7 +6800,7 @@ Il y a trop peu de points dans le fichier SMESHGUI_MeshTab ADD_HYPOTHESIS - Ajouter l'hypothèse + Ajouter l'hypothèse ALGORITHM @@ -6872,7 +6874,7 @@ Il y a trop peu de points dans le fichier SPLIT_METHOD - Diviser l'hexaèdre + Diviser l'hexaèdre SPLIT_HEX_TO_5_TETRA @@ -6950,7 +6952,7 @@ Il y a trop peu de points dans le fichier REVOLUTION_AROUND_AXIS - Révolution autour d'un axe + Révolution autour d'un axe TOTAL_ANGLE @@ -6958,7 +6960,7 @@ Il y a trop peu de points dans le fichier MEN_POINT_SELECT - De l'origine au point sélectionner + De l'origine au point sélectionner MEN_FACE_SELECT @@ -6989,39 +6991,39 @@ Il y a trop peu de points dans le fichier ERROR_1 - La frontière Libre1 n'est pas trouvée avec les nœuds sélectionnés + La frontière Libre1 n'est pas trouvée avec les nœuds sélectionnés ERROR_2 - La frontière Libre2 n'est pas trouvée avec les nœuds sélectionnés + La frontière Libre2 n'est pas trouvée avec les nœuds sélectionnés ERROR_3 - Les frontières Libres 1 et 2 n'ont pas été trouvées avec les nœuds sélectionnés + Les frontières Libres 1 et 2 n'ont pas été trouvées avec les nœuds sélectionnés ERROR_4 - Aucun chemin du premier au dernier nœud de la frontière n'est trouvé + Aucun chemin du premier au dernier nœud de la frontière n'est trouvé ERROR_5 - Il n'est pas permis de découper les volumes de bord! + Il n'est pas permis de découper les volumes de bord! ERROR_6 - Le nombre d'éléments sélectionnés est différent de chaque côté + Le nombre d'éléments sélectionnés est différent de chaque côté ERROR_7 - Les jeux d'éléments sont topologiquement différents ou les nœuds ne conviennent pas + Les jeux d'éléments sont topologiquement différents ou les nœuds ne conviennent pas ERROR_8 - Les nœuds du côté 1 soit ne sont pas connectés soit ne sont pas situés à la frontière du jeu d'éléments + Les nœuds du côté 1 soit ne sont pas connectés soit ne sont pas situés à la frontière du jeu d'éléments ERROR_9 - Les nœuds du côté 2 soit ne sont pas connectés soit ne sont pas situés à la frontière de l'élément + Les nœuds du côté 2 soit ne sont pas connectés soit ne sont pas situés à la frontière de l'élément FIRST_NODE_ID @@ -7138,11 +7140,11 @@ Il y a trop peu de points dans le fichier IS_PARAMETRIC - dans l'espace paramétrique + dans l'espace paramétrique ITERATION_LIMIT - Limite d'Itération + Limite d'Itération LAPLACIAN @@ -7451,13 +7453,13 @@ Il y a trop peu de points dans le fichier WRONG_GROUPS - Les groupes suivants n'ont pas été traités + Les groupes suivants n'ont pas été traités en raison de leurs types incompatibles: %1 SMESH_ERR_NO_INPUT_MESH - Aucun maillage, sous-maillage ou groupe source n'est indiqué + Aucun maillage, sous-maillage ou groupe source n'est indiqué SMESH_TOO_MANY_MESHES @@ -7469,19 +7471,19 @@ en raison de leurs types incompatibles: SMESH_ERR_NO_3D_ELEMENTS - L'objet source ne contient pas d'éléments 3D + L'objet source ne contient pas d'éléments 3D SMESH_ERR_NO_2D_ELEMENTS - L'objet source ne contient pas d'éléments 2D + L'objet source ne contient pas d'éléments 2D SMESH_ERR_MESH_NAME_NOT_SPECIFIED - Le nom du nouveau maillage n'est pas indiqué + Le nom du nouveau maillage n'est pas indiqué SMESH_ERR_GRP_NAME_NOT_SPECIFIED - Le nom du groupe n'est pas indiqué + Le nom du groupe n'est pas indiqué @@ -7596,7 +7598,7 @@ en raison de leurs types incompatibles: OBJECT_GROUP_EDGES - Groupe d'arêtes + Groupe d'arêtes OBJECT_GROUP_FACES @@ -7608,11 +7610,11 @@ en raison de leurs types incompatibles: OBJECT_GROUP_0DELEMS - Groupe d'éléments 0D + Groupe d'éléments 0D OBJECT_GROUP_BALLS - Groupe d'éléments particulaires + Groupe d'éléments particulaires OBJECT_GROUP_STANDALONE @@ -7679,7 +7681,7 @@ en raison de leurs types incompatibles: SAVE_INFO - Sauver l'info + Sauver l'info X_FROM_Y_ITEMS_SHOWN @@ -8091,7 +8093,7 @@ en raison de leurs types incompatibles: NUMBER_OF_THE_DOUBLE_EDGES - Nombre d'arêtes doubles + Nombre d'arêtes doubles FACES_INFO @@ -8234,30 +8236,30 @@ en raison de leurs types incompatibles: NEW_NAME - Nom du nouveau maillage + New Mesh Name NEW_GEOM - Nouvelle géométrie + New Geometry REUSE_HYPOTHESES - Réutiliser les hypothèses + Reuse Hypotheses COPY_ELEMENTS - Copier les éléments du maillage + Copy Mesh Elements OPERATION_FAILED - Les sous-objets du maillage n'ont pas tous été copiés + Not all mesh sub-objects have been copied SUBSHAPES_NOT_FOUND_MSG -Des sous-formes ne sont pas trouvées dans la géométrie. Elles sont listées -ci-dessous avec les objets de maillage qui sont marqués -en rouge dans le browser. +Some sub-shapes not found in the new geometry. They are listed +below along with dependent mesh objects that are marked with +with red in the Object Browser. @@ -8391,11 +8393,11 @@ en rouge dans le browser. NO_FACES - L'objet ne contient pas de faces + L'objet ne contient pas de faces NO_VOLUMES - L'objet ne contient pas de volumes + L'objet ne contient pas de volumes ZERO_SIZE_VECTOR @@ -8446,7 +8448,7 @@ en rouge dans le browser. ORIENTATIONS - Vecteurs d'orientation + Vecteurs d'orientation COLOR diff --git a/src/SMESHUtils/SMESH_MAT2d.cxx b/src/SMESHUtils/SMESH_MAT2d.cxx index 601fdd84d..fbbb0553f 100644 --- a/src/SMESHUtils/SMESH_MAT2d.cxx +++ b/src/SMESHUtils/SMESH_MAT2d.cxx @@ -1077,6 +1077,11 @@ namespace } } + else // 2D_mesh_QuadranglePreference_00/A1, bos20144.brep + { + continue; // bndSegs.size() == 1 + } + bndSegs[i].setBranch( branchID, bndSegsPerEdge ); // set to i-th and to the opposite bndSeg if ( bndSegs[i].hasOppositeEdge() ) branchEdges[ bndSegs[i].branchID() ].push_back( bndSegs[i]._edge ); diff --git a/src/SMESHUtils/SMESH_MeshAlgos.cxx b/src/SMESHUtils/SMESH_MeshAlgos.cxx index 14c781836..db6f5e690 100644 --- a/src/SMESHUtils/SMESH_MeshAlgos.cxx +++ b/src/SMESHUtils/SMESH_MeshAlgos.cxx @@ -317,7 +317,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() //================================================================================ /*! - * \brief Redistrubute element boxes among children + * \brief Redistribute element boxes among children */ //================================================================================ diff --git a/src/SMESHUtils/SMESH_Octree.cxx b/src/SMESHUtils/SMESH_Octree.cxx index 19473e226..85df6d93b 100644 --- a/src/SMESHUtils/SMESH_Octree.cxx +++ b/src/SMESHUtils/SMESH_Octree.cxx @@ -28,6 +28,9 @@ // #include "SMESH_Octree.hxx" +#include +#include + //=========================================================================== /*! * Constructor. limit must be provided at tree root construction. @@ -90,7 +93,12 @@ void SMESH_Octree::enlargeByFactor( Bnd_B3d* box, double factor ) const { gp_XYZ halfSize = 0.5 * ( box->CornerMax() - box->CornerMin() ); for ( int iDim = 1; iDim <= 3; ++iDim ) - halfSize.SetCoord( iDim, factor * halfSize.Coord( iDim )); + { + double newHSize = factor * halfSize.Coord( iDim ); + if ( newHSize < std::numeric_limits::min() ) + newHSize = Precision::Confusion(); // 1.e-7 + halfSize.SetCoord( iDim, newHSize ); + } box->SetHSize( halfSize ); } } diff --git a/src/SMESHUtils/SMESH_Tree.hxx b/src/SMESHUtils/SMESH_Tree.hxx index 37e92a18c..7be283943 100644 --- a/src/SMESHUtils/SMESH_Tree.hxx +++ b/src/SMESHUtils/SMESH_Tree.hxx @@ -31,6 +31,8 @@ #include "SMESH_Utils.hxx" +const double theEnlargeFactor = 1. + 1e-10; + //================================================================================ // Data limiting the tree height struct SMESH_TreeLimit { @@ -160,6 +162,7 @@ void SMESH_Tree::compute() { if ( !myLimit ) myLimit = new SMESH_TreeLimit(); myBox = buildRootBox(); + enlargeByFactor( myBox, theEnlargeFactor ); if ( myLimit->myMinBoxSize > 0. && maxSize() <= myLimit->myMinBoxSize ) myIsLeaf = true; else @@ -227,7 +230,7 @@ void SMESH_Tree::buildChildren() myChildren[i]->myLimit = myLimit; myChildren[i]->myLevel = myLevel + 1; myChildren[i]->myBox = newChildBox( i ); - enlargeByFactor( myChildren[i]->myBox, 1. + 1e-10 ); + enlargeByFactor( myChildren[i]->myBox, theEnlargeFactor ); if ( myLimit->myMinBoxSize > 0. && myChildren[i]->maxSize() <= myLimit->myMinBoxSize ) myChildren[i]->myIsLeaf = true; } diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index d6cb5b130..3c2e62f5d 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -116,13 +116,15 @@ public: // Get CORBA object corresponding to the SALOMEDS::SObject static CORBA::Object_var SObjectToObject( SALOMEDS::SObject_ptr theSObject ); // Get the SALOMEDS::SObject corresponding to a CORBA object - static SALOMEDS::SObject_ptr ObjectToSObject(CORBA::Object_ptr theObject); + static SALOMEDS::SObject_ptr ObjectToSObject( CORBA::Object_ptr theObject ); // Get the SALOMEDS::Study from naming service static SALOMEDS::Study_var getStudyServant(); // Get GEOM Object corresponding to TopoDS_Shape - GEOM::GEOM_Object_ptr ShapeToGeomObject (const TopoDS_Shape& theShape ); + static GEOM::GEOM_Object_ptr ShapeToGeomObject( const TopoDS_Shape& theShape ); // Get TopoDS_Shape corresponding to GEOM_Object - TopoDS_Shape GeomObjectToShape(GEOM::GEOM_Object_ptr theGeomObject); + static TopoDS_Shape GeomObjectToShape( GEOM::GEOM_Object_ptr theGeomObject ); + // Get GEOM Object by its study entry + static GEOM::GEOM_Object_ptr GetGeomObjectByEntry( const std::string& entry ); // Default constructor SMESH_Gen_i(); diff --git a/src/SMESH_I/SMESH_Gen_i_1.cxx b/src/SMESH_I/SMESH_Gen_i_1.cxx index 4c78e2316..d7d61bcaf 100644 --- a/src/SMESH_I/SMESH_Gen_i_1.cxx +++ b/src/SMESH_I/SMESH_Gen_i_1.cxx @@ -236,8 +236,8 @@ template static inline T* objectToServant( CORBA::Object_ptr theIOR GEOM::GEOM_Object_ptr SMESH_Gen_i::ShapeToGeomObject (const TopoDS_Shape& theShape ) { GEOM::GEOM_Object_var aShapeObj; - if ( !theShape.IsNull() ) { - GEOM_Client* aClient = GetShapeReader(); + if ( !theShape.IsNull() && mySMESHGen ) { + GEOM_Client* aClient = mySMESHGen->GetShapeReader(); TCollection_AsciiString IOR; if ( aClient && aClient->Find( theShape, IOR )) { @@ -257,9 +257,9 @@ GEOM::GEOM_Object_ptr SMESH_Gen_i::ShapeToGeomObject (const TopoDS_Shape& theSha TopoDS_Shape SMESH_Gen_i::GeomObjectToShape(GEOM::GEOM_Object_ptr theGeomObject) { TopoDS_Shape S; - if ( !theGeomObject->_is_nil() && !theGeomObject->_non_existent() ) + if ( mySMESHGen && !theGeomObject->_is_nil() && !theGeomObject->_non_existent() ) { - GEOM_Client* aClient = GetShapeReader(); + GEOM_Client* aClient = mySMESHGen->GetShapeReader(); GEOM::GEOM_Gen_var aGeomEngine = GetGeomEngine( theGeomObject ); if ( aClient && !aGeomEngine->_is_nil () ) S = aClient->GetShape( aGeomEngine, theGeomObject ); @@ -267,6 +267,25 @@ TopoDS_Shape SMESH_Gen_i::GeomObjectToShape(GEOM::GEOM_Object_ptr theGeomObject) return S; } +//================================================================================ +/*! + * \brief Get GEOM Object by its study entry + */ +//================================================================================ + +GEOM::GEOM_Object_ptr SMESH_Gen_i::GetGeomObjectByEntry( const std::string& entry ) +{ + GEOM::GEOM_Object_var go; + if ( !entry.empty() && mySMESHGen ) + { + SALOMEDS::SObject_wrap so = mySMESHGen->getStudyServant()->FindObjectID( entry.c_str() ); + CORBA::Object_var obj = SObjectToObject( so ); + go = GEOM::GEOM_Object::_narrow( obj ); + } + return go._retn(); +} + + //======================================================================= //function : publish //purpose : diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 97687ae79..8a4313de5 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -1212,6 +1212,9 @@ void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup if ( n->NbInverseElements() == 0 ) _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 ); + _impl->GetMeshDS()->Modified(); + _impl->SetIsModified( true ); + // Update Python script (theGroup must be alive for this) pyDump << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroupWithContents( " << theGroup << " )"; @@ -3432,12 +3435,17 @@ namespace { SMESH_Mesh_i* _mesh; TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {} - virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); } - virtual void HypothesisModified( int hypID, - bool updIcons) { _mesh->onHypothesisModified( hypID, - updIcons ); } - virtual void Load () { _mesh->Load(); } - virtual bool IsLoaded() { return _mesh->IsLoaded(); } + void RemoveGroup (const int theGroupID) override { _mesh->removeGroup( theGroupID ); } + void HypothesisModified( int hypID, + bool updIcons) override { _mesh->onHypothesisModified( hypID, + updIcons ); } + void Load () override { _mesh->Load(); } + bool IsLoaded() override { return _mesh->IsLoaded(); } + TopoDS_Shape GetShapeByEntry(const std::string& entry) override + { + GEOM::GEOM_Object_var go = SMESH_Gen_i::GetGeomObjectByEntry( entry ); + return SMESH_Gen_i::GeomObjectToShape( go ); + } }; } @@ -3773,7 +3781,7 @@ void SMESH_Mesh_i::ExportMED(const char* file, TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'" << file << "', " << "auto_groups=" <`) to export instead of the mesh autoDimension: if *True* (default), a space dimension of a MED mesh can be either @@ -2328,7 +2332,7 @@ class Mesh(metaclass = MeshMeta): #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility fileName = args[0] auto_groups = args[1] if len(args) > 1 else False - minor = args[2] if len(args) > 2 else -1 + version = args[2] if len(args) > 2 else -1 overwrite = args[3] if len(args) > 3 else True meshPart = args[4] if len(args) > 4 else None autoDimension = args[5] if len(args) > 5 else True @@ -2337,7 +2341,8 @@ class Mesh(metaclass = MeshMeta): z_tolerance = args[8] if len(args) > 8 else -1. # process keywords arguments auto_groups = kwargs.get("auto_groups", auto_groups) - minor = kwargs.get("minor", minor) + version = kwargs.get("version", version) + version = kwargs.get("minor", version) overwrite = kwargs.get("overwrite", overwrite) meshPart = kwargs.get("meshPart", meshPart) autoDimension = kwargs.get("autoDimension", autoDimension) @@ -2355,10 +2360,11 @@ class Mesh(metaclass = MeshMeta): z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance) self.mesh.SetParameters(Parameters) - self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, minor, overwrite, autoDimension, + self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, + version, overwrite, autoDimension, fields, geomAssocFields, z_tolerance) else: - self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension) + self.mesh.ExportMED(fileName, auto_groups, version, overwrite, autoDimension) def ExportSAUV(self, f, auto_groups=0): """ diff --git a/src/SMESH_SWIG/smesh_algorithm.py b/src/SMESH_SWIG/smesh_algorithm.py index 8ee3718a3..e9867dc4e 100644 --- a/src/SMESH_SWIG/smesh_algorithm.py +++ b/src/SMESH_SWIG/smesh_algorithm.py @@ -440,6 +440,18 @@ class Mesh_Algorithm: for i in reverseList: if isinstance( i, int ): s = geompy.GetSubShape(self.mesh.geom, [i]) + + #bos #20082 begin: + if s is None and type(self.geom) != geomBuilder.GEOM._objref_GEOM_Object: + # try to get the SHAPERSTUDY engine directly, as GetGen does not work because of + # simplification of access in geomBuilder: omniORB.registerObjref + from SHAPERSTUDY_utils import getEngine + gen = getEngine() + if gen: + aShapeOp = gen.GetIShapesOperations() + s = aShapeOp.GetSubShape(self.mesh.geom, i) + #bos #20082 end + if s.GetShapeType() != geomBuilder.GEOM.EDGE: raise TypeError("Not EDGE index given") resList.append( i ) diff --git a/src/StdMeshers/CMakeLists.txt b/src/StdMeshers/CMakeLists.txt index 2947ada60..3f7dc1af7 100644 --- a/src/StdMeshers/CMakeLists.txt +++ b/src/StdMeshers/CMakeLists.txt @@ -62,7 +62,9 @@ SET(_link_LIBRARIES ${GEOM_GEOMUtils} SMESHimpl SMESHDS + SMESHUtils ${TBB_LIBS} + ${Boost_LIBRARIES} ) IF(SALOME_SMESH_ENABLE_MEFISTO) @@ -130,6 +132,7 @@ SET(StdMeshers_HEADERS StdMeshers_QuadFromMedialAxis_1D2D.hxx StdMeshers_PolygonPerFace_2D.hxx StdMeshers_PolyhedronPerSolid_3D.hxx + StdMeshers_BlockRenumber.hxx ) IF(SALOME_SMESH_ENABLE_MEFISTO) @@ -196,6 +199,7 @@ SET(StdMeshers_SOURCES StdMeshers_QuadFromMedialAxis_1D2D.cxx StdMeshers_PolygonPerFace_2D.cxx StdMeshers_PolyhedronPerSolid_3D.cxx + StdMeshers_BlockRenumber.cxx ) IF(SALOME_SMESH_ENABLE_MEFISTO) diff --git a/src/StdMeshers/StdMeshers_BlockRenumber.cxx b/src/StdMeshers/StdMeshers_BlockRenumber.cxx new file mode 100644 index 000000000..bc2e63a43 --- /dev/null +++ b/src/StdMeshers/StdMeshers_BlockRenumber.cxx @@ -0,0 +1,324 @@ +// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : StdMeshers_BlockRenumber.cxx +// Author : Edward AGAPOV, OCC +// Module : SMESH + +#include "StdMeshers_BlockRenumber.hxx" + +#include "SMDS_EdgePosition.hxx" +#include "SMDS_FacePosition.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESHDS_SubMesh.hxx" +#include "SMESH_Algo.hxx" +#include "SMESH_Mesh.hxx" +#include "SMESH_MesherHelper.hxx" +#include "SMESH_TryCatch.hxx" + +#include +#include +#include +#include + +#include +#include + +//============================================================================= +/*! + * Constructor + */ +//============================================================================= + +StdMeshers_BlockRenumber::StdMeshers_BlockRenumber(int hypId, SMESH_Gen * gen) + :SMESH_Hypothesis(hypId, gen) +{ + _name = "BlockRenumber"; + _param_algo_dim = 3; // is used by StdMeshers_Hexa_3D and StdMeshers_CompositeHexa_3D +} + +//================================================================================ +/*! + * \brief Set local CS of blocks + */ +//================================================================================ + +void StdMeshers_BlockRenumber::SetBlocksOrientation( std::vector< StdMeshers_BlockCS > & blockCS ) +{ + if ( _blockCS != blockCS ) + { + NotifySubMeshesHypothesisModification(); + _blockCS.swap( blockCS ); + _solids2vertices.Clear(); + } +} + +//================================================================================ +/* + * Return true and vertices if block orientation is defined for a given solid + */ +//================================================================================ + +bool StdMeshers_BlockRenumber::IsSolidIncluded( SMESH_Mesh& mesh, + const TopoDS_Shape& solid, + TopoDS_Vertex& vertex000, + TopoDS_Vertex& vertex001 ) const +{ + bool result = false; + vertex000.Nullify(); + vertex001.Nullify(); + + if ( _solids2vertices.IsEmpty() ) + { + StdMeshers_BlockRenumber* me = const_cast(this); + for ( StdMeshers_BlockCS& bcs : me->_blockCS ) + { + TopoDS_Shape so = mesh.GetShapeByEntry( bcs._solid ); + TopoDS_Shape s000 = mesh.GetShapeByEntry( bcs._vertex000 ); + TopoDS_Shape s001 = mesh.GetShapeByEntry( bcs._vertex001 ); + TopoDS_Vertex v000 = StdMeshers_RenumberHelper::GetVertexAtPoint( so, s000 ); + TopoDS_Vertex v001 = StdMeshers_RenumberHelper::GetVertexAtPoint( so, s001 ); + if ( !v000.IsNull() && !v001.IsNull() ) + { + me->_solids2vertices.Bind( so, std::make_pair( v000, v001 )); + if ( so.IsSame( solid )) + { + result = true; + vertex000 = v000; + vertex001 = v001; + } + } + } + } + else if ( !solid.IsNull() ) + { + if (( result = _solids2vertices.IsBound( solid ))) + { + auto vvPairPtr = _solids2vertices.Seek( solid ); + vertex000 = vvPairPtr->first; + vertex001 = vvPairPtr->second; + } + } + return result; +} + +//======================================================================= +//function : CheckHypothesis +//purpose : +//======================================================================= + +SMESH_ComputeErrorPtr StdMeshers_BlockRenumber::CheckHypothesis(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape) const +{ + SMESH_Comment errorTxt; + for ( size_t i = 0; i < _blockCS.size() && errorTxt.empty(); ++i ) + { + TopoDS_Shape solid = aMesh.GetShapeByEntry( _blockCS[i]._solid ); + TopoDS_Shape v000 = aMesh.GetShapeByEntry( _blockCS[i]._vertex000 ); + TopoDS_Shape v001 = aMesh.GetShapeByEntry( _blockCS[i]._vertex001 ); + v000 = StdMeshers_RenumberHelper::GetVertexAtPoint( solid, v000 ); + v001 = StdMeshers_RenumberHelper::GetVertexAtPoint( solid, v001 ); + + if ( solid.IsNull() || solid.ShapeType() != TopAbs_SOLID ) + errorTxt << "Can't find a SOLID by entry '" << _blockCS[i]._solid << "'"; + else if ( v000.IsNull() || v000.ShapeType() != TopAbs_VERTEX ) + errorTxt << "Can't find a VERTEX by entry '" << _blockCS[i]._vertex000 << "'"; + else if ( v001.IsNull() || v001.ShapeType() != TopAbs_VERTEX ) + errorTxt << "Can't find a VERTEX by entry '" << _blockCS[i]._vertex001 << "'"; + else if ( !SMESH_MesherHelper::IsSubShape( v000, solid )) + errorTxt << "VERTEX '" << _blockCS[i]._vertex001 << "' does not belong to SOLID '" + << _blockCS[i]._solid << "'"; + else if ( !SMESH_MesherHelper::IsSubShape( v001, solid )) + errorTxt << "VERTEX '" << _blockCS[i]._vertex001 << "' does not belong to SOLID '" + << _blockCS[i]._solid << "'"; + else if ( SMESH_MesherHelper::Count( solid, TopAbs_VERTEX, true ) == 8 && + SMESH_MesherHelper::GetCommonAncestor( v000, v001, aMesh, TopAbs_EDGE ).IsNull() ) + errorTxt << "Vertices '" << _blockCS[i]._vertex000 << "' and '" << _blockCS[i]._vertex001 + << "' are not connected by an edge"; + } + + SMESH_ComputeErrorPtr error; + if ( !errorTxt.empty() ) + { + error = SMESH_ComputeError::New( COMPERR_BAD_PARMETERS, + SMESH_Comment("Renumber hypothesis: ") << errorTxt ); + } + return error; +} + +//======================================================================= +//function : StdMeshers_RenumberHelper +//purpose : constructor +//======================================================================= + +StdMeshers_RenumberHelper::StdMeshers_RenumberHelper( SMESH_Mesh& mesh, + const StdMeshers_BlockRenumber* hyp) + : _mesh( &mesh ), _hyp( hyp ), _newOldNodes( 2, nullptr ) +{ +} + +//======================================================================= +//function : GetVertex000 +//purpose : Find default vertex at (0,0,0) local position +//======================================================================= + +TopoDS_Vertex StdMeshers_RenumberHelper::GetVertex000( const TopTools_MapOfShape& cornerVertices ) +{ + TopoDS_Vertex v000; + if ( cornerVertices.Extent() < 8 ) + return TopoDS_Vertex(); + + double minVal = DBL_MAX, minX = DBL_MAX, val; + for ( auto it = cornerVertices.cbegin(); it != cornerVertices.cend(); ++it ) + { + gp_Pnt P = BRep_Tool::Pnt( TopoDS::Vertex( *it )); + val = P.X() + P.Y() + P.Z(); + if ( val < minVal || ( val == minVal && P.X() < minX )) + { + v000 = TopoDS::Vertex( *it ); + minVal = val; + minX = P.X(); + } + } + return v000; +} + +//======================================================================= +//function : GetVertex000 +//purpose : Find default vertex at (0,0,0) local position +//======================================================================= + +TopoDS_Vertex StdMeshers_RenumberHelper::GetVertexAtPoint( const TopoDS_Shape& solid, + const TopoDS_Shape& point ) +{ + if ( !solid.IsNull() && !point.IsNull() && point.ShapeType() == TopAbs_VERTEX ) + { + gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( point )); + double tol = Precision::Confusion(); + for ( TopExp_Explorer exp( solid, TopAbs_VERTEX ); exp.More(); exp.Next() ) + { + const TopoDS_Vertex& v = TopoDS::Vertex( exp.Current() ); + if ( v.IsSame( point ) || p.IsEqual( BRep_Tool::Pnt( v ), tol )) + return v; + } + } + return TopoDS_Vertex(); +} + +//================================================================================ +/* + * Create a copy of an old node and remember this couple of nodes for replacement + */ +//================================================================================ + +void StdMeshers_RenumberHelper::AddReplacingNode( const SMDS_MeshNode* & oldNode ) +{ + SMESHDS_Mesh* mesh = _mesh->GetMeshDS(); + SMESH_NodeXYZ oldXYZ = oldNode; + SMDS_MeshNode* newNode = mesh->AddNode( oldXYZ.X(), oldXYZ.Y(), oldXYZ.Z() ); + _newOldNodes.front() = newNode; + _newOldNodes.back() = oldNode; + _nodesToMerge.push_back( _newOldNodes ); + oldNode = newNode; + + int shapeID = oldXYZ->GetShapeID(); + const TopoDS_Shape& shape = mesh->IndexToShape( shapeID ); + if ( !shape.IsNull() ) + switch ( shape.ShapeType() ) + { + case TopAbs_FACE: + if ( SMDS_FacePositionPtr pos = oldXYZ->GetPosition() ) + mesh->SetNodeOnFace( newNode, shapeID, pos->GetUParameter(), pos->GetVParameter() ); + break; + case TopAbs_EDGE: + if ( SMDS_EdgePositionPtr pos = oldXYZ->GetPosition() ) + mesh->SetNodeOnEdge( newNode, shapeID, pos->GetUParameter() ); + break; + case TopAbs_VERTEX: + mesh->SetNodeOnVertex( newNode, shapeID ); + break; + default: + mesh->SetNodeInVolume( newNode, shapeID ); + } +} + +//================================================================================ +/* + * Replace old nodes by new ones + */ +//================================================================================ + +void StdMeshers_RenumberHelper::DoReplaceNodes() +{ + SMESH_MeshEditor( _mesh ).MergeNodes( _nodesToMerge ); +} + +//============================================================================= +/*! + * Persistence + */ +//============================================================================= + +ostream & StdMeshers_BlockRenumber::SaveTo(ostream & save) +{ + boost::archive::text_oarchive archive( save ); + archive << *this; + + return save; +} + +//============================================================================= +/*! + * Persistence + */ +//============================================================================= + +istream & StdMeshers_BlockRenumber::LoadFrom(istream & load) +{ + SMESH_TRY; + + boost::archive::text_iarchive archive( load ); + archive >> *this; + + SMESH_CATCH( SMESH::doNothing ); + + return load; +} + +namespace boost { + namespace serialization { + + //======================================================================= + //function : serialize + //purpose : serialize StdMeshers_BlockCS + //======================================================================= + + template + void serialize(Archive & ar, StdMeshers_BlockCS & blockCS, const unsigned int version) + { + ar & blockCS._solid; + ar & blockCS._vertex000; + ar & blockCS._vertex001; + } + + } // namespace serialization +} // namespace boost diff --git a/src/StdMeshers/StdMeshers_BlockRenumber.hxx b/src/StdMeshers/StdMeshers_BlockRenumber.hxx new file mode 100644 index 000000000..f68b17ecd --- /dev/null +++ b/src/StdMeshers/StdMeshers_BlockRenumber.hxx @@ -0,0 +1,170 @@ +// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SMESH SMESH : implementation of SMESH idl descriptions +// File : StdMeshers_BlockRenumber.hxx +// Author : Edward AGAPOV, OCC +// Module : SMESH +// +#ifndef _SMESH_BlockRenumber_HXX_ +#define _SMESH_BlockRenumber_HXX_ + +#include "SMESH_StdMeshers.hxx" + +#include "SMESH_ComputeError.hxx" +#include "SMESH_Hypothesis.hxx" +#include "SMESH_MeshEditor.hxx" + +#include +#include +#include + +#include +#include + +class SMESH_Mesh; +class TopoDS_Shape; +class TopoDS_TShape; +class TopoDS_Vertex; + +// ========================================================= +struct StdMeshers_BlockCS // Local coordinate system of a block +{ + std::string _solid; + std::string _vertex000; + std::string _vertex001; + + bool operator==( const StdMeshers_BlockCS& other ) const + { + return ( _solid == other._solid && + _vertex000 == other._vertex000 && + _vertex001 == other._vertex001 ); + } +}; + +// ========================================================= +/*! + * \class 3D Hypothesis used by Hexahedron(ijk) algorithm + * to renumber mesh of a block to be structured-like + */ +// ========================================================= + +class STDMESHERS_EXPORT StdMeshers_BlockRenumber : public SMESH_Hypothesis +{ +public: + StdMeshers_BlockRenumber(int hypId, SMESH_Gen * gen); + + void SetBlocksOrientation( std::vector< StdMeshers_BlockCS > & blockCS ); + + const std::vector< StdMeshers_BlockCS > & GetBlocksOrientation() const { return _blockCS; } + + virtual std::ostream & SaveTo(std::ostream & save) override; + virtual std::istream & LoadFrom(std::istream & load) override; + + /*! + * \brief Initialize Fineness by the mesh built on the geometry + * \param theMesh - the built mesh + * \param theShape - the geometry of interest + * \retval bool - true if parameter values have been successfully defined + */ + bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape) override + { return false; } + + /*! + * \brief Initialize my parameter values by default parameters. + * \retval bool - true if parameter values have been successfully defined + */ + bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0) override + { return false; } + + public: + + /*! + * \brief Check validity of parameter + */ + SMESH_ComputeErrorPtr CheckHypothesis(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape) const; + + /*! + * \brief Return true and vertices if block orientation is defined for a given solid + */ + bool IsSolidIncluded( SMESH_Mesh& mesh, + const TopoDS_Shape& solid, + TopoDS_Vertex& vertex000, + TopoDS_Vertex& vertex001 ) const; + + private: + + // Persistence: define both input and output at once + friend class boost::serialization::access; + template void serialize( Archive & ar, const unsigned int version ) + { + ar & _blockCS; + } + + protected: + + std::vector< StdMeshers_BlockCS > _blockCS; + + typedef NCollection_DataMap< TopoDS_Shape, std::pair< TopoDS_Vertex, TopoDS_Vertex > > TSolid2VV; + TSolid2VV _solids2vertices; // shapes defined by _blockCS, non-persistent +}; + +// ========================================================= +/*! + * \brief Help in using StdMeshers_BlockRenumber + */ +class StdMeshers_RenumberHelper +{ +public: + + StdMeshers_RenumberHelper( SMESH_Mesh& mesh, + const StdMeshers_BlockRenumber* hyp); + /*! + * \brief Find default vertex at (0,0,0) local position + */ + static TopoDS_Vertex GetVertex000( const TopTools_MapOfShape& cornerVertices ); + + /*! + * \brief Find a vertex of a solid located at the given point + */ + static TopoDS_Vertex GetVertexAtPoint( const TopoDS_Shape& solid, const TopoDS_Shape& point ); + + /*! + * \brief Create a copy of an old node and remember this couple of nodes for replacement + */ + void AddReplacingNode( const SMDS_MeshNode* & oldNode ); + + /*! + * \brief Replace old nodes by new ones + */ + void DoReplaceNodes(); + +private: + + SMESH_Mesh* _mesh; + const StdMeshers_BlockRenumber* _hyp; + + SMESH_MeshEditor::TListOfListOfNodes _nodesToMerge; + std::list< const SMDS_MeshNode* > _newOldNodes; +}; + +#endif diff --git a/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx b/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx index 8f624c777..b3e420619 100644 --- a/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx +++ b/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx @@ -38,6 +38,8 @@ #include "SMESH_MeshAlgos.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_subMesh.hxx" +#include "StdMeshers_BlockRenumber.hxx" +#include "StdMeshers_FaceSide.hxx" #include "StdMeshers_ViscousLayers.hxx" #include @@ -61,6 +63,8 @@ #include #include #include +#include +#include using namespace std; @@ -180,6 +184,8 @@ public: //** Methods to find and orient faces of 6 sides of the box **// TChildIterator GetChildren() const { return TChildIterator( myChildren.begin(), myChildren.end()); } + bool Contain( const TopoDS_Vertex& vertex ) const { return mySides.Contain( vertex ); } + public: //** Loading and access to mesh **// //!< Load nodes of a mesh @@ -271,7 +277,7 @@ private: //================================================================================ StdMeshers_CompositeHexa_3D::StdMeshers_CompositeHexa_3D(int hypId, SMESH_Gen* gen) - :SMESH_3D_Algo(hypId, gen) + :SMESH_3D_Algo(hypId, gen), _blockRenumberHyp( nullptr ) { _name = "CompositeHexa_3D"; _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID); // 1 bit /shape type @@ -287,6 +293,7 @@ bool StdMeshers_CompositeHexa_3D::CheckHypothesis(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, Hypothesis_Status& aStatus) { + _blockRenumberHyp = nullptr; aStatus = HYP_OK; return true; } @@ -545,6 +552,163 @@ namespace return faceFound; } + //================================================================================ + /*! + * \brief Rearrange block sides according to StdMeshers_BlockRenumber hypothesis + */ + //================================================================================ + + bool arrangeForRenumber( list< _QuadFaceGrid >& blockSides, + const TopTools_MapOfShape& cornerVertices, + SMESH_Mesh* mesh, + TopoDS_Vertex& v000, + TopoDS_Vertex& v001 ) + { + if ( v000.IsNull() ) + { + // block CS is not defined; + // renumber only if the block has an edge parallel to an axis of global CS + + v000 = StdMeshers_RenumberHelper::GetVertex000( cornerVertices ); + } + + Bnd_B3d bbox; + for ( auto it = cornerVertices.cbegin(); it != cornerVertices.cend(); ++it ) + bbox.Add( BRep_Tool::Pnt( TopoDS::Vertex( *it ))); + double tol = 1e-5 * Sqrt( bbox.SquareExtent() ); + + // get block edges starting at v000 + + std::vector< const _FaceSide* > edgesAtV000; + std::vector< gp_Vec > edgeDir; + std::vector< int > iParallel; // 0 - none, 1 - X, 2 - Y, 3 - Z + TopTools_MapOfShape lastVertices; + for ( _QuadFaceGrid & quad: blockSides ) + { + for ( int iS = 0; iS < 4 && edgesAtV000.size() < 3; ++iS ) + { + const _FaceSide* side = & quad.GetSide( iS ); + TopoDS_Vertex v1 = side->FirstVertex(), v2 = side->LastVertex(); + if (( v1.IsSame( v000 ) && !lastVertices.Contains( v2 )) || + ( v2.IsSame( v000 ) && !lastVertices.Contains( v1 ))) + { + bool reverse = v2.IsSame( v000 ); + if ( reverse ) + std::swap( v1, v2 ); + lastVertices.Add( v2 ); + + edgesAtV000.push_back( side ); + + gp_Pnt pf = BRep_Tool::Pnt( v1 ); + gp_Pnt pl = BRep_Tool::Pnt( v2 ); + gp_Vec vec( pf, pl ); + edgeDir.push_back( vec ); + + iParallel.push_back( 0 ); + if ( !v001.IsNull() ) + { + if ( quad.IsComplex() ) + for ( _QuadFaceGrid::TChildIterator chIt = quad.GetChildren(); chIt.more(); ) + { + const _QuadFaceGrid& child = chIt.next(); + if ( child.GetSide( iS ).Contain( v001 )) + { + iParallel.back() = 3; + break; + } + } + else if ( side->Contain( v001 )) + iParallel.back() = 3; + } + else + { + bool isStraight = true; + std::list< TopoDS_Edge > edges; + for ( int iE = 0; true; ++iE ) + { + TopoDS_Edge edge = side->Edge( iE ); + if ( edge.IsNull() ) + break; + edges.push_back( edge ); + if ( isStraight ) + isStraight = SMESH_Algo::IsStraight( edge ); + } + // is parallel to a GCS axis? + if ( isStraight ) + { + int nbDiff = (( Abs( vec.X() ) > tol ) + + ( Abs( vec.Y() ) > tol ) + + ( Abs( vec.Z() ) > tol ) ); + if ( nbDiff == 1 ) + iParallel.back() = ( Abs( vec.X() ) > tol ) ? 1 : ( Abs( vec.Y() ) > tol ) ? 2 : 3; + } + else + { + TopoDS_Face nullFace; + StdMeshers_FaceSide fSide( nullFace, edges, mesh, true, true ); + edgeDir.back() = gp_Vec( pf, fSide.Value3d( reverse ? 0.99 : 0.01 )); + } + } + } + } + } + if ( std::accumulate( iParallel.begin(), iParallel.end(), 0 ) == 0 ) + return false; + + // find edge OZ and edge OX + const _FaceSide* edgeOZ = nullptr, *edgeOY = nullptr, *edgeOX = nullptr; + auto iZIt = std::find( iParallel.begin(), iParallel.end(), 3 ); + if ( iZIt != iParallel.end() ) + { + int i = std::distance( iParallel.begin(), iZIt ); + edgeOZ = edgesAtV000[ i ]; + int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() ); + int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() ); + if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 ) + std::swap( iE1, iE2 ); + edgeOX = edgesAtV000[ iE1 ]; + edgeOY = edgesAtV000[ iE2 ]; + } + else + { + for ( size_t i = 0; i < edgesAtV000.size(); ++i ) + { + if ( !iParallel[ i ] ) + continue; + int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() ); + int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() ); + if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 ) + std::swap( iE1, iE2 ); + edgeOZ = edgesAtV000[ iParallel[i] == 1 ? iE2 : iE1 ]; + edgeOX = edgesAtV000[ iParallel[i] == 1 ? i : iE1 ]; + edgeOY = edgesAtV000[ iParallel[i] == 1 ? iE1 : i ]; + break; + } + } + + if ( !edgeOZ || !edgeOX || !edgeOY ) + return false; + + TopoDS_Vertex v100 = edgeOX->LastVertex(); + if ( v100.IsSame( v000 )) + v100 = edgeOX->FirstVertex(); + + // Find the left quad, one including v000 but not v100 + + for ( auto quad = blockSides.begin(); quad != blockSides.end(); ++quad ) + { + if ( quad->Contain( v000 ) && !quad->Contain( v100 )) // it's a left quad + { + if ( quad != blockSides.begin() ) + blockSides.splice( blockSides.begin(), blockSides, quad ); + blockSides.front().SetBottomSide( *edgeOZ ); // edgeOY + + return true; + } + } + return false; + } + } // namespace //================================================================================ @@ -557,6 +721,7 @@ bool StdMeshers_CompositeHexa_3D::findBoxFaces( const TopoDS_Shape& shape, list< _QuadFaceGrid >& boxFaces, SMESH_Mesh& mesh, SMESH_ProxyMesh& proxyMesh, + bool& toRenumber, _QuadFaceGrid * & fBottom, _QuadFaceGrid * & fTop, _QuadFaceGrid * & fFront, @@ -609,6 +774,22 @@ bool StdMeshers_CompositeHexa_3D::findBoxFaces( const TopoDS_Shape& shape, for ( exp.Init( shape, TopAbs_FACE); exp.More(); exp.Next(), ++boxFace ) boxFace->Init( TopoDS::Face( exp.Current() ), proxyMesh ); } + + toRenumber = _blockRenumberHyp; + if ( toRenumber ) + { + TopoDS_Vertex v000, v001; + _blockRenumberHyp->IsSolidIncluded( mesh, shape, v000, v001 ); + + toRenumber = arrangeForRenumber( boxFaces, cornerVertices, &mesh, v000, v001 ); + + if ( toRenumber ) + { + mesh.GetMeshDS()->Modified(); + mesh.GetMeshDS()->CompactMesh(); // remove numbering holes + } + } + // ---------------------------------------- // Find out position of faces within a box // ---------------------------------------- @@ -686,8 +867,9 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh& theMesh, // Try to find 6 side faces // ------------------------- list< _QuadFaceGrid > boxFaceContainer; + bool toRenumber = false; _QuadFaceGrid *fBottom, *fTop, *fFront, *fBack, *fLeft, *fRight; - if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh, + if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh, toRenumber, fBottom, fTop, fFront, fBack, fLeft, fRight)) return false; @@ -711,6 +893,8 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh& theMesh, fRight ->ComputeIJK( COO_Y, COO_Z, /*x=*/1. ); fTop ->ComputeIJK( COO_X, COO_Y, /*z=*/1. ); + StdMeshers_RenumberHelper renumHelper( theMesh, _blockRenumberHyp ); + int x, xSize = fBottom->GetNbHoriSegments(*proxyMesh) + 1, X = xSize - 1; int y, ySize = fBottom->GetNbVertSegments(*proxyMesh) + 1, Y = ySize - 1; int z, zSize = fFront ->GetNbVertSegments(*proxyMesh) + 1, Z = zSize - 1; @@ -768,8 +952,23 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh& theMesh, gp_XYZ params; // normalized parameters of an internal node within the unit box - for ( x = 1; x < xSize-1; ++x ) + if ( toRenumber ) + for ( y = 0; y < ySize; ++y ) + { + vector< const SMDS_MeshNode* >& columnXy = columns[ colIndex( X, y )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( columnXy[ z ] ); + } + + for ( x = X-1; x > 0; --x ) { + if ( toRenumber ) + { + vector< const SMDS_MeshNode* >& columnX0 = columns[ colIndex( x, 0 )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( columnX0[ z ] ); + } + const double rX = x / double(X); for ( y = 1; y < ySize-1; ++y ) { @@ -788,6 +987,10 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh& theMesh, // points projections on horizontal faces pointsOnShapes[ SMESH_Block::ID_Fxy0 ] = fBottom->GetXYZ( x, y ); pointsOnShapes[ SMESH_Block::ID_Fxy1 ] = fTop ->GetXYZ( x, y ); + + if ( toRenumber ) + renumHelper.AddReplacingNode( column[ 0 ] ); + for ( z = 1; z < zSize-1; ++z ) // z loop { // compute normalized parameters of an internal node within the unit box @@ -832,16 +1035,35 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh& theMesh, //cout << "Params: ( "<< params.X()<<", "<& columnXY = columns[ colIndex( x, Y )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( columnXY[ z ] ); } - } + } // for ( x = X-1; x > 0; --x ) + + if ( toRenumber ) + for ( y = 0; y < ySize; ++y ) + { + vector< const SMDS_MeshNode* >& column0Y = columns[ colIndex( 0, y )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( column0Y[ z ] ); + } + + // faces no more needed, free memory boxFaceContainer.clear(); // ---------------- // Add hexahedrons // ---------------- - for ( x = 0; x < xSize-1; ++x ) { + for ( x = xSize-2; true; --x ) { for ( y = 0; y < ySize-1; ++y ) { vector< const SMDS_MeshNode* >& col00 = columns[ colIndex( x, y )]; vector< const SMDS_MeshNode* >& col10 = columns[ colIndex( x+1, y )]; @@ -850,11 +1072,22 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh& theMesh, for ( z = 0; z < zSize-1; ++z ) { // bottom face normal of a hexa mush point outside the volume - helper.AddVolume(col00[z], col01[z], col11[z], col10[z], - col00[z+1], col01[z+1], col11[z+1], col10[z+1]); + helper.AddVolume(col10[z], col11[z], col11[z+1], col10[z+1], + col00[z], col01[z], col01[z+1], col00[z+1]); } } + if ( x == 0) + break; + } + if ( toRenumber ) + renumHelper.DoReplaceNodes(); + + if ( _blockRenumberHyp ) + { + return error( _blockRenumberHyp->CheckHypothesis( theMesh, theShape )); + } + return true; } @@ -875,7 +1108,8 @@ bool StdMeshers_CompositeHexa_3D::Evaluate(SMESH_Mesh& theMesh, // ------------------------- list< _QuadFaceGrid > boxFaceContainer; _QuadFaceGrid *fBottom, *fTop, *fFront, *fBack, *fLeft, *fRight; - if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh, + bool toRenumber = false; + if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh, toRenumber, fBottom, fTop, fFront, fBack, fLeft, fRight)) return false; diff --git a/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx b/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx index 695624fe5..9a17e2b81 100644 --- a/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx @@ -29,6 +29,7 @@ class SMESH_Mesh; class SMESH_ProxyMesh; +class StdMeshers_BlockRenumber; class StdMeshers_FaceSide; class TopoDS_Edge; class TopoDS_Face; @@ -44,7 +45,8 @@ class STDMESHERS_EXPORT StdMeshers_CompositeHexa_3D: public SMESH_3D_Algo { public: StdMeshers_CompositeHexa_3D(int hypId, SMESH_Gen* gen); - //virtual ~StdMeshers_CompositeHexa_3D(); + + void SetHypothesis( const StdMeshers_BlockRenumber* hyp ) { _blockRenumberHyp = hyp; } virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); @@ -56,18 +58,21 @@ public: const TopoDS_Shape& aShape, Hypothesis_Status& aStatus); -private: + private: bool findBoxFaces( const TopoDS_Shape& shape, std::list< _QuadFaceGrid >& boxFaceContainer, SMESH_Mesh& mesh, SMESH_ProxyMesh& proxyMesh, + bool& toRenumber, _QuadFaceGrid * & fBottom, _QuadFaceGrid * & fTop, _QuadFaceGrid * & fFront, _QuadFaceGrid * & fBack, _QuadFaceGrid * & fLeft, _QuadFaceGrid * & fRight); + + const StdMeshers_BlockRenumber* _blockRenumberHyp; }; #endif diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index da593c9c3..a9c254e09 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -181,6 +181,41 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, } // loop on edges + // orient seam edges (#19982) + const double tol = Precision::Confusion(); + if ( NbEdges() > 1 && !myC2d[0].IsNull() ) + for ( int i = 0; i < NbEdges(); ++i ) + { + int iPrev = SMESH_MesherHelper::WrapIndex( i - 1, NbEdges() ); + if ( !BRep_Tool::IsClosed( myEdge[i], myFace ) || !myC2d[iPrev] ) + continue; + gp_Pnt2d pLastPrev = myC2d[iPrev]->Value( myLast[iPrev] ); + gp_Pnt2d pFirst = myC2d[i]->Value( myFirst[i] ); + if ( pLastPrev.IsEqual( pFirst, tol )) + continue; // OK + pFirst = myC2d[i]->Value( myLast[i] ); + if ( pLastPrev.IsEqual( pFirst, tol )) + { + std::swap( myFirst[i], myLast[i] ); + continue; + } + TopoDS_Edge E = myEdge[i]; + E.Reverse(); + Handle(Geom2d_Curve) c2dRev = BRep_Tool::CurveOnSurface( E, myFace, myFirst[i], myLast[i] ); + pFirst = c2dRev->Value( myFirst[i] ); + if ( pLastPrev.IsEqual( pFirst, tol )) + { + myC2d[i] = c2dRev; + continue; + } + pFirst = c2dRev->Value( myLast[i] ); + if ( pLastPrev.IsEqual( pFirst, tol )) + { + myC2d[i] = c2dRev; + std::swap( myFirst[i], myLast[i] ); + } + } + // count nodes and segments NbPoints( /*update=*/true ); diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.cxx b/src/StdMeshers/StdMeshers_Hexa_3D.cxx index 53877e2ab..eeb6ad40e 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.cxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.cxx @@ -28,6 +28,13 @@ // #include "StdMeshers_Hexa_3D.hxx" +#include "SMDS_MeshNode.hxx" +#include "SMESH_Comment.hxx" +#include "SMESH_Gen.hxx" +#include "SMESH_Mesh.hxx" +#include "SMESH_MesherHelper.hxx" +#include "SMESH_subMesh.hxx" +#include "StdMeshers_BlockRenumber.hxx" #include "StdMeshers_CompositeHexa_3D.hxx" #include "StdMeshers_FaceSide.hxx" #include "StdMeshers_HexaFromSkin_3D.hxx" @@ -36,23 +43,21 @@ #include "StdMeshers_Quadrangle_2D.hxx" #include "StdMeshers_ViscousLayers.hxx" -#include "SMESH_Comment.hxx" -#include "SMESH_Gen.hxx" -#include "SMESH_Mesh.hxx" -#include "SMESH_MesherHelper.hxx" -#include "SMESH_subMesh.hxx" - -#include "SMDS_MeshNode.hxx" - +#include +#include #include #include -#include #include +#include #include #include "utilities.h" #include "Utils_ExceptHandlers.hxx" +#include + +#include + typedef SMESH_Comment TComm; using namespace std; @@ -77,6 +82,7 @@ StdMeshers_Hexa_3D::StdMeshers_Hexa_3D(int hypId, SMESH_Gen * gen) _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID); // 1 bit /shape type _requireShape = false; _compatibleHypothesis.push_back("ViscousLayers"); + _compatibleHypothesis.push_back("BlockRenumber"); _quadAlgo = new StdMeshers_Quadrangle_2D( gen->GetANewId(), _gen ); } @@ -114,7 +120,8 @@ bool StdMeshers_Hexa_3D::CheckHypothesis return false; */ - _viscousLayersHyp = NULL; + _viscousLayersHyp = nullptr; + _blockRenumberHyp = nullptr; const list& hyps = GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliary=*/false); @@ -129,13 +136,25 @@ bool StdMeshers_Hexa_3D::CheckHypothesis aStatus = HYP_OK; for ( ; h != hyps.end(); ++h ) { - if ( !(_viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h ))) - break; + if ( !_viscousLayersHyp && + (_viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h ))) + continue; + if ( !_blockRenumberHyp && + (_blockRenumberHyp = dynamic_cast< const StdMeshers_BlockRenumber*> ( *h ))) + continue; + break; } - if ( !_viscousLayersHyp ) + if ((int) hyps.size() != (bool)_viscousLayersHyp + (bool)_blockRenumberHyp ) aStatus = HYP_INCOMPATIBLE; else - error( _viscousLayersHyp->CheckHypothesis( aMesh, aShape, aStatus )); + { + if ( _viscousLayersHyp ) + if ( !error( _viscousLayersHyp->CheckHypothesis( aMesh, aShape, aStatus ))) + aStatus = HYP_BAD_PARAMETER; + + if ( _blockRenumberHyp && aStatus == HYP_OK ) + error( _blockRenumberHyp->CheckHypothesis( aMesh, aShape )); + } return aStatus == HYP_OK; } @@ -202,26 +221,6 @@ namespace int operator()(const int x, const int y) const { return y * _xSize + x; } }; - //================================================================================ - /*! - * \brief Appends a range of node columns from a map to another map - */ - template< class TMapIterator > - void append( TParam2ColumnMap& toMap, TMapIterator from, TMapIterator to ) - { - const SMDS_MeshNode* lastNode = toMap.rbegin()->second[0]; - const SMDS_MeshNode* firstNode = from->second[0]; - if ( lastNode == firstNode ) - from++; - double u = toMap.rbegin()->first; - for (; from != to; ++from ) - { - u += 1; - TParam2ColumnMap::iterator u2nn = toMap.insert( toMap.end(), make_pair ( u, TNodeColumn())); - u2nn->second.swap( from->second ); - } - } - //================================================================================ /*! * \brief Finds FaceQuadStruct having a side equal to a given one and rearranges @@ -260,6 +259,204 @@ namespace } return foundQuad; } + + //================================================================================ + /*! + * \brief Put quads to aCubeSide in the order of enum EBoxSides + */ + //================================================================================ + + bool arrangeQuads( FaceQuadStructPtr quad[ 6 ], _FaceGrid aCubeSide[ 6 ], bool reverseBottom ) + { + swap( aCubeSide[B_BOTTOM]._quad, quad[0] ); + if ( reverseBottom ) + swap( aCubeSide[B_BOTTOM]._quad->side[ Q_RIGHT],// direct the bottom normal inside cube + aCubeSide[B_BOTTOM]._quad->side[ Q_LEFT ] ); + + aCubeSide[B_FRONT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_BOTTOM], quad ); + aCubeSide[B_RIGHT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_RIGHT ], quad ); + aCubeSide[B_BACK ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_TOP ], quad ); + aCubeSide[B_LEFT ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_LEFT ], quad ); + if ( aCubeSide[B_FRONT ]._quad ) + aCubeSide[B_TOP]._quad = getQuadWithBottom( aCubeSide[B_FRONT ]._quad->side[Q_TOP ], quad ); + + for ( int i = 1; i < 6; ++i ) + if ( !aCubeSide[i]._quad ) + return false; + return true; + } + + //================================================================================ + /*! + * \brief Rearrange block sides according to StdMeshers_BlockRenumber hypothesis + */ + //================================================================================ + + bool arrangeForRenumber( _FaceGrid blockSide[ 6 ], + TopoDS_Vertex& v000, + TopoDS_Vertex& v001 ) + { + std::swap( blockSide[B_BOTTOM]._quad->side[ Q_RIGHT],// restore after arrangeQuads() + blockSide[B_BOTTOM]._quad->side[ Q_LEFT ] ); + + // find v000 + TopTools_MapOfShape cornerVertices; + cornerVertices.Add( blockSide[B_BOTTOM]._quad->side[Q_BOTTOM].grid->LastVertex() ); + cornerVertices.Add( blockSide[B_BOTTOM]._quad->side[Q_BOTTOM].grid->FirstVertex() ); + cornerVertices.Add( blockSide[B_BOTTOM]._quad->side[Q_TOP ].grid->LastVertex() ); + cornerVertices.Add( blockSide[B_BOTTOM]._quad->side[Q_TOP ].grid->FirstVertex() ); + cornerVertices.Add( blockSide[B_TOP ]._quad->side[Q_BOTTOM].grid->FirstVertex() ); + cornerVertices.Add( blockSide[B_TOP ]._quad->side[Q_BOTTOM].grid->LastVertex() ); + cornerVertices.Add( blockSide[B_TOP ]._quad->side[Q_TOP ].grid->FirstVertex() ); + cornerVertices.Add( blockSide[B_TOP ]._quad->side[Q_TOP ].grid->LastVertex() ); + + if ( v000.IsNull() ) + { + // block CS is not defined; + // renumber only if the block has an edge parallel to an axis of global CS + + v000 = StdMeshers_RenumberHelper::GetVertex000( cornerVertices ); + } + + Bnd_B3d bbox; + for ( auto it = cornerVertices.cbegin(); it != cornerVertices.cend(); ++it ) + bbox.Add( BRep_Tool::Pnt( TopoDS::Vertex( *it ))); + double tol = 1e-5 * Sqrt( bbox.SquareExtent() ); + + // get block edges starting at v000 + + std::vector< StdMeshers_FaceSidePtr > edgesAtV000; + std::vector< gp_Vec > edgeDir; + std::vector< int > iParallel; // 0 - none, 1 - X, 2 - Y, 3 - Z + TopTools_MapOfShape lastVertices; + for ( int iQ = 0; iQ < 6; ++iQ ) + { + FaceQuadStructPtr quad = blockSide[iQ]._quad; + for ( size_t iS = 0; iS < quad->side.size() && edgesAtV000.size() < 3; ++iS ) + { + StdMeshers_FaceSidePtr edge = quad->side[iS]; + TopoDS_Vertex v1 = edge->FirstVertex(), v2 = edge->LastVertex(); + if (( v1.IsSame( v000 ) && !lastVertices.Contains( v2 )) || + ( v2.IsSame( v000 ) && !lastVertices.Contains( v1 ))) + { + bool reverse = v2.IsSame( v000 ); + if ( reverse ) + std::swap( v1, v2 ); + lastVertices.Add( v2 ); + + edgesAtV000.push_back( edge ); + + gp_Pnt pf = BRep_Tool::Pnt( v1 ); + gp_Pnt pl = BRep_Tool::Pnt( v2 ); + gp_Vec vec( pf, pl ); + edgeDir.push_back( vec ); + + iParallel.push_back( 0 ); + if ( !v001.IsNull() ) + { + if ( v001.IsSame( v2 )) + iParallel.back() = 3; + } + else + { + bool isStraight = true; + for ( int iE = 0; iE < edge->NbEdges() && isStraight; ++iE ) + isStraight = SMESH_Algo::IsStraight( edge->Edge( iE )); + + // is parallel to a GCS axis? + if ( isStraight ) + { + int nbDiff = (( Abs( vec.X() ) > tol ) + + ( Abs( vec.Y() ) > tol ) + + ( Abs( vec.Z() ) > tol ) ); + if ( nbDiff == 1 ) + iParallel.back() = ( Abs( vec.X() ) > tol ) ? 1 : ( Abs( vec.Y() ) > tol ) ? 2 : 3; + } + else + { + edgeDir.back() = gp_Vec( pf, edge->Value3d( reverse ? 0.99 : 0.01 )); + } + } + } + } + } + if ( std::accumulate( iParallel.begin(), iParallel.end(), 0 ) == 0 ) + return false; + + // find edge OZ and edge OX + StdMeshers_FaceSidePtr edgeOZ, edgeOX; + auto iZIt = std::find( iParallel.begin(), iParallel.end(), 3 ); + if ( iZIt != iParallel.end() ) + { + int i = std::distance( iParallel.begin(), iZIt ); + edgeOZ = edgesAtV000[ i ]; + int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() ); + int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() ); + if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 ) + std::swap( iE1, iE2 ); + edgeOX = edgesAtV000[ iE1 ]; + } + else + { + for ( size_t i = 0; i < edgesAtV000.size(); ++i ) + { + if ( !iParallel[ i ] ) + continue; + int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() ); + int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() ); + if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 ) + std::swap( iE1, iE2 ); + edgeOZ = edgesAtV000[ iParallel[i] == 1 ? iE2 : iE1 ]; + edgeOX = edgesAtV000[ iParallel[i] == 1 ? i : iE1 ]; + break; + } + } + + if ( !edgeOZ || !edgeOX ) + return false; + + TopoDS_Vertex v100 = edgeOX->LastVertex(); + if ( v100.IsSame( v000 )) + v100 = edgeOX->FirstVertex(); + + // Find the left quad, one including v000 but not v100 + + for ( int iQ = 0; iQ < 6; ++iQ ) + { + FaceQuadStructPtr quad = blockSide[iQ]._quad; + bool hasV000 = false, hasV100 = false; + for ( size_t iS = 0; iS < quad->side.size(); ++iS ) + { + StdMeshers_FaceSidePtr edge = quad->side[iS]; + if ( edge->FirstVertex().IsSame( v000 ) || edge->LastVertex().IsSame( v000 )) + hasV000 = true; + if ( edge->FirstVertex().IsSame( v100 ) || edge->LastVertex().IsSame( v100 )) + hasV100 = true; + } + if ( hasV000 && !hasV100 ) + { + // orient the left quad + for ( int i = 0; i < 4; ++i ) + { + if ( quad->side[Q_BOTTOM].grid->Edge(0).IsSame( edgeOZ->Edge(0) )) + break; + quad->shift( 1, true ); + } + + FaceQuadStructPtr quads[ 6 ]; + quads[0].swap( blockSide[iQ]._quad ); + for ( int i = 1, j = 0; i < 6; ++i, ++j ) + if ( blockSide[ j ]._quad ) + quads[ i ].swap( blockSide[ j ]._quad ); + else + --i; + + return arrangeQuads( quads, blockSide, false/* true*/ ); + } + } + return false; + } + //================================================================================ /*! * \brief Returns true if the 1st base node of sideGrid1 belongs to sideGrid2 @@ -371,9 +568,11 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, if ( FF.Extent() != 6) { static StdMeshers_CompositeHexa_3D compositeHexa(_gen->GetANewId(), _gen); + compositeHexa.SetHypothesis( _blockRenumberHyp ); if ( !compositeHexa.Compute( aMesh, aShape )) return error( compositeHexa.GetComputeError() ); - return true; + + return _blockRenumberHyp ? error( _blockRenumberHyp->CheckHypothesis( aMesh, aShape )) : true; } // Find sides of a cube @@ -399,22 +598,11 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, return error( COMPERR_BAD_SHAPE, "Not a quadrangular box side" ); } + // put quads in a proper order _FaceGrid aCubeSide[ 6 ]; + if ( !arrangeQuads( quad, aCubeSide, true )) + return error( COMPERR_BAD_SHAPE ); - swap( aCubeSide[B_BOTTOM]._quad, quad[0] ); - swap( aCubeSide[B_BOTTOM]._quad->side[ Q_RIGHT],// direct the normal of bottom quad inside cube - aCubeSide[B_BOTTOM]._quad->side[ Q_LEFT ] ); - - aCubeSide[B_FRONT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_BOTTOM], quad ); - aCubeSide[B_RIGHT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_RIGHT ], quad ); - aCubeSide[B_BACK ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_TOP ], quad ); - aCubeSide[B_LEFT ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_LEFT ], quad ); - if ( aCubeSide[B_FRONT ]._quad ) - aCubeSide[B_TOP]._quad = getQuadWithBottom( aCubeSide[B_FRONT ]._quad->side[Q_TOP ], quad ); - - for ( int i = 1; i < 6; ++i ) - if ( !aCubeSide[i]._quad ) - return error( COMPERR_BAD_SHAPE ); // Make viscous layers // -------------------- @@ -446,6 +634,22 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, } } + // Arrange sides according to _blockRenumberHyp + bool toRenumber = _blockRenumberHyp; + if ( toRenumber ) + { + TopoDS_Vertex v000, v001; + _blockRenumberHyp->IsSolidIncluded( aMesh, aShape, v000, v001 ); + + toRenumber = arrangeForRenumber( aCubeSide, v000, v001 ); + + if ( toRenumber ) + { + meshDS->Modified(); + meshDS->CompactMesh(); // remove numbering holes + } + } + // Check presence of regular grid mesh on FACEs of the cube // ------------------------------------------------------------ @@ -605,6 +809,8 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, computeIJK( *fFront, COO_X, COO_Z, /*y=*/0. ); computeIJK( *fBack, COO_X, COO_Z, /*y=*/1. ); + StdMeshers_RenumberHelper renumHelper( aMesh, _blockRenumberHyp ); + // projection points of the internal node on cube sub-shapes by which // coordinates of the internal node are computed vector pointsOnShapes( SMESH_Block::ID_Shell ); @@ -620,8 +826,24 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, pointsOnShapes[ SMESH_Block::ID_V111 ] = fTop->GetXYZ( X, Y ); gp_XYZ params; // normalized parameters of an internal node within the unit box + + if ( toRenumber ) + for ( y = 0; y < ySize; ++y ) + { + vector< const SMDS_MeshNode* >& column0y = columns[ colIndex( 0, y )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( column0y[ z ] ); + } + for ( x = 1; x < xSize-1; ++x ) { + if ( toRenumber ) + { + vector< const SMDS_MeshNode* >& columnX0 = columns[ colIndex( x, 0 )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( columnX0[ z ] ); + } + const double rX = x / double(X); for ( y = 1; y < ySize-1; ++y ) { @@ -641,6 +863,10 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, // projection points on horizontal faces pointsOnShapes[ SMESH_Block::ID_Fxy0 ] = fBottom->GetXYZ( x, y ); pointsOnShapes[ SMESH_Block::ID_Fxy1 ] = fTop ->GetXYZ( x, y ); + + if ( toRenumber ) + renumHelper.AddReplacingNode( column[ 0 ] ); + for ( z = 1; z < zSize-1; ++z ) // z loop { const double rZ = z / double(Z); @@ -673,13 +899,31 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, gp_XYZ coords; SMESH_Block::ShellPoint( params, pointsOnShapes, coords ); column[ z ] = helper.AddNode( coords.X(), coords.Y(), coords.Z() ); - } + + } // z loop + if ( toRenumber ) + renumHelper.AddReplacingNode( column[ Z ] ); + + } // y loop + if ( toRenumber ) + { + vector< const SMDS_MeshNode* >& columnX0 = columns[ colIndex( x, Y )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( columnX0[ z ] ); + } + } // x loop + + if ( toRenumber ) + for ( y = 0; y < ySize; ++y ) + { + vector< const SMDS_MeshNode* >& columnXy = columns[ colIndex( X, y )]; + for ( z = 0; z < zSize; ++z ) + renumHelper.AddReplacingNode( columnXy[ z ] ); } - } // side data no more needed, free memory for ( int i = 0; i < 6; ++i ) - aCubeSide[i]._columns.clear(); + SMESHUtils::FreeVector( aCubeSide[i]._columns ); // 5) Create hexahedrons // --------------------- @@ -693,11 +937,25 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, for ( z = 0; z < zSize-1; ++z ) { // bottom face normal of a hexa mush point outside the volume - helper.AddVolume(col00[z], col01[z], col11[z], col10[z], - col00[z+1], col01[z+1], col11[z+1], col10[z+1]); + if ( toRenumber ) + helper.AddVolume(col00[z], col01[z], col01[z+1], col00[z+1], + col10[z], col11[z], col11[z+1], col10[z+1]); + else + helper.AddVolume(col00[z], col01[z], col11[z], col10[z], + col00[z+1], col01[z+1], col11[z+1], col10[z+1]); } } } + + if ( toRenumber ) + renumHelper.DoReplaceNodes(); + + + if ( _blockRenumberHyp ) + { + return error( _blockRenumberHyp->CheckHypothesis( aMesh, aShape )); + } + return true; } diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.hxx b/src/StdMeshers/StdMeshers_Hexa_3D.hxx index a743d4754..16315e0d7 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.hxx @@ -37,6 +37,7 @@ class SMESH_MesherHelper; class StdMeshers_Quadrangle_2D; class StdMeshers_ViscousLayers; +class StdMeshers_BlockRenumber; class STDMESHERS_EXPORT StdMeshers_Hexa_3D : public SMESH_3D_Algo { @@ -64,6 +65,7 @@ public: protected: const StdMeshers_ViscousLayers* _viscousLayersHyp; + const StdMeshers_BlockRenumber* _blockRenumberHyp; StdMeshers_Quadrangle_2D* _quadAlgo; }; diff --git a/src/StdMeshers/StdMeshers_Import_1D.cxx b/src/StdMeshers/StdMeshers_Import_1D.cxx index 179dd52e4..e3d59a79c 100644 --- a/src/StdMeshers/StdMeshers_Import_1D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D.cxx @@ -38,14 +38,19 @@ #include "SMESH_Mesh.hxx" #include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" +#include "SMESH_Octree.hxx" #include "SMESH_subMesh.hxx" #include "SMESH_subMeshEventListener.hxx" #include "Utils_SALOME_Exception.hxx" #include "utilities.h" +#include #include #include +#include +#include +#include #include #include #include @@ -55,25 +60,251 @@ using namespace std; -//============================================================================= -/*! - * Creates StdMeshers_Import_1D - */ -//============================================================================= - -StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, SMESH_Gen * gen) - :SMESH_1D_Algo(hypId, gen), _sourceHyp(0) -{ - _name = "Import_1D"; - _shapeType = (1 << TopAbs_EDGE); - - _compatibleHypothesis.push_back("ImportSource1D"); -} - //================================================================================ namespace // INTERNAL STUFF //================================================================================ { + /*! + * \brief Compute point position on a curve. Use octree to fast reject far points + */ + class CurveProjector : public SMESH_Octree + { + public: + CurveProjector( const TopoDS_Edge& edge, double enlarge ); + + bool IsOnCurve( const gp_XYZ& point, double & distance2, double & u ); + + bool IsOut( const gp_XYZ& point ) const { return getBox()->IsOut( point ); } + + protected: + CurveProjector() {} + SMESH_Octree* newChild() const { return new CurveProjector; } + void buildChildrenData(); + Bnd_B3d* buildRootBox(); + + private: + struct CurveSegment : public Bnd_B3d + { + double _chord, _chord2, _length2; + gp_Pnt _pFirst, _pLast; + gp_Lin _line; + Handle(Geom_Curve) _curve; + + CurveSegment() {} + void Init( const gp_Pnt& pf, const gp_Pnt& pl, + double uf, double ul, double tol, Handle(Geom_Curve)& curve ); + bool IsOn( const gp_XYZ& point, double & distance2, double & u ); + bool IsInContact( const Bnd_B3d& bb ); + }; + std::vector< CurveSegment > _segments; + }; + + //=============================================================================== + /*! + * \brief Create an octree of curve segments + */ + //================================================================================ + + CurveProjector::CurveProjector( const TopoDS_Edge& edge, double enlarge ) + :SMESH_Octree( 0 ) + { + double f,l; + Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l ); + double curDeflect = 0.3; // Curvature deflection + double angDeflect = 1e+100; // Angular deflection - don't control chordal error + GCPnts_TangentialDeflection div( BRepAdaptor_Curve( edge ), angDeflect, curDeflect ); + _segments.resize( div.NbPoints() - 1 ); + for ( int i = 1; i < div.NbPoints(); ++i ) + try { + _segments[ i - 1 ].Init( div.Value( i ), div.Value( i+1 ), + div.Parameter( i ), div.Parameter( i+1 ), + enlarge, curve ); + } + catch ( Standard_Failure ) { + _segments.resize( _segments.size() - 1 ); + --i; + } + if ( _segments.size() < 3 ) + myIsLeaf = true; + + compute(); + + if ( _segments.size() == 1 ) + myBox->Enlarge( enlarge ); + } + + //================================================================================ + /*! + * \brief Return the maximal box + */ + //================================================================================ + + Bnd_B3d* CurveProjector::buildRootBox() + { + Bnd_B3d* box = new Bnd_B3d; + for ( size_t i = 0; i < _segments.size(); ++i ) + box->Add( _segments[i] ); + return box; + } + + //================================================================================ + /*! + * \brief Redistribute segments among children + */ + //================================================================================ + + void CurveProjector::buildChildrenData() + { + bool allIn = true; + for ( size_t i = 0; i < _segments.size(); ++i ) + { + for (int j = 0; j < 8; j++) + { + if ( _segments[i].IsInContact( *myChildren[j]->getBox() )) + ((CurveProjector*)myChildren[j])->_segments.push_back( _segments[i]); + else + allIn = false; + } + } + if ( allIn && _segments.size() < 3 ) + { + myIsLeaf = true; + for (int j = 0; j < 8; j++) + static_cast( myChildren[j])->myIsLeaf = true; + } + else + { + SMESHUtils::FreeVector( _segments ); // = _segments.clear() + free memory + + for (int j = 0; j < 8; j++) + { + CurveProjector* child = static_cast( myChildren[j]); + if ( child->_segments.size() < 3 ) + child->myIsLeaf = true; + } + } + } + + //================================================================================ + /*! + * \brief Return true if a point is close to the curve + * \param [in] point - the point + * \param [out] distance2 - distance to the curve + * \param [out] u - parameter on the curve + * \return bool - is the point is close to the curve + */ + //================================================================================ + + bool CurveProjector::IsOnCurve( const gp_XYZ& point, double & distance2, double & u ) + { + if ( getBox()->IsOut( point )) + return false; + + if ( isLeaf() ) + { + for ( size_t i = 0; i < _segments.size(); ++i ) + if ( !_segments[i].IsOut( point ) && + _segments[i].IsOn( point, distance2, u )) + return true; + } + else + { + for (int i = 0; i < 8; i++) + if (((CurveProjector*) myChildren[i])->IsOnCurve( point, distance2, u )) + return true; + } + return false; + } + + //================================================================================ + /*! + * \brief Initialize + */ + //================================================================================ + + void CurveProjector::CurveSegment::Init(const gp_Pnt& pf, + const gp_Pnt& pl, + const double uf, + const double ul, + const double tol, + Handle(Geom_Curve)& curve ) + { + _pFirst = pf; + _pLast = pl; + _curve = curve; + _length2 = pf.SquareDistance( pl ); + _chord2 = Max( _line. SquareDistance( curve->Value( uf + 0.25 * ( ul - uf ))), + Max( _line.SquareDistance( curve->Value( uf + 0.5 * ( ul - uf ))), + _line.SquareDistance( curve->Value( uf + 0.75 * ( ul - uf ))))); + _chord2 = Max( tol, _chord2 ); + _chord = Sqrt( _chord2 ); + _line.SetLocation( pf ); + _line.SetDirection( gp_Vec( pf, pl )); + + Bnd_Box bb; + BndLib_Add3dCurve::Add( GeomAdaptor_Curve( curve, uf, ul ), tol, bb ); + Add( bb.CornerMin() ); + Add( bb.CornerMax() ); + } + + //================================================================================ + /*! + * \brief Return true if a point is close to the curve segment + * \param [in] point - the point + * \param [out] distance2 - distance to the curve + * \param [out] u - parameter on the curve + * \return bool - is the point is close to the curve segment + */ + //================================================================================ + + bool CurveProjector::CurveSegment::IsOn( const gp_XYZ& point, double & distance2, double & u ) + { + distance2 = _line.SquareDistance( point ); + if ( distance2 > _chord2 ) + return false; + + // check if the point projection falls into the segment range + { + gp_Vec edge( _pFirst, _pLast ); + gp_Vec n1p ( _pFirst, point ); + u = ( edge * n1p ) / _length2; // param [0,1] on the edge + if ( u < 0 ) + { + if ( _pFirst.SquareDistance( point ) > _chord2 ) + return false; + } + else if ( u > _chord ) + { + if ( _pLast.SquareDistance( point ) > _chord2 ) + return false; + } + } + gp_Pnt proj; + distance2 = ShapeAnalysis_Curve().Project( _curve, point, Precision::Confusion(), + proj, u, false ); + distance2 *= distance2; + return true; + } + + //================================================================================ + /*! + * \brief Check if the segment is in contact with a box + */ + //================================================================================ + + bool CurveProjector::CurveSegment::IsInContact( const Bnd_B3d& bb ) + { + if ( bb.IsOut( _line.Position(), /*isRay=*/true, _chord )) + return false; + + gp_Ax1 axRev = _line.Position().Reversed(); + axRev.SetLocation( _pLast ); + return !bb.IsOut( axRev, /*isRay=*/true, _chord ); + } + + //================================================================================ + //================================================================================ + int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS, SMESH_Mesh* tgtMesh); enum _ListenerDataType @@ -590,8 +821,50 @@ namespace // INTERNAL STUFF return 0; } + //================================================================================ + /*! + * \brief Return minimal square length of edges of 1D and 2D elements sharing the node + */ + //================================================================================ + + double getMinEdgeLength2( const SMDS_MeshNode* n ) + { + SMESH_NodeXYZ p = n; + double minLen2 = Precision::Infinite(); + for ( SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator(); eIt->more(); ) + { + const SMDS_MeshElement* e = eIt->next(); + const SMDSAbs_ElementType type = e->GetType(); + if ( type != SMDSAbs_Edge && type != SMDSAbs_Face ) + continue; + int i = e->GetNodeIndex( n ); + int iNext = SMESH_MesherHelper::WrapIndex( i + 1, e->NbCornerNodes() ); + minLen2 = Min( minLen2, p.SquareDistance( e->GetNode( iNext ))); + if ( type != SMDSAbs_Face ) + continue; + int iPrev = SMESH_MesherHelper::WrapIndex( i - 1, e->NbCornerNodes() ); + minLen2 = Min( minLen2, p.SquareDistance( e->GetNode( iPrev ))); + } + return minLen2; + } + } // namespace +//============================================================================= +/*! + * Creates StdMeshers_Import_1D + */ +//============================================================================= + +StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, SMESH_Gen * gen) + :SMESH_1D_Algo(hypId, gen), _sourceHyp(0) +{ + _name = "Import_1D"; + _shapeType = (1 << TopAbs_EDGE); + + _compatibleHypothesis.push_back("ImportSource1D"); +} + //============================================================================= /*! * Check presence of a hypothesis @@ -658,17 +931,31 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th const double edgeTol = BRep_Tool::Tolerance( geomEdge ); const int shapeID = tgtMesh->ShapeToIndex( geomEdge ); - set subShapeIDs; - subShapeIDs.insert( shapeID ); + + double geomTol = Precision::Confusion(); + for ( size_t iG = 0; iG < srcGroups.size(); ++iG ) + { + const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS(); + for ( SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements(); srcElems->more(); ) + { + const SMDS_MeshElement* edge = srcElems->next(); + geomTol = Sqrt( 0.5 * ( getMinEdgeLength2( edge->GetNode(0) ) + + getMinEdgeLength2( edge->GetNode(1) ))) / 25; + iG = srcGroups.size(); + break; + } + } + CurveProjector curveProjector( geomEdge, geomTol ); // get nodes on vertices + set vertexIDs; list < SMESH_TNodeXYZ > vertexNodes; list < SMESH_TNodeXYZ >::iterator vNIt; TopExp_Explorer vExp( theShape, TopAbs_VERTEX ); for ( ; vExp.More(); vExp.Next() ) { const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() ); - if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second ) + if ( !vertexIDs.insert( tgtMesh->ShapeToIndex( v )).second ) continue; // closed edge const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh ); if ( !n ) @@ -696,56 +983,61 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements(); vector newNodes; - SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0); - double u = 0.314159; // "random" value between 0 and 1, avoid 0 and 1, false detection possible on edge restrictions while ( srcElems->more() ) // loop on group contents { const SMDS_MeshElement* edge = srcElems->next(); + gp_XYZ middle = 0.5 * ( SMESH_NodeXYZ( edge->GetNode(0)) + + SMESH_NodeXYZ( edge->GetNode(1))); + if ( curveProjector.IsOut( middle )) + continue; + // find or create nodes of a new edge newNodes.resize( edge->NbNodes() ); - //MESSAGE("edge->NbNodes " << edge->NbNodes()); newNodes.back() = 0; + int nbNodesOnVertex = 0; SMDS_MeshElement::iterator node = edge->begin_nodes(); - SMESH_TNodeXYZ a(edge->GetNode(0)); - // --- define a tolerance relative to the length of an edge - double mytol = a.Distance(edge->GetNode(edge->NbNodes()-1))/25; - //mytol = max(1.E-5, 10*edgeTol); // too strict and not necessary - //MESSAGE("mytol = " << mytol); for ( size_t i = 0; i < newNodes.size(); ++i, ++node ) { - TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first; + TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, nullptr )).first; if ( n2nIt->second ) { - if ( !subShapeIDs.count( n2nIt->second->getshapeId() )) - break; + int sId = n2nIt->second->getshapeId(); + if ( sId != shapeID ) + { + if ( vertexIDs.count( sId )) + ++nbNodesOnVertex; + else + break; + } } - else + else if ( !vertexNodes.empty() ) { // find an existing vertex node double checktol = max(1.E-10, 10*edgeTol*edgeTol); for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt) if ( vNIt->SquareDistance( *node ) < checktol) { - //MESSAGE("SquareDistance " << vNIt->SquareDistance( *node ) << " checktol " << checktol <<" "<X()<<" "<Y()<<" "<Z()); (*n2nIt).second = vNIt->_node; vertexNodes.erase( vNIt ); + ++nbNodesOnVertex; break; } - else if ( vNIt->SquareDistance( *node ) < 10*checktol) - MESSAGE("SquareDistance missed" << vNIt->SquareDistance( *node ) << " checktol " << checktol <<" "<X()<<" "<Y()<<" "<Z()); } if ( !n2nIt->second ) { - // find out if node lies on theShape - //double dxyz[4]; - tmpNode->setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z()); - if ( helper.CheckNodeU( geomEdge, tmpNode, u, mytol, /*force=*/true)) // , dxyz )) // dxyz used for debug purposes + // find out if the node lies on theShape + SMESH_NodeXYZ xyz = *node; + double dist2, u; + if ( curveProjector.IsOnCurve( xyz, dist2, u )) { - SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z()); - n2nIt->second = newNode; - tgtMesh->SetNodeOnEdge( newNode, shapeID, u ); - //MESSAGE("u=" << u << " " << newNode->X()<< " " << newNode->Y()<< " " << newNode->Z()); - //MESSAGE("d=" << dxyz[0] << " " << dxyz[1] << " " << dxyz[2] << " " << dxyz[3]); + // tolerance relative to the length of surrounding edges + double mytol2 = getMinEdgeLength2( *node ) / 25 / 25; + if ( dist2 < mytol2 ) + { + SMDS_MeshNode* newNode = tgtMesh->AddNode( xyz.X(), xyz.Y(), xyz.Z() ); + n2nIt->second = newNode; + tgtMesh->SetNodeOnEdge( newNode, shapeID, u ); + } } } if ( !(newNodes[i] = n2nIt->second )) @@ -763,12 +1055,17 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] ); else newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]); - //MESSAGE("add Edge " << newNodes[0]->GetID() << " " << newNodes[1]->GetID()); tgtMesh->SetMeshElementOnShape( newEdge, shapeID ); e2e->insert( make_pair( edge, newEdge )); - } - helper.GetMeshDS()->RemoveNode(tmpNode); - } + + if ( nbNodesOnVertex >= 2 ) // EDGE is meshed by a sole segment + { + iG = srcGroups.size(); // stop looingp on groups + break; + } + } // loop on group contents + } // loop on groups + if ( n2n->empty()) return error("Empty source groups"); diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.cxx b/src/StdMeshers/StdMeshers_Import_1D2D.cxx index 04d903508..30f3d163c 100644 --- a/src/StdMeshers/StdMeshers_Import_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D2D.cxx @@ -324,8 +324,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & { const SMDS_MeshElement* face = srcElems->next(); - SMDS_MeshElement::iterator node = face->begin_nodes(); - if ( bndBox3d.IsOut( SMESH_TNodeXYZ( *node ))) + if ( bndBox3d.IsOut( SMESH_NodeXYZ( face->GetNode(0) ))) continue; // find or create nodes of a new face @@ -334,13 +333,14 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & newNodes.back() = 0; int nbCreatedNodes = 0; bool isOut = false, isIn = false; // if at least one node isIn - do not classify other nodes - for ( size_t i = 0; i < newNodes.size(); ++i, ++node ) + for ( size_t i = 0; i < newNodes.size(); ++i ) { - SMESH_TNodeXYZ nXYZ = *node; + const SMDS_MeshNode* node = face->GetNode( i ); + SMESH_NodeXYZ nXYZ = node; nodeState[ i ] = TopAbs_UNKNOWN; newNodes [ i ] = 0; - it_isnew = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )); + it_isnew = n2n->insert( make_pair( node, nullptr )); n2nIt = it_isnew.first; const SMDS_MeshNode* & newNode = n2nIt->second; @@ -354,7 +354,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & if ( newNode->GetID() < (int) isNodeIn.size() && isNodeIn[ newNode->GetID() ]) isIn = true; - if ( !isIn && bndNodes.count( *node )) + if ( !isIn && bndNodes.count( node )) nodeState[ i ] = TopAbs_ON; } else @@ -373,7 +373,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & { // find out if node lies on the surface of theShape gp_XY uv( Precision::Infinite(), 0 ); - isOut = ( !helper.CheckNodeUV( geomFace, *node, uv, groupTol, /*force=*/true ) || + isOut = ( !helper.CheckNodeUV( geomFace, node, uv, groupTol, /*force=*/true ) || bndBox2d.IsOut( uv )); //int iCoo; if ( !isOut && !isIn ) // classify @@ -381,7 +381,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & nodeState[i] = classifier.Perform( uv ); //classifier.Perform( geomFace, uv, clsfTol ); //nodeState[i] = classifier.State(); isOut = ( nodeState[i] == TopAbs_OUT ); - if ( isOut && helper.IsOnSeam( uv ) && onEdgeClassifier.IsSatisfy( (*node)->GetID() )) + if ( isOut && helper.IsOnSeam( uv ) && onEdgeClassifier.IsSatisfy( node->GetID() )) { // uv.SetCoord( iCoo, helper.GetOtherParam( uv.Coord( iCoo ))); // classifier.Perform( geomFace, uv, clsfTol ); @@ -402,7 +402,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & isNodeIn.resize( newNode->GetID() + 1, false ); } if ( nodeState[i] == TopAbs_ON ) - bndNodes.insert( *node ); + bndNodes.insert( node ); else if ( nodeState[i] != TopAbs_UNKNOWN ) isNodeIn[ newNode->GetID() ] = isIn = true; } diff --git a/src/StdMeshersGUI/CMakeLists.txt b/src/StdMeshersGUI/CMakeLists.txt index c0f1c390f..d423dd2a3 100644 --- a/src/StdMeshersGUI/CMakeLists.txt +++ b/src/StdMeshersGUI/CMakeLists.txt @@ -81,6 +81,7 @@ SET(_moc_HEADERS StdMeshersGUI_RadioButtonsGrpWdg.h StdMeshersGUI_PropagationHelperWdg.h StdMeshersGUI_NameCheckableGrpWdg.h + StdMeshersGUI_BlockRenumberCreator.h ) IF(SALOME_USE_PLOT2DVIEWER) @@ -117,6 +118,7 @@ SET(_other_SOURCES StdMeshersGUI_RadioButtonsGrpWdg.cxx StdMeshersGUI_PropagationHelperWdg.cxx StdMeshersGUI_NameCheckableGrpWdg.cxx + StdMeshersGUI_BlockRenumberCreator.cxx ) IF(SALOME_USE_PLOT2DVIEWER) diff --git a/src/StdMeshersGUI/StdMeshersGUI.cxx b/src/StdMeshersGUI/StdMeshersGUI.cxx index 511874583..406c14de9 100644 --- a/src/StdMeshersGUI/StdMeshersGUI.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI.cxx @@ -24,10 +24,11 @@ // Author : Alexander SOLOVYOV, Open CASCADE S.A.S. // SMESH includes // -#include "StdMeshersGUI_StdHypothesisCreator.h" -#include "StdMeshersGUI_NbSegmentsCreator.h" +#include "StdMeshersGUI_BlockRenumberCreator.h" #include "StdMeshersGUI_CartesianParamCreator.h" +#include "StdMeshersGUI_NbSegmentsCreator.h" #include "StdMeshersGUI_QuadrangleParamWdg.h" +#include "StdMeshersGUI_StdHypothesisCreator.h" //============================================================================= /*! GetHypothesisCreator @@ -45,6 +46,8 @@ extern "C" return new StdMeshersGUI_CartesianParamCreator( aHypType ); else if ( aHypType=="QuadrangleParams" ) return new StdMeshersGUI_QuadrangleParamCreator( aHypType ); + else if ( aHypType=="BlockRenumber") + return new StdMeshersGUI_BlockRenumberCreator( aHypType ); else return new StdMeshersGUI_StdHypothesisCreator( aHypType ); } diff --git a/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.cxx new file mode 100644 index 000000000..2f946d9a1 --- /dev/null +++ b/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.cxx @@ -0,0 +1,515 @@ +// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : StdMeshersGUI_BlockRenumberCreator.cxx +// Author : Open CASCADE S.A.S. + +#include "StdMeshersGUI_BlockRenumberCreator.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_Utils.h" +#include "SMESHGUI_VTKUtils.h" +#include "SMESHGUI_HypothesesUtils.h" + +#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPACING 6 +#define MARGIN 11 + +namespace { + + //================================================================================ + /*! + * \brief Textual representation of GEOM_Object in QTreeWidget + */ + //================================================================================ + + QString toText( const GEOM::GEOM_Object_var& theGO, + const QString & /*theLabel*/, + QString& theEntry ) + { + QString txt; + if ( !theGO->_is_nil() ) + { + CORBA::String_var name = theGO->GetName(); + CORBA::String_var entry = theGO->GetStudyEntry(); + theEntry = entry.in(); + + txt = name.in(); + //txt = theLabel + name.in() + " [" + theEntry + "]"; + //txt += " ";//" ("; + //txt += entry.in(); + //txt += ")"; + } + return txt; + } + + //================================================================================ + /*! + * \brief Find GEOM_Object by study entry + */ + //================================================================================ + + GEOM::GEOM_Object_var toGeom( const QString& entry ) + { + return SMESH::EntryToInterface( entry ); + } + + + //================================================================================ + /*! + * \brief Find GEOM_Object in the tree + */ + //================================================================================ + + QTreeWidgetItem* findSolidInTree( const GEOM::GEOM_Object_var& go, QTreeWidget* tree ) + { + if ( go->_is_nil() || !tree ) + return nullptr; + + for ( int i = 0; i < tree->topLevelItemCount(); ++i ) + { + QTreeWidgetItem* item = tree->topLevelItem( i ); + if ( item->data( 1, Qt::UserRole ).toString() == SMESH::toQStr( go->GetStudyEntry() )) + return item; + } + return nullptr; + } +} + +//================================================================================ +/*! + * \brief StdMeshersGUI_BlockRenumberCreator constructor + */ +//================================================================================ + +StdMeshersGUI_BlockRenumberCreator::StdMeshersGUI_BlockRenumberCreator(const QString& aHypType) + : StdMeshersGUI_StdHypothesisCreator( aHypType ), + mySolidFilter( "", TopAbs_SOLID, 1, TopAbs_SOLID ), + myVertexFilter( "", TopAbs_VERTEX, 1, TopAbs_VERTEX ) +{ +} + +//================================================================================ +/*! + * \brief StdMeshersGUI_BlockRenumberCreator destructor + */ +//================================================================================ + +StdMeshersGUI_BlockRenumberCreator::~StdMeshersGUI_BlockRenumberCreator() +{ + SMESHGUI::selectionMgr()->clearFilters(); +} + +//================================================================================ +/*! + * \brief Create widgets + */ +//================================================================================ + +QFrame* StdMeshersGUI_BlockRenumberCreator::buildFrame() +{ + QFrame* fr = new QFrame(); + //fr->setMinimumWidth(460); + + QGridLayout* frLayout = new QGridLayout( fr ); + frLayout->setSpacing( SPACING ); + frLayout->setMargin( MARGIN ); + + // name + myName = 0; + int row = 0; + if( isCreation() ) + { + myName = new QLineEdit( fr ); + frLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), fr ), row, 0 ); + frLayout->addWidget( myName, row, 1 ); + row++; + } + + QGroupBox* groupBox = new QGroupBox( tr( "BLOCK_CS_GROUPBOX" ), fr ); + frLayout->addWidget( groupBox, row, 0, 1, 2 ); + + QGridLayout* layout = new QGridLayout( groupBox ); + layout->setSpacing( SPACING ); + layout->setMargin( MARGIN ); + layout->setColumnStretch( 0, 1 ); + + // tree + row = 0; + myBlockTree = new QTreeWidget( groupBox ); + myBlockTree->setColumnCount( 2 ); + myBlockTree->header()->hide(); + // myBlockTree->setHeaderLabels( QStringList() + // << tr("COLUMN_BLOCK") << tr("COLUMN_V000") << tr("COLUMN_V001")); + layout->addWidget( myBlockTree, row, 0, row + 7, 1 ); + + // selection widgets + myButGroup = new QButtonGroup( groupBox ); + myButGroup->setExclusive( true ); + QLabel* label[3] = { new QLabel( tr( "SOLID" ), groupBox ), + new QLabel( tr( "V000" ), groupBox ), + new QLabel( tr( "V001" ), groupBox ) }; + QIcon icon( SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT"))); + for ( int i = 0; i < 3; ++i ) + { + myShapeSelectBut[i] = new QPushButton( icon, "", groupBox ); + myLineEdit [i] = new QLineEdit( groupBox ); + layout->addWidget( label[i], row, 1 ); + layout->addWidget( myShapeSelectBut[i], row, 2 ); + layout->addWidget( myLineEdit[i], row, 3 ); + myShapeSelectBut[i]->setCheckable( true ); + myButGroup->addButton( myShapeSelectBut[i], i ); + row++; + } + + // buttons + myAddBut = new QPushButton( tr("ADD"), groupBox ); + myModifBut = new QPushButton( tr("MODIFY"), groupBox ); + myRemoveBut = new QPushButton( tr("SMESH_REMOVE"), groupBox ); + layout->addWidget( myAddBut, row, 1, 1, 3 ); + row++; + layout->addWidget( myModifBut, row, 1, 1, 3 ); + row++; + layout->addWidget( myRemoveBut, row, 1, 1, 3 ); + row++; + layout->setRowStretch( row, 1 ); + + LightApp_SelectionMgr* selMgr = SMESH::GetSelectionMgr( SMESHGUI::GetSMESHGUI() ); + + connect( selMgr, SIGNAL( currentSelectionChanged()), SLOT( onSelectionChange())); + connect( myBlockTree, SIGNAL( itemSelectionChanged() ), SLOT( onTreeSelectionChange())); + connect( myShapeSelectBut[0], SIGNAL( clicked(bool)), SLOT( onSelectBtnClick() )); + connect( myShapeSelectBut[1], SIGNAL( clicked(bool)), SLOT( onSelectBtnClick() )); + connect( myShapeSelectBut[2], SIGNAL( clicked(bool)), SLOT( onSelectBtnClick() )); + connect( myAddBut, SIGNAL( clicked() ), SLOT( onAddBtnClick() )); + connect( myModifBut, SIGNAL( clicked() ), SLOT( onModifBtnClick() )); + connect( myRemoveBut, SIGNAL( clicked() ), SLOT( onRemoveBtnClick() )); + + return fr; +} + +//================================================================================ +/*! + * \brief Set myGO's to the tree + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::setBlockToTree(QTreeWidgetItem* solidItem) +{ + if ( !myGO[0]->_is_nil() && !myGO[1]->_is_nil() && !myGO[2]->_is_nil() ) + { + if ( !solidItem ) solidItem = new QTreeWidgetItem( myBlockTree ); + solidItem->setExpanded( true ); + QTreeWidgetItem* item = solidItem; + + QFont boldFont = item->font( 0 ); + boldFont.setBold( true ); + + QString entry, label[3] = { tr("BLOCK_LABEL"), tr("V000_LABEL"), tr("V001_LABEL") }; + for ( int i = 0; i < 3; ++i ) + { + if ( i > 0 && ! (item = solidItem->child( i - 1 ))) + item = new QTreeWidgetItem( solidItem ); + + item->setText( 0, label[i] ); + item->setText( 1, toText( myGO[i], label[i], entry )); + item->setData( 1, Qt::UserRole, entry ); + item->setFont( 1, boldFont ); + item->setToolTip( 1, entry ); + } + myBlockTree->resizeColumnToContents( 0 ); + myBlockTree->resizeColumnToContents( 1 ); + } + for ( int i = 0; i < 3; ++i ) + { + myGO[i] = GEOM::GEOM_Object::_nil(); + myLineEdit[i]->setText(""); + } +} + +//================================================================================ +/*! + * \brief Transfer parameters from hypothesis to widgets + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::retrieveParams() const +{ + StdMeshersGUI_BlockRenumberCreator* me = const_cast( this ); + + StdMeshers::StdMeshers_BlockRenumber_var h = + StdMeshers::StdMeshers_BlockRenumber::_narrow( initParamsHypothesis() ); + + if( myName ) + me->myName->setText( hypName() ); + + me->myBlockTree->clear(); + + StdMeshers::blockcs_array_var blkArray = h->GetBlocksOrientation(); + for ( CORBA::ULong i = 0; i < blkArray->length(); ++i ) + { + me->myGO[0] = GEOM::GEOM_Object::_duplicate( blkArray[i].solid.in() ); + me->myGO[1] = GEOM::GEOM_Object::_duplicate( blkArray[i].vertex000.in() ); + me->myGO[2] = GEOM::GEOM_Object::_duplicate( blkArray[i].vertex001.in() ); + me->setBlockToTree(); + } + + me->myShapeSelectBut[0]->click(); + + me->updateButtons(); +} + +//================================================================================ +/*! + * \brief Transfer parameters from widgets to hypothesis + */ +//================================================================================ + +QString StdMeshersGUI_BlockRenumberCreator::storeParams() const +{ + StdMeshers::StdMeshers_BlockRenumber_var h = + StdMeshers::StdMeshers_BlockRenumber::_narrow( hypothesis() ); + + try + { + if( isCreation() ) + SMESH::SetName( SMESH::FindSObject( h ), myName->text().toUtf8().constData() ); + + StdMeshers::blockcs_array_var array = new StdMeshers::blockcs_array(); + array->length( myBlockTree->topLevelItemCount() ); + + for ( int i = 0; i < myBlockTree->topLevelItemCount(); ++i ) + { + StdMeshers::BlockCS& bcs = array[i]; + QTreeWidgetItem* item0 = myBlockTree->topLevelItem( i ); + QTreeWidgetItem* item1 = item0->child( 0 ); + QTreeWidgetItem* item2 = item0->child( 1 ); + + bcs.solid = toGeom( item0->data( 1, Qt::UserRole ).toString() )._retn(); + bcs.vertex000 = toGeom( item1->data( 1, Qt::UserRole ).toString() )._retn(); + bcs.vertex001 = toGeom( item2->data( 1, Qt::UserRole ).toString() )._retn(); + } + h->SetBlocksOrientation( array ); + + } + catch(const SALOME::SALOME_Exception& ex) + { + SalomeApp_Tools::QtCatchCorbaException(ex); + } + return ""; +} + +//================================================================================ +/*! + * \brief Take selected object + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::onSelectionChange() +{ + SALOME_ListIO list; + SMESHGUI::GetSMESHGUI()->selectionMgr()->selectedObjects( list ); + + int shapeID = myButGroup->checkedId(); + if ( shapeID < 0 || shapeID > 2 ) + shapeID = 0; + + myGO[ shapeID ] = GEOM::GEOM_Object::_nil(); + myLineEdit[ shapeID ]->clear(); + + if ( list.IsEmpty() ) + return; + + Handle(SALOME_InteractiveObject) io = list.First(); + if ( !io->hasEntry() ) + return; + + myGO[ shapeID ] = SMESH::IObjectToInterface( io ); + + if ( !myGO[ shapeID ]->_is_nil() ) + myLineEdit[ shapeID ]->setText( SMESH::toQStr( myGO[ shapeID ]->GetName() )); + + updateButtons(); +} + +//================================================================================ +/*! + * \brief Display selected block CS in myLineEdit's + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::onTreeSelectionChange() +{ + QList items = myBlockTree->selectedItems(); + for ( QTreeWidgetItem* item : items ) + { + if ( item->parent() ) + item = item->parent(); + + QTreeWidgetItem* items[3] = { item, item->child( 0 ), item->child( 1 ) }; + if ( items[1] && items[2] ) + for ( int i = 0; i < 3; ++i ) + { + myGO[i] = toGeom( items[i]->data( 1, Qt::UserRole ).toString() ); + myLineEdit[i]->setText( items[i]->text( 1 )); + } + + break; + } + + updateButtons(); +} + +//================================================================================ +/*! + * \brief Activate/deactivate buttons + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::updateButtons() +{ + bool isSolidInTree = findSolidInTree( myGO[0], myBlockTree ); + myAddBut ->setEnabled( !isSolidInTree && + !myGO[0]->_is_nil() && !myGO[1]->_is_nil() && !myGO[2]->_is_nil() ); + myModifBut ->setEnabled( isSolidInTree ); + myRemoveBut->setEnabled( !myBlockTree->selectedItems().isEmpty() || + myBlockTree->topLevelItemCount() == 1 ); +} + +//================================================================================ +/*! + * \brief Install filter upon activation of another object selection + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::onSelectBtnClick() +{ + int shapeID = myButGroup->checkedId(); + LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr(); + selMgr->clearFilters(); + selMgr->installFilter( shapeID > 0 ? &myVertexFilter : &mySolidFilter ); +} + +//================================================================================ +/*! + * \brief Add shapes to the tree + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::onAddBtnClick() +{ + setBlockToTree(); + updateButtons(); +} + +//================================================================================ +/*! + * \brief Modify a current block + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::onModifBtnClick() +{ + if ( QTreeWidgetItem* item = findSolidInTree( myGO[0], myBlockTree )) + { + setBlockToTree( item ); + } + updateButtons(); +} + +//================================================================================ +/*! + * \brief Remove selected block from the tree + */ +//================================================================================ + +void StdMeshersGUI_BlockRenumberCreator::onRemoveBtnClick() +{ + QList items = myBlockTree->selectedItems(); + if ( items.isEmpty() && myBlockTree->topLevelItemCount() == 1 ) + items.push_back( myBlockTree->topLevelItem( 0 )); + + for ( QTreeWidgetItem* item : items ) + { + if ( item->parent() ) + item = item->parent(); + delete item; + } + + updateButtons(); +} + + +//================================================================================ +/*! + * \brief Validate parameters + */ +//================================================================================ + +bool StdMeshersGUI_BlockRenumberCreator::checkParams( QString& msg ) const +{ + return true; +} + +//================================================================================ +/*! + * \brief Returns a name of help page + */ +//================================================================================ + +QString StdMeshersGUI_BlockRenumberCreator::helpPage() const +{ + return "3d_meshing_hypo.html#renumber-hypothesis"; +} + +//================================================================================ +/*! + * \brief Type name + */ +//================================================================================ + +QString StdMeshersGUI_BlockRenumberCreator::hypTypeName( const QString& ) const +{ + return "BLOCK_RENUMBER"; +} diff --git a/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.h b/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.h new file mode 100644 index 000000000..f3fe31d4f --- /dev/null +++ b/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.h @@ -0,0 +1,89 @@ +// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : StdMeshersGUI_BlockRenumberCreator.h +// Author : Open CASCADE S.A.S. +// +#ifndef STDMESHERSGUI_BlockRenumberCreator_H +#define STDMESHERSGUI_BlockRenumberCreator_H + +#include "SMESH_NumberFilter.hxx" +#include "SMESH_StdMeshersGUI.hxx" +#include "StdMeshersGUI_StdHypothesisCreator.h" + +#include +#include CORBA_SERVER_HEADER(GEOM_Gen) +//#include CORBA_SERVER_HEADER(SMESH_Hypothesis) + +class QButtonGroup; +class QLineEdit; +class QString; +class QTreeWidget; +class QTreeWidgetItem; + +class STDMESHERSGUI_EXPORT StdMeshersGUI_BlockRenumberCreator : public StdMeshersGUI_StdHypothesisCreator +{ + Q_OBJECT + +public: + StdMeshersGUI_BlockRenumberCreator( const QString& aHypType ); + ~StdMeshersGUI_BlockRenumberCreator(); + + virtual bool checkParams( QString& ) const override; + virtual QString helpPage() const override; + virtual QString hypTypeName( const QString& ) const override; + +protected: + virtual QFrame* buildFrame() override; + virtual void retrieveParams() const override; + virtual QString storeParams() const override; + +private slots: + void onSelectionChange(); + void onTreeSelectionChange(); + void updateButtons(); + void onSelectBtnClick(); + void onAddBtnClick(); + void onModifBtnClick(); + void onRemoveBtnClick(); + +private: + + void setBlockToTree( QTreeWidgetItem* item = 0 ); + + QLineEdit* myName; + QTreeWidget* myBlockTree; + + QPushButton* myShapeSelectBut[3]; + QButtonGroup* myButGroup; + QLineEdit* myLineEdit[3]; + + QPushButton* myAddBut; + QPushButton* myModifBut; + QPushButton* myRemoveBut; + + GEOM::GEOM_Object_var myGO[3]; + + SMESH_NumberFilter mySolidFilter, myVertexFilter; +}; + +#endif // STDMESHERSGUI_BlockRenumberCreator_H diff --git a/src/StdMeshersGUI/StdMeshers_images.ts b/src/StdMeshersGUI/StdMeshers_images.ts index 681bf7bed..3b41151ac 100644 --- a/src/StdMeshersGUI/StdMeshers_images.ts +++ b/src/StdMeshersGUI/StdMeshers_images.ts @@ -99,6 +99,10 @@ ICON_DLG_START_END_LENGTH mesh_hypo_length.png + + ICON_DLG_BLOCK_RENUMBER + mesh_tree_hypo_renumber.png + ICON_SELECT select1.png @@ -291,6 +295,10 @@ ICON_SMESH_TREE_HYPO_QuadraticMesh mesh_tree_hypo_quadratic.png + + ICON_SMESH_TREE_HYPO_BlockRenumber + mesh_tree_hypo_renumber.png + ICON_SMESH_TREE_HYPO_SegmentLengthAroundVertex mesh_tree_hypo_length.png diff --git a/src/StdMeshersGUI/StdMeshers_msg_en.ts b/src/StdMeshersGUI/StdMeshers_msg_en.ts index 089562445..b0df747b1 100644 --- a/src/StdMeshersGUI/StdMeshers_msg_en.ts +++ b/src/StdMeshersGUI/StdMeshers_msg_en.ts @@ -478,6 +478,14 @@ Consider creating another hypothesis instead of using this one for this mesh/sub SMESH_QUAD_TYPE Type + + SMESH_BLOCK_RENUMBER_TITLE + Hypothesis Construction + + + SMESH_BLOCK_RENUMBER_HYPOTHESIS + Renumber + StdMeshersGUI_QuadrangleParamWdg @@ -649,4 +657,55 @@ Consider creating another hypothesis instead of using this one for this mesh/sub Chain %1 (%2 edges) + + StdMeshersGUI_BlockRenumberCreator + + BLOCK_CS_GROUPBOX + Block coordinate system + + + SOLID + Solid + + + V000 + Vertex (0,0,0) + + + V001 + Vertex (0,0,1) + + + ADD + Add + + + MODIFY + Modify + + + COLUMN_BLOCK + Block + + + COLUMN_V000 + Vertex (0,0,0) + + + COLUMN_V001 + Vertex (0,0,1) + + + BLOCK_LABEL + Block: + + + V000_LABEL + Vertex (0,0,0): + + + V001_LABEL + Vertex (0,0,1): + + diff --git a/src/StdMeshers_I/CMakeLists.txt b/src/StdMeshers_I/CMakeLists.txt index e4e0f27f4..8dbfc245d 100644 --- a/src/StdMeshers_I/CMakeLists.txt +++ b/src/StdMeshers_I/CMakeLists.txt @@ -119,6 +119,7 @@ SET(StdMeshersEngine_HEADERS StdMeshers_Cartesian_3D_i.hxx StdMeshers_PolygonPerFace_2D_i.hxx StdMeshers_PolyhedronPerSolid_3D_i.hxx + StdMeshers_BlockRenumber_i.hxx ) IF(SALOME_SMESH_ENABLE_MEFISTO) SET(StdMeshersEngine_HEADERS ${StdMeshersEngine_HEADERS} StdMeshers_MEFISTO_2D_i.hxx) @@ -175,6 +176,7 @@ SET(StdMeshersEngine_SOURCES StdMeshers_Adaptive1D_i.cxx StdMeshers_PolygonPerFace_2D_i.cxx StdMeshers_PolyhedronPerSolid_3D_i.cxx + StdMeshers_BlockRenumber_i.cxx ) IF(SALOME_SMESH_ENABLE_MEFISTO) diff --git a/src/StdMeshers_I/StdMeshers_BlockRenumber_i.cxx b/src/StdMeshers_I/StdMeshers_BlockRenumber_i.cxx new file mode 100644 index 000000000..7c517cab6 --- /dev/null +++ b/src/StdMeshers_I/StdMeshers_BlockRenumber_i.cxx @@ -0,0 +1,189 @@ +// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes +// File : StdMeshers_BlockRenumber_i.cxx +// Author : Edward AGAPOV +// Module : SMESH +// $Header$ +// +#include "StdMeshers_ObjRefUlils.hxx" +#include "StdMeshers_BlockRenumber_i.hxx" +#include "SMESH_Gen_i.hxx" +#include "SMESH_Gen.hxx" +#include "SMESH_PythonDump.hxx" + +#include "Utils_CorbaException.hxx" + +//============================================================================= +/*! + * StdMeshers_BlockRenumber_i::StdMeshers_BlockRenumber_i + * + * Constructor + */ +//============================================================================= + +StdMeshers_BlockRenumber_i::StdMeshers_BlockRenumber_i( PortableServer::POA_ptr thePOA, + ::SMESH_Gen* theGenImpl ) + : SALOME::GenericObj_i( thePOA ), + SMESH_Hypothesis_i( thePOA ) +{ + myBaseImpl = new ::StdMeshers_BlockRenumber( theGenImpl->GetANewId(), + theGenImpl ); +} + +//================================================================================ +/*! + * \brief Set orientation of blocks + */ +//================================================================================ + +void StdMeshers_BlockRenumber_i::SetBlocksOrientation( const StdMeshers::blockcs_array& blockCS ) +{ + try { + SMESH_Comment dump; + CORBA::String_var entry; + std::vector< StdMeshers_BlockCS > bcsVec( blockCS.length() ); + for ( size_t i = 0; i < bcsVec.size(); i++ ) + { + StdMeshers_BlockCS& bcs = bcsVec[i]; + if ( !CORBA::is_nil( blockCS[i].solid ) && + !CORBA::is_nil( blockCS[i].vertex000 )&& + !CORBA::is_nil( blockCS[i].vertex001 )) + { + entry = blockCS[i].solid->GetStudyEntry(); + bcs._solid = entry.in(); + entry = blockCS[i].vertex000->GetStudyEntry(); + bcs._vertex000 = entry.in(); + entry = blockCS[i].vertex001->GetStudyEntry(); + bcs._vertex001 = entry.in(); + + if ( !dump.empty() ) dump << ",\n "; + dump << "StdMeshers.BlockCS( " + << bcs._solid << ", " << bcs._vertex000 << ", " << bcs._vertex001 + << " )"; + } + } + this->GetImpl()->SetBlocksOrientation( bcsVec ); + + // Update Python script + SMESH::TPythonDump() << _this() << ".SetBlocksOrientation([ " << dump << " ])"; + } + catch ( SALOME_Exception& S_ex ) { + THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM ); + } +} + +//================================================================================ +/*! + * \brief Return orientation of blocks + */ +//================================================================================ + +StdMeshers::blockcs_array* StdMeshers_BlockRenumber_i::GetBlocksOrientation() +{ + const std::vector< StdMeshers_BlockCS >& bcsVec = this->GetImpl()->GetBlocksOrientation(); + StdMeshers::blockcs_array_var bcsArray = new StdMeshers::blockcs_array(); + bcsArray->length( bcsVec.size() ); + TopoDS_Shape nullShape; + for ( size_t i = 0; i < bcsVec.size(); ++i ) + { + bcsArray[i].solid = + StdMeshers_ObjRefUlils::EntryOrShapeToGeomObject( bcsVec[i]._solid, nullShape ); + bcsArray[i].vertex000 = + StdMeshers_ObjRefUlils::EntryOrShapeToGeomObject( bcsVec[i]._vertex000, nullShape ); + bcsArray[i].vertex001 = + StdMeshers_ObjRefUlils::EntryOrShapeToGeomObject( bcsVec[i]._vertex001, nullShape ); + } + return bcsArray._retn(); +} + +//================================================================================ +/*! + * \brief Return geom entries + */ +//================================================================================ + +bool StdMeshers_BlockRenumber_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + const std::vector< StdMeshers_BlockCS >& bcsVec = + const_cast(this)->GetImpl()->GetBlocksOrientation(); + entryArray.reserve( entryArray.capacity() + 3 * bcsVec.size()); + for ( size_t i = 0; i < bcsVec.size(); ++i ) + { + entryArray.push_back( bcsVec[i]._solid ); + entryArray.push_back( bcsVec[i]._vertex000 ); + entryArray.push_back( bcsVec[i]._vertex001 ); + } + return !bcsVec.empty(); +} + +//================================================================================ +/*! + * \brief Update geom entries for a new geometry + */ +//================================================================================ + +bool StdMeshers_BlockRenumber_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + std::vector< StdMeshers_BlockCS > bcsVec( entryArray.size() / 3 ); + for ( size_t i = 0; i + 2 < entryArray.size(); i += 3 ) + { + StdMeshers_BlockCS& bcs = bcsVec[i]; + bcs._solid = entryArray[ i ]; + bcs._vertex000 = entryArray[ i + 1 ]; + bcs._vertex001 = entryArray[ i + 2 ]; + } + this->GetImpl()->SetBlocksOrientation( bcsVec ); + return true; +} + + +//============================================================================= +/*! + * StdMeshers_BlockRenumber_i::GetImpl + * + * Get implementation + */ +//============================================================================= + +::StdMeshers_BlockRenumber* StdMeshers_BlockRenumber_i::GetImpl() +{ + return ( ::StdMeshers_BlockRenumber* )myBaseImpl; +} + +//================================================================================ +/*! + * \brief Verify whether hypothesis supports given entity type + * \param type - dimension (see SMESH::Dimension enumeration) + * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise + * + * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration) + */ +//================================================================================ +CORBA::Boolean StdMeshers_BlockRenumber_i::IsDimSupported( SMESH::Dimension type ) +{ + return type == SMESH::DIM_3D; +} + diff --git a/src/StdMeshers_I/StdMeshers_BlockRenumber_i.hxx b/src/StdMeshers_I/StdMeshers_BlockRenumber_i.hxx new file mode 100644 index 000000000..42291fd04 --- /dev/null +++ b/src/StdMeshers_I/StdMeshers_BlockRenumber_i.hxx @@ -0,0 +1,76 @@ +// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : StdMeshers_BlockRenumber_i.hxx +// Author : Edward AGAPOV +// Module : SMESH +// +#ifndef _SMESH_BlockRenumber_I_HXX_ +#define _SMESH_BlockRenumber_I_HXX_ + +#include "SMESH_StdMeshers_I.hxx" + +#include +#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis) + +#include "SMESH_Hypothesis_i.hxx" +#include "StdMeshers_BlockRenumber.hxx" + +class SMESH_Gen; + +// ========================================================= +/*! + * \class 3D Hypothesis used by Hexahedron(ijk) algorithm + * to renumber mesh of a block to be structured-like + */ +// ========================================================= + +class STDMESHERS_I_EXPORT StdMeshers_BlockRenumber_i: + public virtual POA_StdMeshers::StdMeshers_BlockRenumber, + public virtual SMESH_Hypothesis_i +{ +public: + + StdMeshers_BlockRenumber_i( PortableServer::POA_ptr thePOA, + ::SMESH_Gen* theGenImpl ); + + // Set orientation of blocks + void SetBlocksOrientation( const StdMeshers::blockcs_array& blockCS ) override; + + // Return orientation of blocks + StdMeshers::blockcs_array* GetBlocksOrientation() override; + + + // Get implementation + ::StdMeshers_BlockRenumber* GetImpl(); + + // Verify whether hypothesis supports given entity type + CORBA::Boolean IsDimSupported( SMESH::Dimension type ) override; + + // Methods for copying mesh definition to other geometry + bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const override; + bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) override; +}; + +#endif diff --git a/src/StdMeshers_I/StdMeshers_i.cxx b/src/StdMeshers_I/StdMeshers_i.cxx index 2bd9e4eda..9038d2f58 100644 --- a/src/StdMeshers_I/StdMeshers_i.cxx +++ b/src/StdMeshers_I/StdMeshers_i.cxx @@ -34,6 +34,7 @@ #include "StdMeshers_Adaptive1D_i.hxx" #include "StdMeshers_Arithmetic1D_i.hxx" #include "StdMeshers_AutomaticLength_i.hxx" +#include "StdMeshers_BlockRenumber_i.hxx" #include "StdMeshers_CartesianParameters3D_i.hxx" #include "StdMeshers_Cartesian_3D_i.hxx" #include "StdMeshers_CompositeSegment_1D_i.hxx" @@ -207,6 +208,8 @@ STDMESHERS_I_EXPORT aCreator = new StdHypothesisCreator_i; else if (strcmp(aHypName, "CartesianParameters3D") == 0) aCreator = new StdHypothesisCreator_i; + else if (strcmp(aHypName, "BlockRenumber") == 0) + aCreator = new StdHypothesisCreator_i; // Algorithms else if (strcmp(aHypName, "Regular_1D") == 0)