22487: EDF 2778 SMESH: Add a GUI for the flat elements generation

This commit is contained in:
eap 2014-03-19 18:29:49 +04:00
parent cd3fc5209f
commit 9ab3722c1b
17 changed files with 218 additions and 79 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View 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. \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> <em>To duplicate nodes or/and elements:</em>
<ol> <ol>
@ -14,7 +14,7 @@ Duplication consists in creation of mesh element "equal" to existing ones.
<br> <br>
\image html duplicate_nodes.png "Duplicate Nodes or/and Elements button" \image html duplicate_nodes.png "Duplicate Nodes or/and Elements button"
</li> </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> the type of duplication operation you would like to perform.</li>
<li>Fill the other fields available in the dialog box (depending on <li>Fill the other fields available in the dialog box (depending on
the chosen operation mode).</li> the chosen operation mode).</li>
@ -22,11 +22,12 @@ Duplication consists in creation of mesh element "equal" to existing ones.
operation of duplication.</li> operation of duplication.</li>
</ol> </ol>
\n "Duplicate Nodes or/and Elements" dialog has three working modes: \n "Duplicate Nodes or/and Elements" dialog has four working modes:
<ul> <ul>
<li>\ref mode_without_elem_anchor "Duplicate nodes only"</li> <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_with_elem_anchor "Duplicate nodes and border elements"</li>
<li>\ref mode_elem_only_anchor "Duplicate elements only"</li> <li>\ref mode_elem_only_anchor "Duplicate elements only"</li>
<li>\ref mode_group_boundary_anchor "Duplicate nodes on group boundaries"</li>
</ul> </ul>
<br> <br>
@ -103,12 +104,11 @@ located at the "crack" (if any) are cloned automatically.
<h2>Duplicate elements only</h2> <h2>Duplicate elements only</h2>
This mode duplicates the given elements, i.e. creates new elements with the same nodes as the given elements. This mode duplicates the given elements, i.e. creates new elements with the same nodes as the given elements.
<br> <br>
\image html duplicate03.png \image html duplicate03.png
Parameters to be defined in this mode:
<ul> <ul>
<li><b>Group of elements to duplicate</b> (<em>mandatory</em>): these <li><b>Group of elements to duplicate</b> (<em>mandatory</em>): these
elements will be duplicated.</li> 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> "DoubleElements".</li>
</ul> </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 <br><b>See Also</b> a sample TUI Script of a
\ref tui_duplicate_nodes "Duplicate nodes or/and elements" operation. \ref tui_duplicate_nodes "Duplicate nodes or/and elements" operation.

View File

@ -1275,10 +1275,13 @@ module SMESH
* Triangles are transformed in prisms, and quadrangles in hexahedrons. * Triangles are transformed in prisms, and quadrangles in hexahedrons.
* \param theDomains - list of groups of volumes * \param theDomains - list of groups of volumes
* \param createJointElems - if TRUE, create the elements * \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 * \return TRUE if operation has been completed successfully, FALSE otherwise
*/ */
boolean DoubleNodesOnGroupBoundaries( in ListOfGroups theDomains, boolean DoubleNodesOnGroupBoundaries( in ListOfGroups theDomains,
in boolean createJointElems ) in boolean createJointElems,
in boolean onAllBoundaries)
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
/*! /*!

View File

@ -197,6 +197,7 @@ SET(SMESH_RESOURCES_FILES
mesh_duplicate_nodes.png mesh_duplicate_nodes.png
mesh_duplicate_nodes_with_elem.png mesh_duplicate_nodes_with_elem.png
mesh_duplicate_elem_only.png mesh_duplicate_elem_only.png
mesh_duplicate_group_boundary.png
mesh_bounding_box.png mesh_bounding_box.png
mesh_hypo_viscous_layers.png mesh_hypo_viscous_layers.png
mesh_tree_hypo_viscous_layers.png mesh_tree_hypo_viscous_layers.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

View 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 v2(p0, g2);
gp_Vec n1 = vref.Crossed(v1); gp_Vec n1 = vref.Crossed(v1);
gp_Vec n2 = vref.Crossed(v2); 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. * 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). * 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". * 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 * \param theElems - list of groups of volumes, where a group of volume is a set of
* SMDS_MeshElements sorted by Id. * SMDS_MeshElements sorted by Id.
* @param createJointElems - if TRUE, create the elements * \param createJointElems - if TRUE, create the elements
* @return TRUE if operation has been completed successfully, FALSE otherwise * \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 SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
bool createJointElems) bool createJointElems,
bool onAllBoundaries)
{ {
MESSAGE("----------------------------------------------"); MESSAGE("----------------------------------------------");
MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries"); MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries");
@ -10611,15 +10619,20 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
MESSAGE(".. Number of domains :"<<theElems.size()); 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 // 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); // MESSAGE("... Check of domain #" << idom);
const TIDSortedElemSet& domain = theElems[idom]; const TIDSortedElemSet& domain = theElems[idom];
TIDSortedElemSet::const_iterator elemItr = domain.begin(); TIDSortedElemSet::const_iterator elemItr = domain.begin();
for (; elemItr != domain.end(); ++elemItr) for (; elemItr != domain.end(); ++elemItr)
{ {
SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr; const SMDS_MeshElement* anElem = *elemItr;
int idombisdeb = idom + 1 ; int idombisdeb = idom + 1 ;
for (int idombis = idombisdeb; idombis < theElems.size(); idombis++) // check if the element belongs to a domain further in the list 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) // --- 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(); TIDSortedElemSet::const_iterator elemItr = domain.begin();
for (; elemItr != domain.end(); ++elemItr) for (; elemItr != domain.end(); ++elemItr)
{ {
SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr; const SMDS_MeshElement* anElem = *elemItr;
if (!anElem) if (!anElem)
continue; continue;
int vtkId = anElem->getVtkId(); int vtkId = anElem->getVtkId();
@ -10661,26 +10674,30 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
{ {
int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]); int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); 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 ; 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); // MESSAGE("Domain " << idombis);
const TIDSortedElemSet& domainbis = theElems[idombis]; const TIDSortedElemSet& domainbis = theElems[idombis];
if ( domainbis.count(elem)) ok = true ; // neighbor is in a correct domain : face is kept 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]); DownIdType face(downIds[n], downTypes[n]);
if (!faceDomains.count(face))
faceDomains[face] = emptyMap; // create an empty entry for face
if (!faceDomains[face].count(idom)) if (!faceDomains[face].count(idom))
{ {
faceDomains[face][idom] = vtkId; // volume associated to face in this domain faceDomains[face][idom] = vtkId; // volume associated to face in this domain
celldom[vtkId] = idom; celldom[vtkId] = idom;
//MESSAGE(" cell with a border " << vtkId << " domain " << 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, // 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) // 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); //MESSAGE("Domain " << idomain);
const TIDSortedElemSet& domain = theElems[idomain]; const TIDSortedElemSet& domain = (idomain == iRestDom) ? theRestDomElems : theElems[idomain];
itface = faceDomains.begin(); itface = faceDomains.begin();
for (; itface != faceDomains.end(); ++itface) for (; itface != faceDomains.end(); ++itface)
{ {
std::map<int, int> domvol = itface->second; const std::map<int, int>& domvol = itface->second;
if (!domvol.count(idomain)) if (!domvol.count(idomain))
continue; continue;
DownIdType face = itface->first; DownIdType face = itface->first;
@ -10730,8 +10747,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
//no cells created after BuildDownWardConnectivity //no cells created after BuildDownWardConnectivity
} }
DownIdType aCell(downId, vtkType); DownIdType aCell(downId, vtkType);
if (!cellDomains.count(aCell))
cellDomains[aCell] = emptyMap; // create an empty entry for cell
cellDomains[aCell][idomain] = vtkId; cellDomains[aCell][idomain] = vtkId;
celldom[vtkId] = idomain; celldom[vtkId] = idomain;
//MESSAGE(" cell " << vtkId << " domain " << 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) 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"); MESSAGE(".. Duplication of the nodes");
for (int idomain = 0; idomain < theElems.size(); idomain++) for (int idomain = idom0; idomain < nbDomains; idomain++)
{ {
itface = faceDomains.begin(); itface = faceDomains.begin();
for (; itface != faceDomains.end(); ++itface) for (; itface != faceDomains.end(); ++itface)
{ {
std::map<int, int> domvol = itface->second; const std::map<int, int>& domvol = itface->second;
if (!domvol.count(idomain)) if (!domvol.count(idomain))
continue; continue;
DownIdType face = itface->first; DownIdType face = itface->first;
@ -10770,15 +10785,12 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
for (; itn != oldNodes.end(); ++itn) for (; itn != oldNodes.end(); ++itn)
{ {
int oldId = *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()) if (nodeDomains[oldId].empty())
{ {
nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain
//MESSAGE("-+-+-b oldNode " << oldId << " domain " << idomain); //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) for (; itdom != domvol.end(); ++itdom)
{ {
int idom = itdom->first; int idom = itdom->first;
@ -10816,7 +10828,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
} }
MESSAGE(".. Creation of elements"); MESSAGE(".. Creation of elements");
for (int idomain = 0; idomain < theElems.size(); idomain++) for (int idomain = idom0; idomain < nbDomains; idomain++)
{ {
itface = faceDomains.begin(); itface = faceDomains.begin();
for (; itface != faceDomains.end(); ++itface) 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++) for (int id=0; id < doms.size(); id++)
{ {
int idom = doms[id]; int idom = doms[id];
const TIDSortedElemSet& domain = (idom == iRestDom) ? theRestDomElems : theElems[idom];
for (int ivol=0; ivol<nbvol; ivol++) for (int ivol=0; ivol<nbvol; ivol++)
{ {
int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]); int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId); 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); SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
domvol[idom] = svol; domvol[idom] = svol;
@ -11070,7 +11083,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
feDom.clear(); feDom.clear();
MESSAGE(".. Modification of elements"); 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(); std::map<int, std::map<int, int> >::const_iterator itnod = nodeDomains.begin();
for (; itnod != nodeDomains.end(); ++itnod) for (; itnod != nodeDomains.end(); ++itnod)

View File

@ -553,7 +553,8 @@ public:
double OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const gp_Pnt& g1, const gp_Pnt& g2); 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 DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
bool createJointElems); bool createJointElems,
bool onAllBoundaries);
bool CreateFlatElementsOnFacesGroups( const std::vector<TIDSortedElemSet>& theElems ); bool CreateFlatElementsOnFacesGroups( const std::vector<TIDSortedElemSet>& theElems );

View File

@ -110,6 +110,7 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
QPixmap iconWithoutElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES"))); QPixmap iconWithoutElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES")));
QPixmap iconWithElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES_WITH_ELEM"))); QPixmap iconWithElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES_WITH_ELEM")));
QPixmap iconElemOnly (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_ELEM_ONLY"))); 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"))); QPixmap iconSelect (aResMgr->loadPixmap("SMESH", tr("ICON_SELECT")));
// Main layout // Main layout
@ -130,13 +131,17 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
aRadioButton2->setIcon(iconWithElem); aRadioButton2->setIcon(iconWithElem);
QRadioButton* aRadioButton3 = new QRadioButton(aConstructorsBox); QRadioButton* aRadioButton3 = new QRadioButton(aConstructorsBox);
aRadioButton3->setIcon(iconElemOnly); aRadioButton3->setIcon(iconElemOnly);
QRadioButton* aRadioButton4 = new QRadioButton(aConstructorsBox);
aRadioButton4->setIcon(iconGrpBoundary);
aConstructorsBoxLayout->addWidget(aRadioButton1); aConstructorsBoxLayout->addWidget(aRadioButton1);
aConstructorsBoxLayout->addWidget(aRadioButton2); aConstructorsBoxLayout->addWidget(aRadioButton2);
aConstructorsBoxLayout->addWidget(aRadioButton3); aConstructorsBoxLayout->addWidget(aRadioButton3);
aConstructorsBoxLayout->addWidget(aRadioButton4);
myGroupConstructors->addButton(aRadioButton1, 0); myGroupConstructors->addButton(aRadioButton1, 0);
myGroupConstructors->addButton(aRadioButton2, 1); myGroupConstructors->addButton(aRadioButton2, 1);
myGroupConstructors->addButton(aRadioButton3, 2); myGroupConstructors->addButton(aRadioButton3, 2);
myGroupConstructors->addButton(aRadioButton4, 3);
// Arguments // Arguments
myGroupArguments = new QGroupBox(this); myGroupArguments = new QGroupBox(this);
@ -162,8 +167,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
myLineEdit3 = new QLineEdit(myGroupArguments); myLineEdit3 = new QLineEdit(myGroupArguments);
myLineEdit3->setReadOnly(true); myLineEdit3->setReadOnly(true);
myCheckBoxNewElemGroup = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments); myCheckBox1 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments);
myCheckBoxNewNodeGroup = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments); myCheckBox2 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments);
aGroupArgumentsLayout->addWidget(myTextLabel1, 0, 0); aGroupArgumentsLayout->addWidget(myTextLabel1, 0, 0);
aGroupArgumentsLayout->addWidget(mySelectButton1, 0, 1); aGroupArgumentsLayout->addWidget(mySelectButton1, 0, 1);
@ -174,8 +179,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
aGroupArgumentsLayout->addWidget(myTextLabel3, 2, 0); aGroupArgumentsLayout->addWidget(myTextLabel3, 2, 0);
aGroupArgumentsLayout->addWidget(mySelectButton3, 2, 1); aGroupArgumentsLayout->addWidget(mySelectButton3, 2, 1);
aGroupArgumentsLayout->addWidget(myLineEdit3, 2, 2); aGroupArgumentsLayout->addWidget(myLineEdit3, 2, 2);
aGroupArgumentsLayout->addWidget(myCheckBoxNewElemGroup, 3, 0); aGroupArgumentsLayout->addWidget(myCheckBox1, 3, 0);
aGroupArgumentsLayout->addWidget(myCheckBoxNewNodeGroup, 4, 0); aGroupArgumentsLayout->addWidget(myCheckBox2, 4, 0);
aGroupArgumentsLayout->setRowStretch(5, 1); aGroupArgumentsLayout->setRowStretch(5, 1);
// Buttons // Buttons
@ -207,8 +212,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
aMainLayout->addWidget(myGroupArguments); aMainLayout->addWidget(myGroupArguments);
aMainLayout->addWidget(aGroupButtons); aMainLayout->addWidget(aGroupButtons);
myCheckBoxNewElemGroup->setChecked(true); myCheckBox1->setChecked(true);
myCheckBoxNewNodeGroup->setChecked(true); myCheckBox2->setChecked(true);
// Initialize the dialog // Initialize the dialog
Init(); Init();
@ -223,6 +228,8 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument())); connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
connect(mySelectButton3, 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(myButtonOk, SIGNAL(clicked()), this, SLOT(onOk()));
connect(myButtonClose, SIGNAL(clicked()), this, SLOT(reject())); connect(myButtonClose, SIGNAL(clicked()), this, SLOT(reject()));
connect(myButtonApply, SIGNAL(clicked()), this, SLOT(onApply())); connect(myButtonApply, SIGNAL(clicked()), this, SLOT(onApply()));
@ -298,8 +305,9 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE")); myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE"));
myTextLabel2->setText(tr("GROUP_NODES_TO_REPLACE")); myTextLabel2->setText(tr("GROUP_NODES_TO_REPLACE"));
myCheckBoxNewElemGroup->hide(); myCheckBox1->hide();
myCheckBoxNewNodeGroup->show(); myCheckBox2->show();
myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
// Hide the third field // Hide the third field
myTextLabel2->show(); myTextLabel2->show();
@ -319,8 +327,10 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
myTextLabel2->setText(tr("GROUP_NODES_NOT_DUPLICATE")); myTextLabel2->setText(tr("GROUP_NODES_NOT_DUPLICATE"));
myTextLabel3->setText(tr("GROUP_ELEMS_TO_REPLACE")); myTextLabel3->setText(tr("GROUP_ELEMS_TO_REPLACE"));
myCheckBoxNewElemGroup->show(); myCheckBox1->show();
myCheckBoxNewNodeGroup->show(); myCheckBox2->show();
myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
// Show the third field // Show the third field
myTextLabel2->show(); myTextLabel2->show();
@ -338,8 +348,30 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
myGroupArguments->setTitle(tr("DUPLICATION_ONLY_ELEMS")); myGroupArguments->setTitle(tr("DUPLICATION_ONLY_ELEMS"));
myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE")); myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
myCheckBoxNewElemGroup->show(); myCheckBox1->show();
myCheckBoxNewNodeGroup->hide(); 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 // Hide the second and the third field
myTextLabel2->hide(); myTextLabel2->hide();
@ -367,8 +399,8 @@ bool SMESHGUI_DuplicateNodesDlg::onApply()
BusyLocker lock( myBusy ); BusyLocker lock( myBusy );
bool toCreateElemGroup = myCheckBoxNewElemGroup->isChecked(); bool toCreateElemGroup = myCheckBox1->isChecked();
bool toCreateNodeGroup = myCheckBoxNewNodeGroup->isChecked(); bool toCreateNodeGroup = myCheckBox2->isChecked();
int operationMode = myGroupConstructors->checkedId(); int operationMode = myGroupConstructors->checkedId();
// Apply changes // Apply changes
@ -451,14 +483,28 @@ bool SMESHGUI_DuplicateNodesDlg::onApply()
} }
break; 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) { catch (const SALOME::SALOME_Exception& S_ex) {
SalomeApp_Tools::QtCatchCorbaException(S_ex); SalomeApp_Tools::QtCatchCorbaException(S_ex);
} }
catch ( const std::exception& exc ) { catch ( const std::exception& exc ) {
INFOS( "Follow exception was cought:\n\t" << exc.what() ); INFOS( "Follow exception was cought:\n\t" << exc.what() );
} }
catch (...) { catch (...) {
INFOS( "Unknown exception was cought !!!" ); INFOS( "Unknown exception was cought !!!" );
} }
@ -553,6 +599,9 @@ void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
case 2: case 2:
ok = ( aGroupType != SMESH::NODE ); ok = ( aGroupType != SMESH::NODE );
break; break;
case 3:
ok = ( aGroupType == SMESH::VOLUME );
break;
} }
} }
if ( ok ) aGroups << aGroup; if ( ok ) aGroups << aGroup;
@ -575,8 +624,15 @@ void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3.clear(); else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3.clear();
myCurrentLineEdit->clear(); myCurrentLineEdit->clear();
} }
// Enable/disable "Apply and Close" and "Apply" buttons // 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(); bool isDataValid = isValid();
myButtonOk->setEnabled( isDataValid ); myButtonOk->setEnabled( isDataValid );
myButtonApply->setEnabled( isDataValid ); myButtonApply->setEnabled( isDataValid );
@ -610,12 +666,15 @@ void SMESHGUI_DuplicateNodesDlg::onEditCurrentArgument()
*/ */
bool SMESHGUI_DuplicateNodesDlg::isValid() bool SMESHGUI_DuplicateNodesDlg::isValid()
{ {
return myGroupConstructors->checkedId() == 1 ? switch( myGroupConstructors->checkedId() )
( !myGroups1.isEmpty() && !myGroups3.isEmpty() ) : {
( !myGroups1.isEmpty() ); 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. \brief SLOT called when dialog shoud be deativated.
*/ */

View File

@ -83,6 +83,8 @@ private slots:
void onDeactivate(); void onDeactivate();
void updateButtons();
private: private:
QLineEdit* myCurrentLineEdit; QLineEdit* myCurrentLineEdit;
@ -98,8 +100,8 @@ private:
QLineEdit* myLineEdit1; QLineEdit* myLineEdit1;
QLineEdit* myLineEdit2; QLineEdit* myLineEdit2;
QLineEdit* myLineEdit3; QLineEdit* myLineEdit3;
QCheckBox* myCheckBoxNewElemGroup; QCheckBox* myCheckBox1;
QCheckBox* myCheckBoxNewNodeGroup; QCheckBox* myCheckBox2;
QPushButton* myButtonOk; QPushButton* myButtonOk;
QPushButton* myButtonApply; QPushButton* myButtonApply;

View File

@ -435,10 +435,14 @@
<source>ICON_SMESH_DUPLICATE_NODES_WITH_ELEM</source> <source>ICON_SMESH_DUPLICATE_NODES_WITH_ELEM</source>
<translation>mesh_duplicate_nodes_with_elem.png</translation> <translation>mesh_duplicate_nodes_with_elem.png</translation>
</message> </message>
<message> <message>
<source>ICON_SMESH_DUPLICATE_ELEM_ONLY</source> <source>ICON_SMESH_DUPLICATE_ELEM_ONLY</source>
<translation>mesh_duplicate_elem_only.png</translation> <translation>mesh_duplicate_elem_only.png</translation>
</message> </message>
<message>
<source>ICON_SMESH_DUPLICATE_GROUP_BOUNDARY</source>
<translation>mesh_duplicate_group_boundary.png</translation>
</message>
<message> <message>
<source>ICON_SMESH_TREE_ALGO</source> <source>ICON_SMESH_TREE_ALGO</source>
<translation>mesh_tree_algo.png</translation> <translation>mesh_tree_algo.png</translation>

View File

@ -6752,6 +6752,10 @@ It is impossible to read point coordinates from file</translation>
<source>DUPLICATION_ONLY_ELEMS</source> <source>DUPLICATION_ONLY_ELEMS</source>
<translation>Duplicate elements only</translation> <translation>Duplicate elements only</translation>
</message> </message>
<message>
<source>DUPLICATION_GROUP_BOUNDARY</source>
<translation>Duplicate nodes on group boundaries</translation>
</message>
<message> <message>
<source>GROUP_ELEMS_TO_DUPLICATE</source> <source>GROUP_ELEMS_TO_DUPLICATE</source>
<translation>Group of elements to duplicate</translation> <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> <source>GROUP_ELEMS_TO_REPLACE</source>
<translation>Group of elements to replace nodes with new ones</translation> <translation>Group of elements to replace nodes with new ones</translation>
</message> </message>
<message>
<source>GROUP_VOLUME_GROUPS</source>
<translation>Groups of volumes</translation>
</message>
<message> <message>
<source>CONSTRUCT_NEW_GROUP_NODES</source> <source>CONSTRUCT_NEW_GROUP_NODES</source>
<translation>Construct group with newly created nodes</translation> <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> <source>CONSTRUCT_NEW_GROUP_ELEMENTS</source>
<translation>Construct group with newly created elements</translation> <translation>Construct group with newly created elements</translation>
</message> </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>
<context> <context>
<name>SMESHGUI_Make2DFrom3DDlg</name> <name>SMESHGUI_Make2DFrom3DDlg</name>

View 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. * 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). * 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". * 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 theDomains - list of groups of volumes
* @param createJointElems - if TRUE, create the elements * \param createJointElems - if TRUE, create the elements
* @return TRUE if operation has been completed successfully, FALSE otherwise * \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 CORBA::Boolean
SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains, SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
CORBA::Boolean createJointElems ) CORBA::Boolean createJointElems,
CORBA::Boolean onAllBoundaries )
throw (SALOME::SALOME_Exception) throw (SALOME::SALOME_Exception)
{ {
bool aResult = false; bool isOK = false;
SMESH_TRY; SMESH_TRY;
initData(); initData();
@ -6894,10 +6897,11 @@ SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& the
SMESHDS_Mesh* aMeshDS = getMeshDS(); SMESHDS_Mesh* aMeshDS = getMeshDS();
// MESSAGE("theDomains.length = "<<theDomains.length()); // 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); THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
vector<TIDSortedElemSet> domains; vector<TIDSortedElemSet> domains;
domains.clear(); domains.resize( theDomains.length() );
for ( int i = 0, n = theDomains.length(); i < n; i++ ) 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 ) // if ( aGrp->GetType() != SMESH::VOLUME )
// THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM); // 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(); SMESH::long_array_var anIDs = aGrp->GetIDs();
arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All ); 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 // TODO publish the groups of flat elements in study
declareMeshModified( /*isReComputeSafe=*/ !aResult ); declareMeshModified( /*isReComputeSafe=*/ !isOK );
// Update Python script // Update Python script
TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
<< ", " << createJointElems << " )"; << ", " << createJointElems << ", " << onAllBoundaries << " )";
SMESH_CATCH( SMESH::throwCorbaException ); SMESH_CATCH( SMESH::throwCorbaException );
return aResult; myMesh_i->CreateGroupServants(); // publish created groups if any
return isOK;
} }
//================================================================================ //================================================================================

View File

@ -923,12 +923,15 @@ public:
* The nodes of the internal faces at the boundaries of the groups are doubled. * The nodes of the internal faces at the boundaries of the groups are doubled.
* In option, the internal faces are replaced by flat elements. * In option, the internal faces are replaced by flat elements.
* Triangles are transformed in prisms, and quadrangles in hexahedrons. * Triangles are transformed in prisms, and quadrangles in hexahedrons.
* @param theDomains - list of groups of volumes * \param theDomains - list of groups of volumes
* @param createJointElems - if TRUE, create the elements * \param createJointElems - if TRUE, create the elements
* @return TRUE if operation has been completed successfully, FALSE otherwise * \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 DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
CORBA::Boolean createJointElems ) CORBA::Boolean createJointElems,
CORBA::Boolean onAllBoundaries )
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
/*! /*!
* \brief Double nodes on some external faces and create flat elements. * \brief Double nodes on some external faces and create flat elements.

View File

@ -4503,9 +4503,11 @@ class Mesh:
# Triangles are transformed in prisms, and quadrangles in hexahedrons. # Triangles are transformed in prisms, and quadrangles in hexahedrons.
# @param theDomains - list of groups of volumes # @param theDomains - list of groups of volumes
# @param createJointElems - if TRUE, create the elements # @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 # @return TRUE if operation has been completed successfully, FALSE otherwise
def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems ): def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems ) return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
## Double nodes on some external faces and create flat elements. ## Double nodes on some external faces and create flat elements.
# Flat elements are mainly used by some types of mechanic calculations. # Flat elements are mainly used by some types of mechanic calculations.