Salome HOME
22487: EDF 2778 SMESH: Add a GUI for the flat elements generation
authoreap <eap@opencascade.com>
Wed, 19 Mar 2014 14:29:49 +0000 (18:29 +0400)
committereap <eap@opencascade.com>
Wed, 19 Mar 2014 14:29:49 +0000 (18:29 +0400)
17 files changed:
doc/salome/gui/SMESH/images/duplicate01.png
doc/salome/gui/SMESH/images/duplicate02.png
doc/salome/gui/SMESH/images/duplicate03.png
doc/salome/gui/SMESH/images/duplicate04.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/double_nodes_page.doc
idl/SMESH_MeshEditor.idl
resources/CMakeLists.txt
resources/mesh_duplicate_group_boundary.png [new file with mode: 0644]
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESHGUI/SMESHGUI_DuplicateNodesDlg.cxx
src/SMESHGUI/SMESHGUI_DuplicateNodesDlg.h
src/SMESHGUI/SMESH_images.ts
src/SMESHGUI/SMESH_msg_en.ts
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshBuilder.py

index 02938fa41019a144ee84a1c6cf1a3b6b59691360..f7acf902545a20eed3ce03fd5f5d6e7a04206dff 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/duplicate01.png and b/doc/salome/gui/SMESH/images/duplicate01.png differ
index 9653a3ea08806a2adc752317825b8e5da455c3f9..4bca6447695291b0f9c8d8b4b99ab36ece5680f0 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/duplicate02.png and b/doc/salome/gui/SMESH/images/duplicate02.png differ
index 72b2a7a80aea842007b8b8495e48d56d41f25acb..00c8c871f0b8e85527aa139f727d63a3435412bd 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/duplicate03.png and b/doc/salome/gui/SMESH/images/duplicate03.png differ
diff --git a/doc/salome/gui/SMESH/images/duplicate04.png b/doc/salome/gui/SMESH/images/duplicate04.png
new file mode 100644 (file)
index 0000000..70cb4ad
Binary files /dev/null and b/doc/salome/gui/SMESH/images/duplicate04.png differ
index 817a7e40aebba37684a37aa4fe3e38a15badc0da..c86f0bdc13d3144cb6493ead4434d4c0378fb7b6 100644 (file)
@@ -4,7 +4,7 @@
 
 \n This operation allows duplicating mesh nodes or/and elements, which can be useful to emulate a crack in the model.
 
-Duplication consists in creation of mesh element "equal" to existing ones.
+Duplication consists in creation of mesh elements "equal" to existing ones.
 
 <em>To duplicate nodes or/and elements:</em>
 <ol>
@@ -14,7 +14,7 @@ Duplication consists in creation of mesh element "equal" to existing ones.
 <br>
 \image html duplicate_nodes.png "Duplicate Nodes or/and Elements button"
 </li>
-<li>Check in the dialog box one of three radio buttons corresponding to
+<li>Check in the dialog box one of four radio buttons corresponding to
   the type of duplication operation you would like to perform.</li>
 <li>Fill the other fields available in the dialog box (depending on
   the chosen operation mode).</li>
@@ -22,11 +22,12 @@ Duplication consists in creation of mesh element "equal" to existing ones.
   operation of duplication.</li> 
 </ol>
 
-\n "Duplicate Nodes or/and Elements" dialog has three working modes:
+\n "Duplicate Nodes or/and Elements" dialog has four working modes:
 <ul>
 <li>\ref mode_without_elem_anchor "Duplicate nodes only"</li>
 <li>\ref mode_with_elem_anchor "Duplicate nodes and border elements"</li>
 <li>\ref mode_elem_only_anchor "Duplicate elements only"</li>
+<li>\ref mode_group_boundary_anchor "Duplicate nodes on group boundaries"</li>
 </ul>
 
 <br>
@@ -103,12 +104,11 @@ located at the "crack" (if any) are cloned automatically.
 <h2>Duplicate elements only</h2>
 
 This mode duplicates the given elements, i.e. creates new elements with the same nodes as the given elements.
-
 <br>
 
-
 \image html duplicate03.png
 
+Parameters to be defined in this mode:
 <ul>
 <li><b>Group of elements to duplicate</b> (<em>mandatory</em>): these
   elements will be duplicated.</li> 
@@ -118,6 +118,38 @@ This mode duplicates the given elements, i.e. creates new elements with the same
   "DoubleElements".</li>
 </ul>
 
+<br>
+\anchor mode_group_boundary_anchor
+<h2>Duplicate nodes on group boundaries</h2>
+
+This mode duplicates nodes located on boundaries between given groups of
+volumes. If required, flat elements are created on the duplicated
+nodes: a triangular facet shared by two volumes of two groups generates
+a flat prism, a quadrangular facet generates a flat hexahedron.
+<br>
+The created flat volumes are stored in groups. These groups are named
+according to the position of the group in the list of groups: group
+"j_n_p" is a group of flat elements that are built between the group \#n
+and the group \#p in the group list. All the flat elements are gathered
+into the group named "joints3D". The flat element of the multiple
+junctions between the simple junction are stored in a group named
+"jointsMultiples".
+
+<br>
+
+\image html duplicate04.png
+
+Parameters to be defined in this mode:
+<ul>
+<li><b>Groups of volumes</b> (<em>mandatory</em>): list of volume
+  groups. These groups should be disjoint, i.e. should not share volumes.</li>
+<li><b>Create joint elements</b> : if checked - the flat elements are created.</li>
+<li><b>On all boundaries</b> : if checked - then the volumes not
+  included into the <b>Groups of volumes</b> are considered as another given
+  group. And thus nodes on boundary between <b>Groups of volumes</b> and the
+  rest mesh are also duplicated.</li>
+</ul>
+
 <br><b>See Also</b> a sample TUI Script of a
  \ref tui_duplicate_nodes "Duplicate nodes or/and elements" operation.
 
index f52be7d13a7ce2808e3c212ef376b8bca3314aef..397efff4484f7a82b0ed83409978a0639fb31e3e 100644 (file)
@@ -1275,10 +1275,13 @@ module SMESH
      * Triangles are transformed in prisms, and quadrangles in hexahedrons.
      * \param theDomains - list of groups of volumes
      * \param createJointElems - if TRUE, create the elements
+     * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
+     *        the boundary between \a theDomains and the rest mesh
      * \return TRUE if operation has been completed successfully, FALSE otherwise
      */
     boolean DoubleNodesOnGroupBoundaries( in ListOfGroups theDomains,
-                                          in boolean createJointElems ) 
+                                          in boolean      createJointElems,
+                                          in boolean      onAllBoundaries) 
       raises (SALOME::SALOME_Exception);
 
     /*!
index fc5611aa8a2657418f96ee6aa3342b19f4491175..aeb0faf2edac471118e6849de198cf87bc67f5b6 100755 (executable)
@@ -197,6 +197,7 @@ SET(SMESH_RESOURCES_FILES
   mesh_duplicate_nodes.png
   mesh_duplicate_nodes_with_elem.png
   mesh_duplicate_elem_only.png
+  mesh_duplicate_group_boundary.png
   mesh_bounding_box.png
   mesh_hypo_viscous_layers.png
   mesh_tree_hypo_viscous_layers.png
diff --git a/resources/mesh_duplicate_group_boundary.png b/resources/mesh_duplicate_group_boundary.png
new file mode 100644 (file)
index 0000000..0de9a34
Binary files /dev/null and b/resources/mesh_duplicate_group_boundary.png differ
index 350fcd60f6f40b794f4687fbcb20050a5120e8d8..931caa43414d2a0aea00e1bffb4e2a288bf62963 100644 (file)
@@ -10563,7 +10563,12 @@ double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const
   gp_Vec v2(p0, g2);
   gp_Vec n1 = vref.Crossed(v1);
   gp_Vec n2 = vref.Crossed(v2);
-  return n2.AngleWithRef(n1, vref);
+  try {
+    return n2.AngleWithRef(n1, vref);
+  }
+  catch ( Standard_Failure ) {
+  }
+  return Max( v1.Magnitude(), v2.Magnitude() );
 }
 
 /*!
@@ -10576,13 +10581,16 @@ double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const
  * If there is no shared faces between the group #n and the group #p in the list, the group j_n_p is not created.
  * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
  * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
- * @param theElems - list of groups of volumes, where a group of volume is a set of
- * SMDS_MeshElements sorted by Id.
- * @param createJointElems - if TRUE, create the elements
- * @return TRUE if operation has been completed successfully, FALSE otherwise
+ * \param theElems - list of groups of volumes, where a group of volume is a set of
+ *        SMDS_MeshElements sorted by Id.
+ * \param createJointElems - if TRUE, create the elements
+ * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
+ *        the boundary between \a theDomains and the rest mesh
+ * \return TRUE if operation has been completed successfully, FALSE otherwise
  */
 bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
-                                                     bool createJointElems)
+                                                     bool                                 createJointElems,
+                                                     bool                                 onAllBoundaries)
 {
   MESSAGE("----------------------------------------------");
   MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries");
@@ -10611,15 +10619,20 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
 
   MESSAGE(".. Number of domains :"<<theElems.size());
 
+  TIDSortedElemSet theRestDomElems;
+  const int iRestDom  = -1;
+  const int idom0     = onAllBoundaries ? iRestDom : 0;
+  const int nbDomains = theElems.size();
+
   // Check if the domains do not share an element
-  for (int idom = 0; idom < theElems.size()-1; idom++)
+  for (int idom = 0; idom < nbDomains-1; idom++)
     {
 //       MESSAGE("... Check of domain #" << idom);
       const TIDSortedElemSet& domain = theElems[idom];
       TIDSortedElemSet::const_iterator elemItr = domain.begin();
       for (; elemItr != domain.end(); ++elemItr)
         {
-          SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
+          const SMDS_MeshElement* anElem = *elemItr;
           int idombisdeb = idom + 1 ;
           for (int idombis = idombisdeb; idombis < theElems.size(); idombis++) // check if the element belongs to a domain further in the list
           {
@@ -10635,7 +10648,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
         }
     }
 
-  for (int idom = 0; idom < theElems.size(); idom++)
+  for (int idom = 0; idom < nbDomains; idom++)
     {
 
       // --- build a map (face to duplicate --> volume to modify)
@@ -10648,7 +10661,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       TIDSortedElemSet::const_iterator elemItr = domain.begin();
       for (; elemItr != domain.end(); ++elemItr)
         {
-          SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
+          const SMDS_MeshElement* anElem = *elemItr;
           if (!anElem)
             continue;
           int vtkId = anElem->getVtkId();
@@ -10661,26 +10674,30 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             {
               int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
               const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
-              if (! domain.count(elem)) // neighbor is in another domain : face is shared
+              if (elem && ! domain.count(elem)) // neighbor is in another domain : face is shared
                 {
                   bool ok = false ;
-                  for (int idombis = 0; idombis < theElems.size(); idombis++) // check if the neighbor belongs to another domain of the list
+                  for (int idombis = 0; idombis < theElems.size() && !ok; idombis++) // check if the neighbor belongs to another domain of the list
                   {
                     // MESSAGE("Domain " << idombis);
                     const TIDSortedElemSet& domainbis = theElems[idombis];
                     if ( domainbis.count(elem)) ok = true ; // neighbor is in a correct domain : face is kept
                   }
-                  if ( ok ) // the characteristics of the face is stored
+                  if ( ok || onAllBoundaries ) // the characteristics of the face is stored
                   {
                     DownIdType face(downIds[n], downTypes[n]);
-                    if (!faceDomains.count(face))
-                      faceDomains[face] = emptyMap; // create an empty entry for face
                     if (!faceDomains[face].count(idom))
                       {
                         faceDomains[face][idom] = vtkId; // volume associated to face in this domain
                         celldom[vtkId] = idom;
                         //MESSAGE("       cell with a border " << vtkId << " domain " << idom);
                       }
+                    if ( !ok )
+                    {
+                      theRestDomElems.insert( elem );
+                      faceDomains[face][iRestDom] = neighborsVtkIds[n];
+                      celldom[neighborsVtkIds[n]] = iRestDom;
+                    }
                   }
                 }
             }
@@ -10694,14 +10711,14 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   //     explore the nodes of the face and see if they belong to a cell in the domain,
   //     which has only a node or an edge on the border (not a shared face)
 
-  for (int idomain = 0; idomain < theElems.size(); idomain++)
+  for (int idomain = idom0; idomain < nbDomains; idomain++)
     {
       //MESSAGE("Domain " << idomain);
-      const TIDSortedElemSet& domain = theElems[idomain];
+      const TIDSortedElemSet& domain = (idomain == iRestDom) ? theRestDomElems : theElems[idomain];
       itface = faceDomains.begin();
       for (; itface != faceDomains.end(); ++itface)
         {
-          std::map<int, int> domvol = itface->second;
+          const std::map<int, int>& domvol = itface->second;
           if (!domvol.count(idomain))
             continue;
           DownIdType face = itface->first;
@@ -10730,8 +10747,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                                 //no cells created after BuildDownWardConnectivity
                     }
                   DownIdType aCell(downId, vtkType);
-                  if (!cellDomains.count(aCell))
-                    cellDomains[aCell] = emptyMap; // create an empty entry for cell
                   cellDomains[aCell][idomain] = vtkId;
                   celldom[vtkId] = idomain;
                   //MESSAGE("       cell " << vtkId << " domain " << idomain);
@@ -10753,12 +10768,12 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   std::map<int, std::vector<int> > mutipleNodesToFace; // nodes multi domains with domain order to transform in Face (junction between 3 or more 2D domains)
 
   MESSAGE(".. Duplication of the nodes");
-  for (int idomain = 0; idomain < theElems.size(); idomain++)
+  for (int idomain = idom0; idomain < nbDomains; idomain++)
     {
       itface = faceDomains.begin();
       for (; itface != faceDomains.end(); ++itface)
         {
-          std::map<int, int> domvol = itface->second;
+          const std::map<int, int>& domvol = itface->second;
           if (!domvol.count(idomain))
             continue;
           DownIdType face = itface->first;
@@ -10770,15 +10785,12 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
           for (; itn != oldNodes.end(); ++itn)
             {
               int oldId = *itn;
-              //MESSAGE("-+-+-a node " << oldId);
-              if (!nodeDomains.count(oldId))
-                nodeDomains[oldId] = emptyMap; // create an empty entry for node
               if (nodeDomains[oldId].empty())
                 {
                   nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain
                   //MESSAGE("-+-+-b     oldNode " << oldId << " domain " << idomain);
                 }
-              std::map<int, int>::iterator itdom = domvol.begin();
+              std::map<int, int>::const_iterator itdom = domvol.begin();
               for (; itdom != domvol.end(); ++itdom)
                 {
                   int idom = itdom->first;
@@ -10816,7 +10828,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
     }
 
   MESSAGE(".. Creation of elements");
-  for (int idomain = 0; idomain < theElems.size(); idomain++)
+  for (int idomain = idom0; idomain < nbDomains; idomain++)
     {
       itface = faceDomains.begin();
       for (; itface != faceDomains.end(); ++itface)
@@ -10885,11 +10897,12 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                               for (int id=0; id < doms.size(); id++)
                                 {
                                   int idom = doms[id];
+                                  const TIDSortedElemSet& domain = (idom == iRestDom) ? theRestDomElems : theElems[idom];
                                   for (int ivol=0; ivol<nbvol; ivol++)
                                     {
                                       int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
                                       SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
-                                      if (theElems[idom].count(elem))
+                                      if (domain.count(elem))
                                         {
                                           SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
                                           domvol[idom] = svol;
@@ -11070,7 +11083,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   feDom.clear();
 
   MESSAGE(".. Modification of elements");
-  for (int idomain = 0; idomain < theElems.size(); idomain++)
+  for (int idomain = idom0; idomain < nbDomains; idomain++)
     {
       std::map<int, std::map<int, int> >::const_iterator itnod = nodeDomains.begin();
       for (; itnod != nodeDomains.end(); ++itnod)
index 84cd288c228146916cc0a5387764898f35ba9a07..865a395c96c2884f1d246553eaa53dc08d451d9d 100644 (file)
@@ -553,7 +553,8 @@ public:
   double OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const gp_Pnt& g1, const gp_Pnt& g2);
 
   bool DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
-                                     bool createJointElems);
+                                     bool                                 createJointElems,
+                                     bool                                 onAllBoundaries);
 
   bool CreateFlatElementsOnFacesGroups( const std::vector<TIDSortedElemSet>& theElems );
 
index 407984de7696ddc03d7aaf288c413128816aa198..924ad35894f6aa7e85c12eea0dc3b0ae28d14b6b 100644 (file)
@@ -110,6 +110,7 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
   QPixmap iconWithoutElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES")));
   QPixmap iconWithElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES_WITH_ELEM")));
   QPixmap iconElemOnly (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_ELEM_ONLY")));
+  QPixmap iconGrpBoundary (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_GROUP_BOUNDARY")));
   QPixmap iconSelect (aResMgr->loadPixmap("SMESH", tr("ICON_SELECT")));
 
   // Main layout
@@ -130,13 +131,17 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
   aRadioButton2->setIcon(iconWithElem);
   QRadioButton* aRadioButton3 = new QRadioButton(aConstructorsBox);
   aRadioButton3->setIcon(iconElemOnly);
+  QRadioButton* aRadioButton4 = new QRadioButton(aConstructorsBox);
+  aRadioButton4->setIcon(iconGrpBoundary);
   
   aConstructorsBoxLayout->addWidget(aRadioButton1);
   aConstructorsBoxLayout->addWidget(aRadioButton2);
   aConstructorsBoxLayout->addWidget(aRadioButton3);
+  aConstructorsBoxLayout->addWidget(aRadioButton4);
   myGroupConstructors->addButton(aRadioButton1, 0);
   myGroupConstructors->addButton(aRadioButton2, 1);
   myGroupConstructors->addButton(aRadioButton3, 2);
+  myGroupConstructors->addButton(aRadioButton4, 3);
 
   // Arguments
   myGroupArguments = new QGroupBox(this);
@@ -162,8 +167,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
   myLineEdit3 = new QLineEdit(myGroupArguments);
   myLineEdit3->setReadOnly(true);
 
-  myCheckBoxNewElemGroup = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments);
-  myCheckBoxNewNodeGroup = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments);
+  myCheckBox1 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments);
+  myCheckBox2 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments);
 
   aGroupArgumentsLayout->addWidget(myTextLabel1,    0, 0);
   aGroupArgumentsLayout->addWidget(mySelectButton1, 0, 1);
@@ -174,8 +179,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
   aGroupArgumentsLayout->addWidget(myTextLabel3,    2, 0);
   aGroupArgumentsLayout->addWidget(mySelectButton3, 2, 1);
   aGroupArgumentsLayout->addWidget(myLineEdit3,     2, 2);
-  aGroupArgumentsLayout->addWidget(myCheckBoxNewElemGroup, 3, 0);
-  aGroupArgumentsLayout->addWidget(myCheckBoxNewNodeGroup, 4, 0);
+  aGroupArgumentsLayout->addWidget(myCheckBox1, 3, 0);
+  aGroupArgumentsLayout->addWidget(myCheckBox2, 4, 0);
   aGroupArgumentsLayout->setRowStretch(5, 1);
   
   // Buttons
@@ -207,8 +212,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
   aMainLayout->addWidget(myGroupArguments);
   aMainLayout->addWidget(aGroupButtons);
   
-  myCheckBoxNewElemGroup->setChecked(true);
-  myCheckBoxNewNodeGroup->setChecked(true);
+  myCheckBox1->setChecked(true);
+  myCheckBox2->setChecked(true);
 
   // Initialize the dialog
   Init();
@@ -223,6 +228,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
   connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
   connect(mySelectButton3, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
 
+  connect(myCheckBox2,    SIGNAL(stateChanged(int)), SLOT(updateButtons()));
+
   connect(myButtonOk,     SIGNAL(clicked()), this, SLOT(onOk()));
   connect(myButtonClose,  SIGNAL(clicked()), this, SLOT(reject()));
   connect(myButtonApply,  SIGNAL(clicked()), this, SLOT(onApply()));
@@ -298,8 +305,9 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
       myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE"));
       myTextLabel2->setText(tr("GROUP_NODES_TO_REPLACE"));
 
-      myCheckBoxNewElemGroup->hide();
-      myCheckBoxNewNodeGroup->show();
+      myCheckBox1->hide();
+      myCheckBox2->show();
+      myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
       
       // Hide the third field
       myTextLabel2->show();
@@ -319,8 +327,10 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
       myTextLabel2->setText(tr("GROUP_NODES_NOT_DUPLICATE"));
       myTextLabel3->setText(tr("GROUP_ELEMS_TO_REPLACE"));
       
-      myCheckBoxNewElemGroup->show();
-      myCheckBoxNewNodeGroup->show();
+      myCheckBox1->show();
+      myCheckBox2->show();
+      myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
+      myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
 
       // Show the third field
       myTextLabel2->show();
@@ -338,8 +348,30 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
       myGroupArguments->setTitle(tr("DUPLICATION_ONLY_ELEMS"));
       myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
       
-      myCheckBoxNewElemGroup->show();
-      myCheckBoxNewNodeGroup->hide();
+      myCheckBox1->show();
+      myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
+      myCheckBox2->hide();
+
+      // Hide the second and the third field
+      myTextLabel2->hide();
+      mySelectButton2->hide();
+      myLineEdit2->hide();
+      myTextLabel3->hide();
+      mySelectButton3->hide();
+      myLineEdit3->hide();
+
+      break;
+    }
+  case 3:
+    {
+      // Set text to the group of arguments and to all the labels
+      myGroupArguments->setTitle(tr("DUPLICATION_GROUP_BOUNDARY"));
+      myTextLabel1->setText(tr("GROUP_VOLUME_GROUPS"));
+      
+      myCheckBox1->show();
+      myCheckBox2->show();
+      myCheckBox1->setText( tr("CREATE_JOINT_ELEMENTS"));
+      myCheckBox2->setText( tr("ON_ALL_BOUNDARIES"));
 
       // Hide the second and the third field
       myTextLabel2->hide();
@@ -367,8 +399,8 @@ bool SMESHGUI_DuplicateNodesDlg::onApply()
 
   BusyLocker lock( myBusy );
  
-  bool toCreateElemGroup = myCheckBoxNewElemGroup->isChecked();
-  bool toCreateNodeGroup = myCheckBoxNewNodeGroup->isChecked();
+  bool toCreateElemGroup = myCheckBox1->isChecked();
+  bool toCreateNodeGroup = myCheckBox2->isChecked();
   int operationMode      = myGroupConstructors->checkedId();
   
   // Apply changes
@@ -451,14 +483,28 @@ bool SMESHGUI_DuplicateNodesDlg::onApply()
       }
       break;
     }
+    case 3:
+    {
+      bool createJointElems = myCheckBox1->isChecked();
+      bool onAllBoundaries  = myCheckBox2->isChecked();
+
+      SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
+      g1->length( myGroups1.count() );
+      for ( int i = 0; i < myGroups1.count(); i++ )
+        g1[i] = myGroups1[i];
+
+      result = aMeshEditor->DoubleNodesOnGroupBoundaries( g1.in(), createJointElems, onAllBoundaries );
+
+      break;
     }
+    } // switch( operationMode )
   }
   catch (const SALOME::SALOME_Exception& S_ex) {
     SalomeApp_Tools::QtCatchCorbaException(S_ex);
   }
   catch ( const std::exception& exc ) {
     INFOS( "Follow exception was cought:\n\t" << exc.what() );
-  } 
+  }
   catch (...) {
     INFOS( "Unknown exception was cought !!!" );
   }
@@ -553,6 +599,9 @@ void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
       case 2:
         ok = ( aGroupType != SMESH::NODE );
         break;
+      case 3:
+        ok = ( aGroupType == SMESH::VOLUME );
+        break;
       }
     }
     if ( ok ) aGroups << aGroup;
@@ -575,8 +624,15 @@ void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
     else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3.clear();
     myCurrentLineEdit->clear();
   }
-
   // Enable/disable "Apply and Close" and "Apply" buttons
+  updateButtons();
+}
+
+/*!
+ * \brief Enable/disable "Apply and Close" and "Apply" buttons
+ */
+void SMESHGUI_DuplicateNodesDlg::updateButtons()
+{
   bool isDataValid = isValid();
   myButtonOk->setEnabled( isDataValid );
   myButtonApply->setEnabled( isDataValid );
@@ -610,12 +666,15 @@ void SMESHGUI_DuplicateNodesDlg::onEditCurrentArgument()
 */
 bool SMESHGUI_DuplicateNodesDlg::isValid()
 {
-  return myGroupConstructors->checkedId() == 1 ?
-    ( !myGroups1.isEmpty() && !myGroups3.isEmpty()  ) :
-    ( !myGroups1.isEmpty() );
+  switch( myGroupConstructors->checkedId() )
+  {
+  case 1:  return ( !myGroups1.isEmpty() && !myGroups3.isEmpty()  );
+  case 3:  return ( myGroups1.count() > ( myCheckBox2->isChecked() ? 0 : 1 ));
+  default: return !myGroups1.isEmpty();
+  }
+  return false;
 }
 
-
 /*!
   \brief SLOT called when dialog shoud be deativated.
 */
index 847cbf163cda5e720ee97047cfa19cf3ee759aed..5bf5247d292f9e606bbe6e4a60a2944321b5a6ae 100644 (file)
@@ -83,6 +83,8 @@ private slots:
 
   void                    onDeactivate();
 
+  void                    updateButtons();
+
 private:
   QLineEdit*              myCurrentLineEdit;
   
@@ -98,8 +100,8 @@ private:
   QLineEdit*              myLineEdit1;
   QLineEdit*              myLineEdit2;
   QLineEdit*              myLineEdit3;
-  QCheckBox*              myCheckBoxNewElemGroup;
-  QCheckBox*              myCheckBoxNewNodeGroup;
+  QCheckBox*              myCheckBox1;
+  QCheckBox*              myCheckBox2;
 
   QPushButton*            myButtonOk;
   QPushButton*            myButtonApply;
index c985f167e22847b3fcbd038587df8ad91dd37f9a..f9082a77b06748f7e36bee9f42d4ae56c0d7123a 100644 (file)
             <source>ICON_SMESH_DUPLICATE_NODES_WITH_ELEM</source>
             <translation>mesh_duplicate_nodes_with_elem.png</translation>
         </message>
-           <message>
+        <message>
             <source>ICON_SMESH_DUPLICATE_ELEM_ONLY</source>
             <translation>mesh_duplicate_elem_only.png</translation>
         </message>
+        <message>
+            <source>ICON_SMESH_DUPLICATE_GROUP_BOUNDARY</source>
+            <translation>mesh_duplicate_group_boundary.png</translation>
+        </message>
         <message>
             <source>ICON_SMESH_TREE_ALGO</source>
             <translation>mesh_tree_algo.png</translation>
index ec5ab322c34bf447e7e4d8ce70447f411c1ea014..350444ec3758c661e177c670e2959460cabf3894 100644 (file)
@@ -6752,6 +6752,10 @@ It is impossible to read point coordinates from file</translation>
         <source>DUPLICATION_ONLY_ELEMS</source>
         <translation>Duplicate elements only</translation>
     </message>
+    <message>
+        <source>DUPLICATION_GROUP_BOUNDARY</source>
+        <translation>Duplicate nodes on group boundaries</translation>
+    </message>
     <message>
         <source>GROUP_ELEMS_TO_DUPLICATE</source>
         <translation>Group of elements to duplicate</translation>
@@ -6764,6 +6768,10 @@ It is impossible to read point coordinates from file</translation>
         <source>GROUP_ELEMS_TO_REPLACE</source>
         <translation>Group of elements to replace nodes with new ones</translation>
     </message>
+    <message>
+        <source>GROUP_VOLUME_GROUPS</source>
+        <translation>Groups of volumes</translation>
+    </message>
     <message>
         <source>CONSTRUCT_NEW_GROUP_NODES</source>
         <translation>Construct group with newly created nodes</translation>
@@ -6772,6 +6780,14 @@ It is impossible to read point coordinates from file</translation>
         <source>CONSTRUCT_NEW_GROUP_ELEMENTS</source>
         <translation>Construct group with newly created elements</translation>
     </message>
+    <message>
+        <source>CREATE_JOINT_ELEMENTS</source>
+        <translation>Create joint elements</translation>
+    </message>
+    <message>
+        <source>ON_ALL_BOUNDARIES</source>
+        <translation>On all boundaries</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_Make2DFrom3DDlg</name>
index 5d52e717751c1b43e7ff2220d47948bfe12a372d..9de57c975706a25fbf79216219c01df44de7816e 100644 (file)
@@ -6875,18 +6875,21 @@ CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
  * If there is no shared faces between the group #n and the group #p in the list, the group j_n_p is not created.
  * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
  * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
- * @param theDomains - list of groups of volumes
- * @param createJointElems - if TRUE, create the elements
- * @return TRUE if operation has been completed successfully, FALSE otherwise
+ * \param theDomains - list of groups of volumes
+ * \param createJointElems - if TRUE, create the elements
+ * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
+ *        the boundary between \a theDomains and the rest mesh
+ * \return TRUE if operation has been completed successfully, FALSE otherwise
  */
 //================================================================================
 
 CORBA::Boolean
 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
-                                                  CORBA::Boolean             createJointElems )
+                                                  CORBA::Boolean             createJointElems,
+                                                  CORBA::Boolean             onAllBoundaries )
   throw (SALOME::SALOME_Exception)
 {
-  bool aResult = false;
+  bool isOK = false;
 
   SMESH_TRY;
   initData();
@@ -6894,10 +6897,11 @@ SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& the
   SMESHDS_Mesh* aMeshDS = getMeshDS();
 
   // MESSAGE("theDomains.length = "<<theDomains.length());
-  if ( theDomains.length() <= 1 )
+  if ( theDomains.length() <= 1 && !onAllBoundaries )
     THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
+
   vector<TIDSortedElemSet> domains;
-  domains.clear();
+  domains.resize( theDomains.length() );
 
   for ( int i = 0, n = theDomains.length(); i < n; i++ )
   {
@@ -6906,26 +6910,25 @@ SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& the
     {
 //      if ( aGrp->GetType() != SMESH::VOLUME )
 //        THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
-      TIDSortedElemSet domain;
-      domain.clear();
-      domains.push_back(domain);
       SMESH::long_array_var anIDs = aGrp->GetIDs();
       arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
     }
   }
 
-  aResult = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems );
+  isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
   // TODO publish the groups of flat elements in study
 
-  declareMeshModified( /*isReComputeSafe=*/ !aResult );
+  declareMeshModified( /*isReComputeSafe=*/ !isOK );
 
   // Update Python script
   TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
-      << ", " << createJointElems << " )";
+                << ", " << createJointElems << ", " << onAllBoundaries << " )";
 
   SMESH_CATCH( SMESH::throwCorbaException );
 
-  return aResult;
+  myMesh_i->CreateGroupServants(); // publish created groups if any
+
+  return isOK;
 }
 
 //================================================================================
index 87682048b943b4f3a414934a7b1351f5a89ca9a9..ead3048b05607721d39a334cef77fd3b6c75c736 100644 (file)
@@ -923,12 +923,15 @@ public:
    * The nodes of the internal faces at the boundaries of the groups are doubled.
    * In option, the internal faces are replaced by flat elements.
    * Triangles are transformed in prisms, and quadrangles in hexahedrons.
-   * @param theDomains - list of groups of volumes
-   * @param createJointElems - if TRUE, create the elements
-   * @return TRUE if operation has been completed successfully, FALSE otherwise
+   * \param theDomains - list of groups of volumes
+   * \param createJointElems - if TRUE, create the elements
+   * \param onAllBoundaries - if TRUE, the nodes and elements are also create on
+   *        the boundary between \a theDomains and the rest mesh
+   * \return TRUE if operation has been completed successfully, FALSE otherwise
    */
   CORBA::Boolean DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
-                                               CORBA::Boolean createJointElems )
+                                               CORBA::Boolean             createJointElems,
+                                               CORBA::Boolean             onAllBoundaries )
     throw (SALOME::SALOME_Exception);
   /*!
    * \brief Double nodes on some external faces and create flat elements.
index 262685a4324ed370f9174507adea3bc1170994ff..223cf9130641d3992182d67b70e9cba067548986 100644 (file)
@@ -4503,9 +4503,11 @@ class Mesh:
     # Triangles are transformed in prisms, and quadrangles in hexahedrons.
     # @param theDomains - list of groups of volumes
     # @param createJointElems - if TRUE, create the elements
+    # @param onAllBoundaries - if TRUE, the nodes and elements are also created on
+    #        the boundary between \a theDomains and the rest mesh
     # @return TRUE if operation has been completed successfully, FALSE otherwise
-    def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems ):
-       return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems )
+    def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
+       return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
 
     ## Double nodes on some external faces and create flat elements.
     # Flat elements are mainly used by some types of mechanic calculations.