IMP 23078: [CEA 1498] Sewing of meshes without having to set the nodes ids

This commit is contained in:
eap 2015-09-18 17:10:34 +03:00
parent 8972ce9d84
commit 02ac54c6f3
32 changed files with 2825 additions and 532 deletions

View File

@ -38,7 +38,7 @@ the meshed face boundary.
\image html hypo_quad_params_dialog.png "Quadrangle parameters: Transition" \image html hypo_quad_params_dialog.png "Quadrangle parameters: Transition"
<b>Quadrangle parameters</b> is a hypothesis for Quadrangle (Mapping) algorithm. <b>Quadrangle parameters</b> is a hypothesis for \ref quad_ijk_algo_page.
<b>Transition</b> tab is used to define the algorithm of transition <b>Transition</b> tab is used to define the algorithm of transition
between opposite sides of the face with a different number of between opposite sides of the face with a different number of

View File

@ -23,7 +23,9 @@ elements which will form your group:</li>
</ul> </ul>
<li><b>Name</b> field allows to enter the name of your new group.</li> <li><b>Name</b> field allows to enter the name of your new group.</li>
<li><b>Color</b> - allows to assign to the group a certain color. The <li><b>Color</b> - allows to assign to the group a certain color. The
chosen color is used to display the elements of the group.</li> chosen color is used to display the elements of the group.<br>
Activation of <em>Auto Color</em> item in mesh context menu
switches on a random choice of a color for a new group.</li>
</ul> </ul>
Mesh module distinguishes between the three Group types: Mesh module distinguishes between the three Group types:
<b>Standalone Group</b>, <b>Group on Geometry</b> and <b>Group on Filter</b>. <b>Standalone Group</b>, <b>Group on Geometry</b> and <b>Group on Filter</b>.

View File

@ -16,17 +16,19 @@
either \ref importing_exporting_meshes_page "imported" or manually either \ref importing_exporting_meshes_page "imported" or manually
created); created);
</li> </li>
<li>\ref importing_exporting_meshes_page "importing and exporting meshes in various formats";</li> <li>\ref importing_exporting_meshes_page "importing and exporting meshes"
in various formats;</li>
<li>\subpage modifying_meshes_page "modifying meshes" with a vast <li>\subpage modifying_meshes_page "modifying meshes" with a vast
array of dedicated operations;</li> array of dedicated operations;</li>
<li>\subpage grouping_elements_page "creating groups of mesh <li>\subpage grouping_elements_page "creating groups" of mesh
elements";</li> elements;</li>
<li>filtering mesh entities (nodes or elements) using <li>filtering mesh entities (nodes or elements) using
\subpage filters_page "Filters" functionality for \ref \subpage filters_page "Filters" functionality for \ref
grouping_elements_page "creating groups" and applying \ref grouping_elements_page "creating groups" and applying \ref
modifying_meshes_page "mesh modifications";</li> modifying_meshes_page "mesh modifications";</li>
<li>\subpage viewing_meshes_overview_page "viewing meshes" in <li>\subpage viewing_meshes_overview_page "viewing meshes" in
the VTK viewer;</li> the VTK viewer and \ref mesh_infos_page "getting info" on mesh
and its sub-objects;</li>
<li>applying to meshes \subpage quality_page "Quality Controls", <li>applying to meshes \subpage quality_page "Quality Controls",
allowing to highlight important elements;</li> allowing to highlight important elements;</li>
<li>taking various \subpage measurements_page "measurements" of the <li>taking various \subpage measurements_page "measurements" of the

View File

@ -21,10 +21,10 @@ then converted to the single node.
processed. processed.
<li>\b Tolerance is a maximum distance between nodes sufficient for <li>\b Tolerance is a maximum distance between nodes sufficient for
merging.</li> merging.</li>
<li>Activation of <b>No merge of corner and medium nodes</b> check-box <li>Activation of <b>No merge of corner and medium nodes of quadratic
prevents merging medium nodes of quadratic elements with corner cells</b> check-box prevents merging medium nodes of quadratic
nodes. This check-box is enabled provided that the selected mesh elements with corner nodes. This check-box is enabled provided
includes quadratic elements.</li> that the selected mesh includes quadratic elements.</li>
<li><b>Exclude Groups</b> group box allows to ignore the nodes which <li><b>Exclude Groups</b> group box allows to ignore the nodes which
belong to the specified mesh groups.</li> belong to the specified mesh groups.</li>
<li><b>Nodes to keep</b> group box allows to specify nodes to keep in <li><b>Nodes to keep</b> group box allows to specify nodes to keep in

View File

@ -14,14 +14,16 @@ in the toolbar.
<em>"Mesh Information" button</em></center> <em>"Mesh Information" button</em></center>
The <b>Mesh Information</b> dialog box provides three tab pages: The <b>Mesh Information</b> dialog box provides three tab pages:
- <b>\ref advanced_mesh_infos_anchor "Base Info"</b> - to show base - <b>\ref advanced_mesh_infos_anchor "Base Info"</b> - to show
information about the selected mesh object. base and quantitative information about the selected mesh object.
- <b>\ref mesh_element_info_anchor "Element Info"</b> - to show - <b>\ref mesh_element_info_anchor "Element Info"</b> - to show
detailed information about the selected mesh node or element. detailed information about the selected mesh nodes or elements.
- <b>\ref mesh_addition_info_anchor "Additional Info"</b> - to show additional information available - <b>\ref mesh_addition_info_anchor "Additional Info"</b> - to show
for the selected mesh, sub-mesh or group object. additional information available for the selected mesh, sub-mesh or
group object.
- <b>\ref mesh_quality_info_anchor "Quality Info"</b> - to show - <b>\ref mesh_quality_info_anchor "Quality Info"</b> - to show
overall quality information about the selected mesh, sub-mesh or group object. overall quality information about the selected mesh, sub-mesh or group
object.
\anchor advanced_mesh_infos_anchor \anchor advanced_mesh_infos_anchor
<h2>Base Information</h2> <h2>Base Information</h2>

View File

@ -27,7 +27,13 @@ the type of sewing operation you would like to perform.</li>
\anchor free_borders_anchor \anchor free_borders_anchor
<h2>Sew free borders</h2> <h2>Sew free borders</h2>
This functionality allows you to unite two free borders of a 2D mesh. This functionality allows you to unite free borders of a 2D mesh.
There are two working modes: \a Automatic and \a Manual. In the \b
Automatic mode, the program finds free borders coincident within a
certain tolerance and sew them. Optionally it is possible to adjust
the found free borders before sewing. In the \b Manual mode you are to
define borders to sew by picking three nodes of each border.
\image html sewing1.png \image html sewing1.png

View File

@ -26,7 +26,10 @@ information about the mesh.</li>
<li>\subpage find_element_by_point_page "Find Element by Point" - <li>\subpage find_element_by_point_page "Find Element by Point" -
allows to find all mesh elements, to which belongs a point with the allows to find all mesh elements, to which belongs a point with the
given coordinates.</li> given coordinates.</li>
<li><b>Auto Color</b> - switch on / off auto-assigning colors for the groups.</li> <li><b>Auto Color</b> - switch on / off auto-assigning colors for the
groups. If switched on, a default color of a new group in
\ref creating_groups_page "Create Group" dialog is chosen
randomly. </li>
<li>\subpage numbering_page "Numbering" - allows to display the ID <li>\subpage numbering_page "Numbering" - allows to display the ID
numbers of all meshing elements or nodes composing your mesh in the numbers of all meshing elements or nodes composing your mesh in the
viewer.</li> viewer.</li>

View File

@ -29,13 +29,37 @@
module SMESH module SMESH
{ {
interface NumericalFunctor;
enum Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D }; enum Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D };
struct FreeBorder
{
SMESH::long_array nodeIDs; // all nodes defining a free border
// 1st and last node is same in a closed border
};
struct FreeBorderPart
{
short border; // border index within a sequence<FreeBorder>
long node1; // node index within the border-th FreeBorder
long node2;
long nodeLast;
};
typedef sequence<FreeBorder> ListOfFreeBorders;
typedef sequence<FreeBorderPart> FreeBordersGroup;
typedef sequence<FreeBordersGroup> ListOfFreeBorderGroups;
struct CoincidentFreeBorders
{
ListOfFreeBorders borders; // nodes of all free borders
ListOfFreeBorderGroups coincidentGroups; // groups of coincident parts of borders
};
/*! /*!
* This interface makes modifications on the Mesh - removing elements and nodes etc. * This interface makes modifications on the Mesh - removing elements and nodes etc.
*/ */
interface NumericalFunctor;
interface SMESH_MeshEditor interface SMESH_MeshEditor
{ {
/*! /*!
@ -723,6 +747,21 @@ module SMESH
short GetPointState(in double x, in double y, in double z) short GetPointState(in double x, in double y, in double z)
raises (SALOME::SALOME_Exception); raises (SALOME::SALOME_Exception);
/*!
* Returns groups of FreeBorder's coincident within the given tolerance.
* If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
* to free borders being compared is used.
*/
CoincidentFreeBorders FindCoincidentFreeBorders(in double tolerance);
/*!
* Sew FreeBorder's of each group
*/
short SewCoincidentFreeBorders (in CoincidentFreeBorders freeBorders,
in boolean createPolygons,
in boolean createPolyedrs)
raises (SALOME::SALOME_Exception);
enum Sew_Error { enum Sew_Error {
SEW_OK, SEW_OK,
SEW_BORDER1_NOT_FOUND, SEW_BORDER1_NOT_FOUND,

View File

@ -559,22 +559,8 @@ bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
if ( theEdgeNum < 0 || theEdgeNum > 3 || (nbNodes != 3 && nbNodes != 4) || theEdgeNum > nbNodes ) if ( theEdgeNum < 0 || theEdgeNum > 3 || (nbNodes != 3 && nbNodes != 4) || theEdgeNum > nbNodes )
return false; return false;
vector<int> anIds( nbNodes ); theNodeId1 = anElem->GetNode( theEdgeNum - 1 )->GetID();
SMDS_ElemIteratorPtr anIter = anElem->nodesIterator(); theNodeId2 = anElem->GetNode( theEdgeNum % nbNodes )->GetID();
int i = 0;
while( anIter->more() && i < nbNodes )
anIds[ i++ ] = anIter->next()->GetID();
if ( theEdgeNum < nbNodes - 1 )
{
theNodeId1 = anIds[ theEdgeNum ];
theNodeId2 = anIds[ theEdgeNum + 1 ];
}
else
{
theNodeId1 = anIds[ nbNodes - 1 ];
theNodeId2 = anIds[ 0 ];
}
return true; return true;
} }

View File

@ -189,7 +189,7 @@ public:
}; };
SMDS_ElemIteratorPtr SMDS_MeshNode:: SMDS_ElemIteratorPtr SMDS_MeshNode::
GetInverseElementIterator(SMDSAbs_ElementType type) const GetInverseElementIterator(SMDSAbs_ElementType type) const
{ {
vtkCellLinks::Link l = SMDS_Mesh::_meshList[myMeshId]->getGrid()->GetCellLinks()->GetLink(myVtkID); vtkCellLinks::Link l = SMDS_Mesh::_meshList[myMeshId]->getGrid()->GetCellLinks()->GetLink(myVtkID);
//MESSAGE("myID " << myID << " ncells " << l.ncells); //MESSAGE("myID " << myID << " ncells " << l.ncells);
@ -208,7 +208,7 @@ private:
int iter; int iter;
vector<SMDS_MeshElement*> myFiltCells; vector<SMDS_MeshElement*> myFiltCells;
public: public:
SMDS_MeshNode_MyIterator(SMDS_Mesh *mesh, SMDS_MeshNode_MyIterator(SMDS_Mesh *mesh,
vtkIdType* cells, vtkIdType* cells,
int ncells, int ncells,
@ -245,7 +245,7 @@ private:
}; };
SMDS_ElemIteratorPtr SMDS_MeshNode:: SMDS_ElemIteratorPtr SMDS_MeshNode::
elementsIterator(SMDSAbs_ElementType type) const elementsIterator(SMDSAbs_ElementType type) const
{ {
if(type==SMDSAbs_Node) if(type==SMDSAbs_Node)
return SMDS_MeshElement::elementsIterator(SMDSAbs_Node); return SMDS_MeshElement::elementsIterator(SMDSAbs_Node);

View File

@ -8269,6 +8269,8 @@ bool SMESH_MeshEditor::CheckFreeBorderNodes(const SMDS_MeshNode* theNode1,
//======================================================================= //=======================================================================
//function : SewFreeBorder //function : SewFreeBorder
//purpose : //purpose :
//warning : for border-to-side sewing theSideSecondNode is considered as
// the last side node and theSideThirdNode is not used
//======================================================================= //=======================================================================
SMESH_MeshEditor::Sew_Error SMESH_MeshEditor::Sew_Error

View File

@ -620,38 +620,25 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh,
// --------------------------------------------------------------- // ---------------------------------------------------------------
// get all faces // get all faces
list< const SMDS_MeshElement* > faces; SMDS_ElemIteratorPtr fIt;
if ( nbElems > 0 ) { if ( nbElems > 0 )
SMDS_ElemIteratorPtr fIt = fSubMesh->GetElements(); fIt = fSubMesh->GetElements();
while ( fIt->more() ) { else
const SMDS_MeshElement* f = fIt->next(); fIt = aMeshDS->elementsIterator( SMDSAbs_Face );
if ( f && f->GetType() == SMDSAbs_Face )
faces.push_back( f );
}
}
else {
SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
while ( fIt->more() )
faces.push_back( fIt->next() );
}
// put nodes of all faces into the nodePointIDMap and fill myElemPointIDs // put nodes of all faces into the nodePointIDMap and fill myElemPointIDs
list< const SMDS_MeshElement* >::iterator fIt = faces.begin(); while ( fIt->more() )
for ( ; fIt != faces.end(); ++fIt )
{ {
const SMDS_MeshElement* face = fIt->next();
myElemPointIDs.push_back( TElemDef() ); myElemPointIDs.push_back( TElemDef() );
TElemDef& elemPoints = myElemPointIDs.back(); TElemDef& elemPoints = myElemPointIDs.back();
int nbNodes = (*fIt)->NbCornerNodes(); int nbNodes = face->NbCornerNodes();
for ( int i = 0;i < nbNodes; ++i ) for ( int i = 0;i < nbNodes; ++i )
{ {
const SMDS_MeshElement* node = (*fIt)->GetNode( i ); const SMDS_MeshElement* node = face->GetNode( i );
TNodePointIDMap::iterator nIdIt = nodePointIDMap.insert( make_pair( node, -1 )).first; TNodePointIDMap::iterator nIdIt = nodePointIDMap.insert( make_pair( node, -1 )).first;
if ( nIdIt->second == -1 ) if ( nIdIt->second == -1 )
{
elemPoints.push_back( iPoint );
nIdIt->second = iPoint++; nIdIt->second = iPoint++;
}
else
elemPoints.push_back( (*nIdIt).second ); elemPoints.push_back( (*nIdIt).second );
} }
} }

View File

@ -142,6 +142,8 @@ SET(_moc_HEADERS
SMESHGUI_FieldSelectorWdg.h SMESHGUI_FieldSelectorWdg.h
SMESHGUI_DisplayEntitiesDlg.h SMESHGUI_DisplayEntitiesDlg.h
SMESHGUI_SplitBiQuad.h SMESHGUI_SplitBiQuad.h
SMESHGUI_PreVisualObj.h
SMESHGUI_IdPreview.h
) )
# header files / no moc processing # header files / no moc processing
@ -251,6 +253,8 @@ SET(_other_SOURCES
SMESHGUI_FieldSelectorWdg.cxx SMESHGUI_FieldSelectorWdg.cxx
SMESHGUI_DisplayEntitiesDlg.cxx SMESHGUI_DisplayEntitiesDlg.cxx
SMESHGUI_SplitBiQuad.cxx SMESHGUI_SplitBiQuad.cxx
SMESHGUI_PreVisualObj.cxx
SMESHGUI_IdPreview.cxx
) )
# sources / to compile # sources / to compile

View File

@ -0,0 +1,202 @@
// Copyright (C) 2007-2015 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
//
#include "SMESHGUI_IdPreview.h"
#include <SALOME_Actor.h>
#include <SMDS_Mesh.hxx>
#include <SVTK_ViewWindow.h>
#include <TColStd_MapOfInteger.hxx>
#include <TColStd_MapIteratorOfMapOfInteger.hxx>
#include <vtkActor2D.h>
#include <vtkDataSetMapper.h>
#include <vtkLabeledDataMapper.h>
#include <vtkMaskPoints.h>
#include <vtkPointData.h>
#include <vtkProperty2D.h>
#include <vtkRenderer.h>
#include <vtkSelectVisiblePoints.h>
#include <vtkTextProperty.h>
#include <vtkUnstructuredGrid.h>
// Extracted from SMESHGUI_MergeDlg.cxx
SMESHGUI_IdPreview::SMESHGUI_IdPreview(SVTK_ViewWindow* theViewWindow):
myViewWindow(theViewWindow)
{
myIdGrid = vtkUnstructuredGrid::New();
// Create and display actor
vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
aMapper->SetInputData( myIdGrid );
myIdActor = SALOME_Actor::New();
myIdActor->SetInfinitive(true);
myIdActor->VisibilityOff();
myIdActor->PickableOff();
myIdActor->SetMapper( aMapper );
aMapper->Delete();
myViewWindow->AddActor(myIdActor);
//Definition of points numbering pipeline
myPointsNumDataSet = vtkUnstructuredGrid::New();
myPtsMaskPoints = vtkMaskPoints::New();
myPtsMaskPoints->SetInputData(myPointsNumDataSet);
myPtsMaskPoints->SetOnRatio(1);
myPtsSelectVisiblePoints = vtkSelectVisiblePoints::New();
myPtsSelectVisiblePoints->SetInputConnection(myPtsMaskPoints->GetOutputPort());
myPtsSelectVisiblePoints->SelectInvisibleOff();
myPtsSelectVisiblePoints->SetTolerance(0.1);
myPtsLabeledDataMapper = vtkLabeledDataMapper::New();
myPtsLabeledDataMapper->SetInputConnection(myPtsSelectVisiblePoints->GetOutputPort());
myPtsLabeledDataMapper->SetLabelModeToLabelScalars();
vtkTextProperty* aPtsTextProp = vtkTextProperty::New();
aPtsTextProp->SetFontFamilyToTimes();
static int aPointsFontSize = 12;
aPtsTextProp->SetFontSize(aPointsFontSize);
aPtsTextProp->SetBold(1);
aPtsTextProp->SetItalic(0);
aPtsTextProp->SetShadow(0);
myPtsLabeledDataMapper->SetLabelTextProperty(aPtsTextProp);
aPtsTextProp->Delete();
myIsPointsLabeled = false;
myPointLabels = vtkActor2D::New();
myPointLabels->SetMapper(myPtsLabeledDataMapper);
myPointLabels->GetProperty()->SetColor(1,1,1);
myPointLabels->SetVisibility(myIsPointsLabeled);
AddToRender(myViewWindow->getRenderer());
}
void SMESHGUI_IdPreview::SetPointsData ( SMDS_Mesh* theMesh,
const TColStd_MapOfInteger & theNodesIdMap )
{
vtkPoints* aPoints = vtkPoints::New();
aPoints->SetNumberOfPoints(theNodesIdMap.Extent());
myIDs.clear();
TColStd_MapIteratorOfMapOfInteger idIter( theNodesIdMap );
for( int i = 0; idIter.More(); idIter.Next(), i++ )
{
const SMDS_MeshNode* aNode = theMesh->FindNode(idIter.Key());
aPoints->SetPoint( i, aNode->X(), aNode->Y(), aNode->Z() );
myIDs.push_back(idIter.Key());
}
myIdGrid->SetPoints(aPoints);
aPoints->Delete();
myIdActor->GetMapper()->Update();
}
void SMESHGUI_IdPreview::SetElemsData( const std::vector<int> & theElemsIdMap,
const std::list<gp_XYZ> & aGrCentersXYZ )
{
vtkPoints* aPoints = vtkPoints::New();
aPoints->SetNumberOfPoints( theElemsIdMap.size() );
myIDs = theElemsIdMap;
std::list<gp_XYZ>::const_iterator coordIt = aGrCentersXYZ.begin();
for( int i = 0; coordIt != aGrCentersXYZ.end(); coordIt++, i++ )
aPoints->SetPoint( i, coordIt->X(), coordIt->Y(), coordIt->Z() );
myIdGrid->SetPoints(aPoints);
aPoints->Delete();
myIdActor->GetMapper()->Update();
}
void SMESHGUI_IdPreview::AddToRender(vtkRenderer* theRenderer)
{
myIdActor->AddToRender(theRenderer);
myPtsSelectVisiblePoints->SetRenderer(theRenderer);
theRenderer->AddActor2D(myPointLabels);
}
void SMESHGUI_IdPreview::RemoveFromRender(vtkRenderer* theRenderer)
{
myIdActor->RemoveFromRender(theRenderer);
myPtsSelectVisiblePoints->SetRenderer(theRenderer);
theRenderer->RemoveActor(myPointLabels);
}
void SMESHGUI_IdPreview::SetPointsLabeled( bool theIsPointsLabeled, bool theIsActorVisible )
{
myIsPointsLabeled = theIsPointsLabeled && myIdGrid->GetNumberOfPoints();
if ( myIsPointsLabeled ) {
myPointsNumDataSet->ShallowCopy(myIdGrid);
vtkDataSet *aDataSet = myPointsNumDataSet;
int aNbElem = myIDs.size();
vtkIntArray *anArray = vtkIntArray::New();
anArray->SetNumberOfValues( aNbElem );
for ( int i = 0; i < aNbElem; i++ )
anArray->SetValue( i, myIDs[i] );
aDataSet->GetPointData()->SetScalars( anArray );
anArray->Delete();
myPtsMaskPoints->SetInputData( aDataSet );
myPointLabels->SetVisibility( theIsActorVisible );
}
else {
myPointLabels->SetVisibility( false );
}
}
SMESHGUI_IdPreview::~SMESHGUI_IdPreview()
{
RemoveFromRender(myViewWindow->getRenderer());
myIdGrid->Delete();
myViewWindow->RemoveActor(myIdActor);
myIdActor->Delete();
//Deleting of points numbering pipeline
//---------------------------------------
myPointsNumDataSet->Delete();
//myPtsLabeledDataMapper->RemoveAllInputs(); //vtk 5.0 porting
myPtsLabeledDataMapper->Delete();
//myPtsSelectVisiblePoints->UnRegisterAllOutputs(); //vtk 5.0 porting
myPtsSelectVisiblePoints->Delete();
//myPtsMaskPoints->UnRegisterAllOutputs(); //vtk 5.0 porting
myPtsMaskPoints->Delete();
myPointLabels->Delete();
// myTimeStamp->Delete();
}

View File

@ -0,0 +1,79 @@
// Copyright (C) 2007-2015 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
//
#ifndef SMESHGUI_IdPreview_H
#define SMESHGUI_IdPreview_H
#include "SMESH_SMESHGUI.hxx"
#include <list>
#include <vector>
#include <gp_XYZ.hxx>
class SALOME_Actor;
class SMDS_Mesh;
class SVTK_ViewWindow;
class TColStd_MapOfInteger;
class vtkActor2D;
class vtkLabeledDataMapper;
class vtkMaskPoints;
class vtkRenderer;
class vtkSelectVisiblePoints;
class vtkTextProperty;
class vtkUnstructuredGrid;
/*!
* \brief To display in the viewer IDs of selected elements or nodes
*/
class SMESHGUI_IdPreview
{
public:
SMESHGUI_IdPreview(SVTK_ViewWindow* theViewWindow);
~SMESHGUI_IdPreview();
void SetPointsData( SMDS_Mesh* theMesh, const TColStd_MapOfInteger & theNodesIdMap );
void SetElemsData ( const std::vector<int> & theElemsIdMap,
const std::list<gp_XYZ> & theGrCentersXYZ );
void SetPointsLabeled( bool theIsPointsLabeled, bool theIsActorVisible = true );
void AddToRender ( vtkRenderer* theRenderer );
void RemoveFromRender( vtkRenderer* theRenderer );
protected:
SVTK_ViewWindow* myViewWindow;
vtkUnstructuredGrid* myIdGrid;
SALOME_Actor* myIdActor;
vtkUnstructuredGrid* myPointsNumDataSet;
vtkMaskPoints* myPtsMaskPoints;
vtkSelectVisiblePoints* myPtsSelectVisiblePoints;
vtkLabeledDataMapper* myPtsLabeledDataMapper;
bool myIsPointsLabeled;
vtkActor2D* myPointLabels;
std::vector<int> myIDs;
};
#endif

View File

@ -28,10 +28,11 @@
#include "SMESHGUI_MergeDlg.h" #include "SMESHGUI_MergeDlg.h"
#include "SMESHGUI.h" #include "SMESHGUI.h"
#include "SMESHGUI_Utils.h" #include "SMESHGUI_IdPreview.h"
#include "SMESHGUI_VTKUtils.h"
#include "SMESHGUI_MeshUtils.h" #include "SMESHGUI_MeshUtils.h"
#include "SMESHGUI_SpinBox.h" #include "SMESHGUI_SpinBox.h"
#include "SMESHGUI_Utils.h"
#include "SMESHGUI_VTKUtils.h"
#include <SMESH_Actor.h> #include <SMESH_Actor.h>
#include <SMESH_TypeFilter.hxx> #include <SMESH_TypeFilter.hxx>
@ -61,34 +62,20 @@
#include CORBA_SERVER_HEADER(SMESH_Group) #include CORBA_SERVER_HEADER(SMESH_Group)
#include CORBA_SERVER_HEADER(SMESH_MeshEditor) #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
// VTK includes
#include <vtkUnstructuredGrid.h>
#include <vtkRenderer.h>
#include <vtkActor2D.h>
#include <vtkPoints.h>
#include <vtkDataSetMapper.h>
#include <vtkMaskPoints.h>
#include <vtkSelectVisiblePoints.h>
#include <vtkLabeledDataMapper.h>
#include <vtkTextProperty.h>
#include <vtkIntArray.h>
#include <vtkProperty2D.h>
#include <vtkPointData.h>
// Qt includes // Qt includes
#include <QApplication> #include <QApplication>
#include <QButtonGroup>
#include <QCheckBox>
#include <QGridLayout>
#include <QGroupBox> #include <QGroupBox>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QListWidget> #include <QListWidget>
#include <QPushButton> #include <QPushButton>
#include <QRadioButton> #include <QRadioButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QGridLayout>
#include <QKeyEvent>
#include <QButtonGroup>
#define SPACING 6 #define SPACING 6
#define MARGIN 11 #define MARGIN 11
@ -97,208 +84,27 @@ namespace
{ {
enum ActionType { MERGE_NODES, MERGE_ELEMENTS, TYPE_AUTO=0, TYPE_MANUAL }; enum ActionType { MERGE_NODES, MERGE_ELEMENTS, TYPE_AUTO=0, TYPE_MANUAL };
} }
namespace SMESH
QPixmap SMESHGUI_MergeDlg::IconFirst()
{ {
class TIdPreview static const char * iconFirst[] = {
{ // to display in the viewer IDs of the selected elements "18 10 2 1",
SVTK_ViewWindow* myViewWindow; " g None",
". g #000000",
vtkUnstructuredGrid* myIdGrid; " . . ",
SALOME_Actor* myIdActor; " .. .. .. ",
" .. ... ... ",
vtkUnstructuredGrid* myPointsNumDataSet; " .. .... .... ",
vtkMaskPoints* myPtsMaskPoints; " .. ..... ..... ",
vtkSelectVisiblePoints* myPtsSelectVisiblePoints; " .. ..... ..... ",
vtkLabeledDataMapper* myPtsLabeledDataMapper; " .. .... .... ",
vtkTextProperty* aPtsTextProp; " .. ... ... ",
bool myIsPointsLabeled; " .. .. .. ",
vtkActor2D* myPointLabels; " . . "};
return iconFirst;
std::vector<int> myIDs;
public:
TIdPreview(SVTK_ViewWindow* theViewWindow):
myViewWindow(theViewWindow)
{
myIdGrid = vtkUnstructuredGrid::New();
// Create and display actor
vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
aMapper->SetInputData( myIdGrid );
myIdActor = SALOME_Actor::New();
myIdActor->SetInfinitive(true);
myIdActor->VisibilityOff();
myIdActor->PickableOff();
myIdActor->SetMapper( aMapper );
aMapper->Delete();
myViewWindow->AddActor(myIdActor);
//Definition of points numbering pipeline
myPointsNumDataSet = vtkUnstructuredGrid::New();
myPtsMaskPoints = vtkMaskPoints::New();
myPtsMaskPoints->SetInputData(myPointsNumDataSet);
myPtsMaskPoints->SetOnRatio(1);
myPtsSelectVisiblePoints = vtkSelectVisiblePoints::New();
myPtsSelectVisiblePoints->SetInputConnection(myPtsMaskPoints->GetOutputPort());
myPtsSelectVisiblePoints->SelectInvisibleOff();
myPtsSelectVisiblePoints->SetTolerance(0.1);
myPtsLabeledDataMapper = vtkLabeledDataMapper::New();
myPtsLabeledDataMapper->SetInputConnection(myPtsSelectVisiblePoints->GetOutputPort());
myPtsLabeledDataMapper->SetLabelModeToLabelScalars();
vtkTextProperty* aPtsTextProp = vtkTextProperty::New();
aPtsTextProp->SetFontFamilyToTimes();
static int aPointsFontSize = 12;
aPtsTextProp->SetFontSize(aPointsFontSize);
aPtsTextProp->SetBold(1);
aPtsTextProp->SetItalic(0);
aPtsTextProp->SetShadow(0);
myPtsLabeledDataMapper->SetLabelTextProperty(aPtsTextProp);
aPtsTextProp->Delete();
myIsPointsLabeled = false;
myPointLabels = vtkActor2D::New();
myPointLabels->SetMapper(myPtsLabeledDataMapper);
myPointLabels->GetProperty()->SetColor(1,1,1);
myPointLabels->SetVisibility(myIsPointsLabeled);
AddToRender(myViewWindow->getRenderer());
}
void SetPointsData ( SMDS_Mesh* theMesh,
TColStd_MapOfInteger & theNodesIdMap )
{
vtkPoints* aPoints = vtkPoints::New();
aPoints->SetNumberOfPoints(theNodesIdMap.Extent());
myIDs.clear();
TColStd_MapIteratorOfMapOfInteger idIter( theNodesIdMap );
for( int i = 0; idIter.More(); idIter.Next(), i++ ) {
const SMDS_MeshNode* aNode = theMesh->FindNode(idIter.Key());
aPoints->SetPoint( i, aNode->X(), aNode->Y(), aNode->Z() );
myIDs.push_back(idIter.Key());
}
myIdGrid->SetPoints(aPoints);
aPoints->Delete();
myIdActor->GetMapper()->Update();
}
void SetElemsData( TColStd_MapOfInteger & theElemsIdMap,
std::list<gp_XYZ> & aGrCentersXYZ )
{
vtkPoints* aPoints = vtkPoints::New();
aPoints->SetNumberOfPoints(theElemsIdMap.Extent());
myIDs.clear();
TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap );
for( ; idIter.More(); idIter.Next() ) {
myIDs.push_back(idIter.Key());
}
gp_XYZ aXYZ;
std::list<gp_XYZ>::iterator coordIt = aGrCentersXYZ.begin();
for( int i = 0; coordIt != aGrCentersXYZ.end(); coordIt++, i++ ) {
aXYZ = *coordIt;
aPoints->SetPoint( i, aXYZ.X(), aXYZ.Y(), aXYZ.Z() );
}
myIdGrid->SetPoints(aPoints);
aPoints->Delete();
myIdActor->GetMapper()->Update();
}
void AddToRender(vtkRenderer* theRenderer)
{
myIdActor->AddToRender(theRenderer);
myPtsSelectVisiblePoints->SetRenderer(theRenderer);
theRenderer->AddActor2D(myPointLabels);
}
void RemoveFromRender(vtkRenderer* theRenderer)
{
myIdActor->RemoveFromRender(theRenderer);
myPtsSelectVisiblePoints->SetRenderer(theRenderer);
theRenderer->RemoveActor(myPointLabels);
}
void SetPointsLabeled( bool theIsPointsLabeled, bool theIsActorVisible = true )
{
myIsPointsLabeled = theIsPointsLabeled && myIdGrid->GetNumberOfPoints();
if ( myIsPointsLabeled ) {
myPointsNumDataSet->ShallowCopy(myIdGrid);
vtkDataSet *aDataSet = myPointsNumDataSet;
int aNbElem = myIDs.size();
vtkIntArray *anArray = vtkIntArray::New();
anArray->SetNumberOfValues( aNbElem );
for ( int i = 0; i < aNbElem; i++ )
anArray->SetValue( i, myIDs[i] );
aDataSet->GetPointData()->SetScalars( anArray );
anArray->Delete();
myPtsMaskPoints->SetInputData( aDataSet );
myPointLabels->SetVisibility( theIsActorVisible );
}
else {
myPointLabels->SetVisibility( false );
}
}
~TIdPreview()
{
RemoveFromRender(myViewWindow->getRenderer());
myIdGrid->Delete();
myViewWindow->RemoveActor(myIdActor);
myIdActor->Delete();
//Deleting of points numbering pipeline
//---------------------------------------
myPointsNumDataSet->Delete();
//myPtsLabeledDataMapper->RemoveAllInputs(); //vtk 5.0 porting
myPtsLabeledDataMapper->Delete();
//myPtsSelectVisiblePoints->UnRegisterAllOutputs(); //vtk 5.0 porting
myPtsSelectVisiblePoints->Delete();
//myPtsMaskPoints->UnRegisterAllOutputs(); //vtk 5.0 porting
myPtsMaskPoints->Delete();
myPointLabels->Delete();
// myTimeStamp->Delete();
}
};
} }
static const char * IconFirst[] = {
"18 10 2 1",
" g None",
". g #000000",
" . . ",
" .. .. .. ",
" .. ... ... ",
" .. .... .... ",
" .. ..... ..... ",
" .. ..... ..... ",
" .. .... .... ",
" .. ... ... ",
" .. .. .. ",
" . . "};
//================================================================================= //=================================================================================
// class : SMESHGUI_MergeDlg() // class : SMESHGUI_MergeDlg()
// purpose : // purpose :
@ -313,7 +119,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
setAttribute(Qt::WA_DeleteOnClose, true); setAttribute(Qt::WA_DeleteOnClose, true);
setWindowTitle(myAction == MERGE_ELEMENTS ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES")); setWindowTitle(myAction == MERGE_ELEMENTS ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES"));
myIdPreview = new SMESH::TIdPreview(SMESH::GetViewWindow( mySMESHGUI )); myIdPreview = new SMESHGUI_IdPreview(SMESH::GetViewWindow( mySMESHGUI ));
SUIT_ResourceMgr* aResMgr = SMESH::GetResourceMgr( mySMESHGUI ); SUIT_ResourceMgr* aResMgr = SMESH::GetResourceMgr( mySMESHGUI );
QPixmap IconMergeNodes (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_MERGE_NODES"))); QPixmap IconMergeNodes (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_MERGE_NODES")));
@ -511,7 +317,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
RemoveElemButton = new QPushButton(GroupEdit); RemoveElemButton = new QPushButton(GroupEdit);
RemoveElemButton->setIcon(IconRemove); RemoveElemButton->setIcon(IconRemove);
SetFirstButton = new QPushButton(GroupEdit); SetFirstButton = new QPushButton(GroupEdit);
SetFirstButton->setIcon(QPixmap(IconFirst)); SetFirstButton->setIcon(IconFirst());
GroupEditLayout->addWidget(ListEdit, 0, 0, 2, 1); GroupEditLayout->addWidget(ListEdit, 0, 0, 2, 1);
GroupEditLayout->addWidget(AddElemButton, 0, 1); GroupEditLayout->addWidget(AddElemButton, 0, 1);
@ -646,6 +452,7 @@ void SMESHGUI_MergeDlg::Init()
// purpose : // purpose :
//================================================================================= //=================================================================================
void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap, void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
std::vector<int>& theIDs,
std::list< gp_XYZ > & theGrCentersXYZ) std::list< gp_XYZ > & theGrCentersXYZ)
{ {
if (!myActor) if (!myActor)
@ -658,11 +465,13 @@ void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
int nbNodes; int nbNodes;
theIDs.reserve( theElemsIdMap.Extent() );
TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap ); TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap );
for( ; idIter.More(); idIter.Next() ) { for( ; idIter.More(); idIter.Next() ) {
const SMDS_MeshElement* anElem = aMesh->FindElement(idIter.Key()); const SMDS_MeshElement* anElem = aMesh->FindElement(idIter.Key());
if ( !anElem ) if ( !anElem )
continue; continue;
theIDs.push_back( idIter.Key() );
gp_XYZ anXYZ(0., 0., 0.); gp_XYZ anXYZ(0., 0., 0.);
SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator(); SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator();
@ -1034,8 +843,9 @@ void SMESHGUI_MergeDlg::onSelectGroup()
} }
else { else {
std::list< gp_XYZ > aGrCentersXYZ; std::list< gp_XYZ > aGrCentersXYZ;
FindGravityCenter(anIndices, aGrCentersXYZ); std::vector<int> anIDs;
myIdPreview->SetElemsData( anIndices, aGrCentersXYZ); FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
myIdPreview->SetElemsData( anIDs, aGrCentersXYZ );
myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility()); myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
} }
else else
@ -1087,8 +897,9 @@ void SMESHGUI_MergeDlg::onSelectElementFromGroup()
} }
else { else {
std::list< gp_XYZ > aGrCentersXYZ; std::list< gp_XYZ > aGrCentersXYZ;
FindGravityCenter(anIndices, aGrCentersXYZ); std::vector<int> anIDs;
myIdPreview->SetElemsData(anIndices, aGrCentersXYZ); FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
myIdPreview->SetElemsData(anIDs, aGrCentersXYZ);
myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility()); myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
} }
else else

View File

@ -38,25 +38,27 @@
// STL includes // STL includes
#include <list> #include <list>
#include <vector>
// IDL includes // IDL includes
#include <SALOMEconfig.h> #include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Mesh) #include CORBA_SERVER_HEADER(SMESH_Mesh)
class LightApp_SelectionMgr;
class QButtonGroup;
class QCheckBox;
class QGroupBox; class QGroupBox;
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
class QListWidget;
class QPushButton; class QPushButton;
class QRadioButton; class QRadioButton;
class QCheckBox;
class QListWidget;
class QButtonGroup;
class SMESHGUI; class SMESHGUI;
class SMESHGUI_IdPreview;
class SMESHGUI_SpinBox; class SMESHGUI_SpinBox;
class SMESH_Actor; class SMESH_Actor;
class SVTK_Selector;
class LightApp_SelectionMgr;
class SUIT_SelectionFilter; class SUIT_SelectionFilter;
class SVTK_Selector;
class TColStd_MapOfInteger; class TColStd_MapOfInteger;
namespace SMESH namespace SMESH
@ -76,6 +78,8 @@ public:
SMESHGUI_MergeDlg( SMESHGUI*, int ); SMESHGUI_MergeDlg( SMESHGUI*, int );
~SMESHGUI_MergeDlg(); ~SMESHGUI_MergeDlg();
static QPixmap IconFirst();
private: private:
void Init(); void Init();
void enterEvent( QEvent* ); /* mouse enter the QWidget */ void enterEvent( QEvent* ); /* mouse enter the QWidget */
@ -85,6 +89,7 @@ private:
bool isNewKeepNodesGroup( const char* entry ); bool isNewKeepNodesGroup( const char* entry );
void FindGravityCenter( TColStd_MapOfInteger&, void FindGravityCenter( TColStd_MapOfInteger&,
std::vector<int>& ,
std::list<gp_XYZ>& ); std::list<gp_XYZ>& );
// add the centers of gravity of ElemsIdMap elements to the GrCentersXYZ list // add the centers of gravity of ElemsIdMap elements to the GrCentersXYZ list
@ -103,7 +108,7 @@ private:
SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter; SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter;
SUIT_SelectionFilter* mySubMeshOrGroupFilter; SUIT_SelectionFilter* mySubMeshOrGroupFilter;
SMESH::TIdPreview* myIdPreview; SMESHGUI_IdPreview* myIdPreview;
int myAction; int myAction;
bool myIsBusy; bool myIsBusy;

View File

@ -0,0 +1,142 @@
// Copyright (C) 2007-2015 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
//
#include "SMESHGUI_PreVisualObj.h"
#include <SMDS_Mesh.hxx>
#include <SMESH_Actor.h>
SMESHGUI_PreVisualObj::SMESHGUI_PreVisualObj()
{
myMesh = new SMDS_Mesh();
}
bool SMESHGUI_PreVisualObj::Update( int theIsClear = true )
{
return false;
}
void SMESHGUI_PreVisualObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
{
if ( theFunctor ) theFunctor->SetMesh( GetMesh() );
}
int SMESHGUI_PreVisualObj::GetElemDimension( const int theObjId )
{
if ( const SMDS_MeshElement* anElem = myMesh->FindElement( theObjId ))
{
switch ( anElem->GetType() )
{
case SMDSAbs_Edge : return 1;
case SMDSAbs_Face : return 2;
case SMDSAbs_Volume: return 3;
// case SMDSAbs_0DElement : return 0;
// case SMDSAbs_Ball : return 0;
default : return 0;
}
}
return -1;
}
int SMESHGUI_PreVisualObj::GetNbEntities( const SMDSAbs_ElementType theType ) const
{
myMesh->GetMeshInfo().NbElements( theType );
}
SMESH::SMESH_Mesh_ptr SMESHGUI_PreVisualObj::GetMeshServer()
{
return SMESH::SMESH_Mesh::_nil();
}
//=================================================================================
// function : GetEdgeNodes
// purpose : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
//=================================================================================
bool SMESHGUI_PreVisualObj::GetEdgeNodes( const int theElemId,
const int theEdgeNum,
int& theNodeId1,
int& theNodeId2 ) const
{
const SMDS_MeshElement* e = myMesh->FindElement( theElemId );
if ( !e || e->GetType() != SMDSAbs_Face )
return false;
int nbNodes = e->NbCornerNodes();
if ( theEdgeNum < 0 || theEdgeNum > nbNodes )
return false;
theNodeId1 = e->GetNode( theEdgeNum-1 )->GetID();
theNodeId2 = e->GetNode( theEdgeNum % nbNodes )->GetID();
return true;
}
bool SMESHGUI_PreVisualObj::IsValid() const
{
return GetNbEntities( SMDSAbs_All ) > 0;
}
vtkUnstructuredGrid* SMESHGUI_PreVisualObj::GetUnstructuredGrid()
{
return myMesh->getGrid();
}
vtkIdType SMESHGUI_PreVisualObj::GetNodeObjId( int theVTKID )
{
const SMDS_MeshNode* aNode = myMesh->FindNodeVtk( theVTKID );
return aNode ? aNode->GetID() : -1;
}
vtkIdType SMESHGUI_PreVisualObj::GetNodeVTKId( int theObjID )
{
const SMDS_MeshNode* aNode = myMesh->FindNode( theObjID );
return aNode ? aNode->GetID() : -1;
}
vtkIdType SMESHGUI_PreVisualObj::GetElemObjId( int theVTKID )
{
return this->GetMesh()->fromVtkToSmds(theVTKID);
}
vtkIdType SMESHGUI_PreVisualObj::GetElemVTKId( int theObjID )
{
const SMDS_MeshElement* e = myMesh->FindElement(theObjID);
return e ? e->getVtkId() : -1;
}
void SMESHGUI_PreVisualObj::ClearEntitiesFlags()
{
myEntitiesState = SMESH_Actor::eAllEntity;
myEntitiesFlag = false;
}
bool SMESHGUI_PreVisualObj::GetEntitiesFlag()
{
return myEntitiesFlag;
}
unsigned int SMESHGUI_PreVisualObj::GetEntitiesState()
{
return myEntitiesState;
}

View File

@ -0,0 +1,71 @@
// Copyright (C) 2007-2015 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 : SMESHGUI_PreVisualObj.h
// Module : SMESH
//
#ifndef SMESHGUI_PreVisualObj_H
#define SMESHGUI_PreVisualObj_H
#include "SMESH_SMESHGUI.hxx"
#include "SMESH_Object.h"
/*!
* \brief Incarnation of SMESH_VisualObj allowing usage of SMESH_Actor
* to show arbitrary mesh data. SMESHGUI_PreVisualObj encapsulates
* a instance of SMDS_Mesh that can be filled by its user.
* Main usage: to initialize a SMESH_Actor to display some preview
*/
class SMESHGUI_EXPORT SMESHGUI_PreVisualObj : public SMESH_VisualObj
{
mutable SMDS_Mesh* myMesh;
bool myEntitiesFlag;
unsigned int myEntitiesState;
public:
SMESHGUI_PreVisualObj();
virtual SMDS_Mesh* GetMesh() const { return myMesh; }
virtual bool Update( int theIsClear );
virtual bool NulData() { return false; }
virtual void UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor );
virtual int GetElemDimension( const int theObjId );
virtual int GetNbEntities( const SMDSAbs_ElementType theType) const;
virtual bool IsValid() const;
virtual bool GetEdgeNodes( const int theElemId,
const int theEdgeNum,
int& theNodeId1,
int& theNodeId2 ) const;
virtual vtkIdType GetNodeObjId( int theVTKID );
virtual vtkIdType GetNodeVTKId( int theObjID );
virtual vtkIdType GetElemObjId( int theVTKID );
virtual vtkIdType GetElemVTKId( int theObjID );
virtual void ClearEntitiesFlags();
virtual bool GetEntitiesFlag();
virtual unsigned int GetEntitiesState();
virtual SMESH::SMESH_Mesh_ptr GetMeshServer();
virtual vtkUnstructuredGrid* GetUnstructuredGrid();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,9 @@
// IDL includes // IDL includes
#include <SALOMEconfig.h> #include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Mesh) #include CORBA_SERVER_HEADER(SMESH_Mesh)
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
#include <vector>
class QButtonGroup; class QButtonGroup;
class QGroupBox; class QGroupBox;
@ -48,6 +51,10 @@ class SMESHGUI;
class SMESH_Actor; class SMESH_Actor;
class SVTK_Selector; class SVTK_Selector;
class LightApp_SelectionMgr; class LightApp_SelectionMgr;
class SMESHGUI_SpinBox;
class SalomeApp_IntSpinBox;
class QListWidget;
class QListWidgetItem;
//================================================================================= //=================================================================================
// class : SMESHGUI_SewingDlg // class : SMESHGUI_SewingDlg
@ -67,6 +74,7 @@ private:
void keyPressEvent( QKeyEvent* ); void keyPressEvent( QKeyEvent* );
int GetConstructorId(); int GetConstructorId();
bool IsValid(); bool IsValid();
void UpdateButtons();
SMESHGUI* mySMESHGUI; /* Current SMESHGUI object */ SMESHGUI* mySMESHGUI; /* Current SMESHGUI object */
LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */
@ -114,13 +122,67 @@ private:
QCheckBox* CheckBoxPolygons; QCheckBox* CheckBoxPolygons;
QCheckBox* CheckBoxPolyedrs; QCheckBox* CheckBoxPolyedrs;
QWidget* SewFreeBordersWidget;
QGroupBox* ModeGroup;
QButtonGroup* ModeButGrp;
//QPushButton* SelectMeshButton;
QLineEdit* LineEditMesh;
SMESHGUI_SpinBox* SpinBoxTolerance;
QCheckBox* AutoSewCheck;
QWidget* GroupCoincidentWidget;
QListWidget* ListCoincident;
QPushButton* DetectButton;
QPushButton* RemoveGroupButton;
QCheckBox* SelectAllCheck;
QListWidget* ListEdit;
QButtonGroup* MoveBorderEndsButGrp;
QLineEdit* BorderEndLine[2];
QPushButton* SwapBut;
QPushButton* SetFirstButton;
QPushButton* RemoveElemButton;
SalomeApp_IntSpinBox* StepSpin;
QString myHelpFileName; QString myHelpFileName;
protected slots:
struct BorderGroupDisplayer;
std::vector< BorderGroupDisplayer* > myBorderDisplayers;
SMESH::CoincidentFreeBorders_var myBorders;
int myCurGroupIndex;
int myCurPartIndex;
int myStoredRepresentation;
unsigned int myStoredEntityMode;
bool haveBorders();
QString getGroupText( int groupIndex );
QString getPartText( const SMESH::FreeBorderPart& part );
void showGroup( QListWidgetItem* item );
bool setCurrentGroup();
bool setCurrentPart();
void onGroupChange(bool partChange=false);
void setDisplayMode();
void restoreDisplayMode();
protected slots:
virtual void reject(); virtual void reject();
private slots: private slots:
void ConstructorsClicked( int ); void ConstructorsClicked( int );
void onModeChange( int );
void onAutoSew( int );
void onDetectClicked();
void onRemoveGroupClicked();
void onSelectGroup();
void onSelectAll(int);
void onSelectBorderPartFromGroup();
void onSetFirstClicked();
void onRemoveElemClicked();
void onMoveBorderEnd(int);
void onSwapClicked();
void ClickOnOk(); void ClickOnOk();
bool ClickOnApply(); bool ClickOnApply();
void ClickOnHelp(); void ClickOnHelp();

View File

@ -5141,7 +5141,7 @@ Please select a group and try again</translation>
</message> </message>
<message> <message>
<source>SEPARATE_CORNERS_AND_MEDIUM</source> <source>SEPARATE_CORNERS_AND_MEDIUM</source>
<translation>No merge of corner and medium nodes</translation> <translation>No merge of corner and medium nodes of quadratic cells</translation>
</message> </message>
<message> <message>
<source>KEEP_NODES</source> <source>KEEP_NODES</source>
@ -5155,10 +5155,6 @@ Please select a group and try again</translation>
<source>SELECT</source> <source>SELECT</source>
<translation>Select: </translation> <translation>Select: </translation>
</message> </message>
<message>
<source></source>
<translation></translation>
</message>
</context> </context>
<context> <context>
<name>SMESHGUI_ExtrusionAlongPathDlg</name> <name>SMESHGUI_ExtrusionAlongPathDlg</name>
@ -6665,6 +6661,42 @@ It is impossible to read point coordinates from file</translation>
<source>SIDE_2</source> <source>SIDE_2</source>
<translation>Side 2</translation> <translation>Side 2</translation>
</message> </message>
<message>
<source>AUTO_SEWING</source>
<translation>Auto Sewing</translation>
</message>
<message>
<source>COINCIDENT_FREE_BORDERS</source>
<translation>Coincident Free Borders</translation>
</message>
<message>
<source>DETECT</source>
<translation>Detect</translation>
</message>
<message>
<source>SELECT_ALL</source>
<translation>Select all</translation>
</message>
<message>
<source>EDIT_SELECTED_GROUP</source>
<translation>Edit Selected Group</translation>
</message>
<message>
<source>STEP</source>
<translation>Step</translation>
</message>
<message>
<source>NO_BORDERS_TO_SEW</source>
<translation>No free borders to sew found</translation>
</message>
<message>
<source>NOT_ALL_BORDERS_SEWED</source>
<translation>%1 of %2 groups of borders sewed</translation>
</message>
<message>
<source>ALL_BORDERS_SEWED</source>
<translation>%1 group(s) of borders sewed</translation>
</message>
</context> </context>
<context> <context>
<name>SMESHGUI_ShapeByMeshDlg</name> <name>SMESHGUI_ShapeByMeshDlg</name>

View File

@ -79,6 +79,7 @@ SET(SMESHUtils_SOURCES
SMESH_File.cxx SMESH_File.cxx
SMESH_MeshAlgos.cxx SMESH_MeshAlgos.cxx
SMESH_MAT2d.cxx SMESH_MAT2d.cxx
SMESH_FreeBorders.cxx
) )
# --- rules --- # --- rules ---

View File

@ -0,0 +1,507 @@
// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
//
// 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 : SMESH_FreeBorders.cxx
// Created : Tue Sep 8 17:08:39 2015
// Author : Edward AGAPOV (eap)
//================================================================================
// Implementation of SMESH_MeshAlgos::FindCoincidentFreeBorders()
//================================================================================
#include "SMESH_MeshAlgos.hxx"
#include "SMDS_LinearEdge.hxx"
#include "SMDS_Mesh.hxx"
#include "SMDS_SetIterator.hxx"
#include <algorithm>
#include <limits>
#include <set>
#include <vector>
#include <NCollection_DataMap.hxx>
#include <gp_Pnt.hxx>
using namespace SMESH_MeshAlgos;
namespace
{
struct BEdge;
/*!
* \brief Node on a free border
*/
struct BNode
{
const SMDS_MeshNode * myNode;
mutable std::vector< BEdge* > myLinkedEdges;
mutable std::vector< BEdge* > myCloseEdges;
BNode(const SMDS_MeshNode * node): myNode( node ) {}
void AddLinked( BEdge* e ) const;
void AddClose ( const BEdge* e ) const;
BEdge* FindCloseEdgeOfBorder( int borderID ) const;
bool operator<(const BNode& other) const { return myNode->GetID() < other.myNode->GetID(); }
};
/*!
* \brief Edge of a free border
*/
struct BEdge : public SMDS_LinearEdge
{
const BNode* myBNode1;
const BNode* myBNode2;
int myBorderID;
int myID; // within a border
BEdge* myPrev;
BEdge* myNext;
const SMDS_MeshElement* myFace;
std::set< int > myCloseBorders;
bool myInGroup;
BEdge():SMDS_LinearEdge( 0, 0 ), myBorderID(-1), myID(-1), myPrev(0), myNext(0), myInGroup(0) {}
void Set( const BNode * node1,
const BNode * node2,
const SMDS_MeshElement* face,
const int ID)
{
myBNode1 = node1;
myBNode2 = node2;
myNodes[0] = node1->myNode;
myNodes[1] = node2->myNode;
myFace = face;
setId( ID ); // mesh element ID
}
bool Contains( const BNode* n ) const
{
return ( n == myBNode1 || n == myBNode2 );
}
void AddLinked( BEdge* e )
{
if ( e->Contains( myBNode1 )) myPrev = e;
else myNext = e;
}
void RemoveLinked( BEdge* e )
{
if ( myPrev == e ) myPrev = 0;
if ( myNext == e ) myNext = 0;
}
void Reverse()
{
std::swap( myBNode1, myBNode2 );
myNodes[0] = myBNode1->myNode;
myNodes[1] = myBNode2->myNode;
}
void Orient()
{
if (( myPrev && !myPrev->Contains( myBNode1 )) ||
( myNext && !myNext->Contains( myBNode2 )))
std::swap( myPrev, myNext );
if ( myPrev && myPrev->myBNode2 != myBNode1 ) myPrev->Reverse();
if ( myNext && myNext->myBNode1 != myBNode2 ) myNext->Reverse();
}
void SetID( int id )
{
if ( myID < 0 )
{
myID = id;
if ( myNext )
myNext->SetID( id + 1 );
}
}
void FindRangeOfSameCloseBorders(BEdge* eRange[2])
{
eRange[0] = this;
while ( eRange[0]->myPrev && eRange[0]->myPrev->myCloseBorders == this->myCloseBorders )
{
if ( eRange[0]->myPrev == this /*|| eRange[0]->myPrev->myInGroup*/ )
break;
eRange[0] = eRange[0]->myPrev;
}
eRange[1] = this;
if ( eRange[0]->myPrev != this ) // not closed range
while ( eRange[1]->myNext && eRange[1]->myNext->myCloseBorders == this->myCloseBorders )
{
if ( eRange[1]->myNext == this /*|| eRange[1]->myNext->myInGroup*/ )
break;
eRange[1] = eRange[1]->myNext;
}
}
};
void BNode::AddLinked( BEdge* e ) const
{
myLinkedEdges.reserve(2);
myLinkedEdges.push_back( e );
if ( myLinkedEdges.size() < 2 ) return;
if ( myLinkedEdges.size() == 2 )
{
myLinkedEdges[0]->AddLinked( myLinkedEdges[1] );
myLinkedEdges[1]->AddLinked( myLinkedEdges[0] );
}
else
{
for ( size_t i = 0; i < myLinkedEdges.size(); ++i )
for ( size_t j = 0; j < myLinkedEdges.size(); ++j )
if ( i != j )
myLinkedEdges[i]->RemoveLinked( myLinkedEdges[j] );
}
}
void BNode::AddClose ( const BEdge* e ) const
{
if ( ! e->Contains( this ))
myCloseEdges.push_back( const_cast< BEdge* >( e ));
}
BEdge* BNode::FindCloseEdgeOfBorder( int borderID ) const
{
for ( size_t i = 0; i < myCloseEdges.size(); ++i )
if ( borderID == myCloseEdges[ i ]->myBorderID )
return myCloseEdges[ i ];
return 0;
}
/// Accessor to SMDS_MeshElement* inherited by BEdge
struct ElemAcess
{
static const SMDS_MeshElement* value( std::vector< BEdge >::const_iterator it)
{
return & (*it);
}
};
/// Iterator over a vector of BEdge's
static SMDS_ElemIteratorPtr getElemIterator( const std::vector< BEdge > & bedges )
{
typedef SMDS_SetIterator
< const SMDS_MeshElement*, std::vector< BEdge >::const_iterator, ElemAcess > BEIter;
return SMDS_ElemIteratorPtr( new BEIter( bedges.begin(), bedges.end() ));
}
} // namespace
// struct needed for NCollection_Map
struct TLinkHasher
{
static int HashCode(const SMESH_TLink& link, int aLimit)
{
return ::HashCode( link.node1()->GetID() + link.node2()->GetID(), aLimit );
}
static Standard_Boolean IsEqual(const SMESH_TLink& l1, const SMESH_TLink& l2)
{
return ( l1.node1() == l2.node1() && l1.node2() == l2.node2() );
}
};
//================================================================================
/*
* Returns groups of TFreeBorder's coincident within the given tolerance.
* If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
* to free borders being compared is used.
*/
//================================================================================
void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
double tolerance,
CoincidentFreeBorders & foundFreeBordes)
{
// find free links
typedef NCollection_DataMap<SMESH_TLink, const SMDS_MeshElement*, TLinkHasher > TLink2FaceMap;
TLink2FaceMap linkMap;
SMDS_FaceIteratorPtr faceIt = mesh.facesIterator();
while ( faceIt->more() )
{
const SMDS_MeshElement* face = faceIt->next();
if ( !face ) continue;
const SMDS_MeshNode* n0 = face->GetNode( face->NbNodes() - 1 );
SMDS_NodeIteratorPtr nodeIt = face->interlacedNodesIterator();
while ( nodeIt->more() )
{
const SMDS_MeshNode* n1 = nodeIt->next();
SMESH_TLink link( n0, n1 );
if ( !linkMap.Bind( link, face ))
linkMap.UnBind( link );
n0 = n1;
}
}
if ( linkMap.IsEmpty() )
return;
// form free borders
std::set < BNode > bNodes;
std::vector< BEdge > bEdges( linkMap.Extent() );
TLink2FaceMap::Iterator linkIt( linkMap );
for ( int iEdge = 0; linkIt.More(); linkIt.Next(), ++iEdge )
{
const SMESH_TLink & link = linkIt.Key();
std::set< BNode >::iterator n1 = bNodes.insert( BNode( link.node1() )).first;
std::set< BNode >::iterator n2 = bNodes.insert( BNode( link.node2() )).first;
bEdges[ iEdge ].Set( &*n1, &*n2, linkIt.Value(), iEdge+1 );
n1->AddLinked( & bEdges[ iEdge ] );
n2->AddLinked( & bEdges[ iEdge ] );
}
linkMap.Clear();
// assign IDs to borders
std::vector< BEdge* > borders; // 1st of connected (via myPrev and myNext) edges
std::set< BNode >::iterator bn = bNodes.begin();
for ( ; bn != bNodes.end(); ++bn )
{
for ( size_t i = 0; i < bn->myLinkedEdges.size(); ++i )
{
if ( bn->myLinkedEdges[i]->myBorderID < 0 )
{
BEdge* be = bn->myLinkedEdges[i];
int borderID = borders.size();
borders.push_back( be );
for ( ; be && be->myBorderID < 0; be = be->myNext )
{
be->myBorderID = borderID;
be->Orient();
}
bool isClosed = ( be == bn->myLinkedEdges[i] );
be = bn->myLinkedEdges[i]->myPrev;
for ( ; be && be->myBorderID < 0; be = be->myPrev )
{
be->myBorderID = borderID;
be->Orient();
}
if ( !isClosed )
while ( borders.back()->myPrev )
borders.back() = borders.back()->myPrev;
borders.back()->SetID( 0 ); // set IDs to all edges of the border
}
}
}
// compute tolerance of each border
double maxTolerance = tolerance;
std::vector< double > bordToler( borders.size(), tolerance );
if ( maxTolerance < std::numeric_limits< double >::min() )
{
// no tolerance provided by the user; compute tolerance of each border
// as one tenth of an average size of faces adjacent to a border
for ( size_t i = 0; i < borders.size(); ++i )
{
double avgFaceSize = 0;
int nbFaces = 0;
BEdge* be = borders[ i ];
do {
double facePerimeter = 0;
gp_Pnt p0 = SMESH_TNodeXYZ( be->myFace->GetNode( be->myFace->NbNodes() - 1 ));
SMDS_NodeIteratorPtr nodeIt = be->myFace->interlacedNodesIterator();
while ( nodeIt->more() )
{
gp_Pnt p1 = SMESH_TNodeXYZ( nodeIt->next() );
facePerimeter += p0.Distance( p1 );
p0 = p1;
}
avgFaceSize += ( facePerimeter / be->myFace->NbCornerNodes() );
nbFaces++;
be = be->myNext;
}
while ( be && be != borders[i] );
bordToler[ i ] = 0.1 * avgFaceSize / nbFaces;
maxTolerance = Max( maxTolerance, bordToler[ i ]);
}
}
// for every border node find close border edges
SMESH_ElementSearcher* searcher =
GetElementSearcher( mesh, getElemIterator( bEdges ), maxTolerance );
SMESHUtils::Deleter< SMESH_ElementSearcher > searcherDeleter( searcher );
std::vector< const SMDS_MeshElement* > candidateEdges;
for ( bn = bNodes.begin(); bn != bNodes.end(); ++bn )
{
gp_Pnt point = SMESH_TNodeXYZ( bn->myNode );
searcher->FindElementsByPoint( point, SMDSAbs_Edge, candidateEdges );
if ( candidateEdges.size() <= bn->myLinkedEdges.size() )
continue;
double nodeTol = 0;
for ( size_t i = 0; i < bn->myLinkedEdges.size(); ++i )
nodeTol = Max( nodeTol, bordToler[ bn->myLinkedEdges[ i ]->myBorderID ]);
for ( size_t i = 0; i < candidateEdges.size(); ++i )
{
const BEdge* be = static_cast< const BEdge* >( candidateEdges[ i ]);
double tol = Max( nodeTol, bordToler[ be->myBorderID ]);
if ( maxTolerance - tol < 1e-12 ||
!SMESH_MeshAlgos::IsOut( be, point, tol ))
bn->AddClose( be );
}
}
// for every border edge find close borders
std::vector< BEdge* > closeEdges;
for ( size_t i = 0; i < bEdges.size(); ++i )
{
BEdge& be = bEdges[i];
if ( be.myBNode1->myCloseEdges.empty() ||
be.myBNode2->myCloseEdges.empty() )
continue;
closeEdges.clear();
for ( size_t iE1 = 0; iE1 < be.myBNode1->myCloseEdges.size(); ++iE1 )
{
// find edges of the same border close to both nodes of the edge
BEdge* closeE1 = be.myBNode1->myCloseEdges[ iE1 ];
BEdge* closeE2 = be.myBNode2->FindCloseEdgeOfBorder( closeE1->myBorderID );
if ( !closeE2 )
continue;
// check that edges connecting closeE1 and closeE2 (if any) are also close to 'be'
if ( closeE1 != closeE2 )
{
bool coincide;
for ( int j = 0; j < 2; ++j ) // move closeE1 -> closeE2 or inversely
{
BEdge* ce = closeE1;
do {
coincide = ( ce->myBNode2->FindCloseEdgeOfBorder( be.myBorderID ));
ce = ce->myNext;
} while ( coincide && ce && ce != closeE2 );
if ( coincide && ce == closeE2 )
break;
if ( j == 0 )
std::swap( closeE1, closeE2 );
coincide = false;
}
if ( !coincide )
continue;
closeEdges.push_back( closeE1 );
closeEdges.push_back( closeE2 );
}
else
{
closeEdges.push_back( closeE1 );
}
be.myCloseBorders.insert( closeE1->myBorderID );
}
if ( !closeEdges.empty() )
{
be.myCloseBorders.insert( be.myBorderID );
// for ( size_t iB = 0; iB < closeEdges.size(); ++iB )
// closeEdges[ iB ]->myCloseBorders.insert( be.myCloseBorders.begin(),
// be.myCloseBorders.end() );
}
}
// Fill in CoincidentFreeBorders
// save nodes of free borders
foundFreeBordes._borders.resize( borders.size() );
for ( size_t i = 0; i < borders.size(); ++i )
{
BEdge* be = borders[i];
foundFreeBordes._borders[i].push_back( be->myBNode1->myNode );
do {
foundFreeBordes._borders[i].push_back( be->myBNode2->myNode );
be = be->myNext;
}
while ( be && be != borders[i] );
}
// form groups of coincident parts of free borders
TFreeBorderPart part;
TCoincidentGroup group;
for ( size_t i = 0; i < borders.size(); ++i )
{
BEdge* be = borders[i];
// look for an edge close to other borders
do {
if ( !be->myInGroup && !be->myCloseBorders.empty() )
break;
be = be->myNext;
} while ( be && be != borders[i] );
if ( !be || be->myInGroup || be->myCloseBorders.empty() )
continue; // all edges of a border treated or are non-coincident
group.clear();
// look for the 1st and last edge of a coincident group
BEdge* beRange[2];
be->FindRangeOfSameCloseBorders( beRange );
BEdge* be1st = beRange[0];
// fill in a group
part._border = i;
part._node1 = beRange[0]->myID;
part._node2 = beRange[0]->myID + 1;
part._nodeLast = beRange[1]->myID + 1;
group.push_back( part );
be = beRange[0];
be->myInGroup = true;
while ( be != beRange[1] )
{
be->myInGroup = true;
be = be->myNext;
}
beRange[1]->myInGroup = true;
// add parts of other borders
std::set<int>::iterator closeBord = be1st->myCloseBorders.begin();
for ( ; closeBord != be1st->myCloseBorders.end(); ++closeBord )
{
be = be1st->myBNode2->FindCloseEdgeOfBorder( *closeBord );
if ( !be ) continue;
be->FindRangeOfSameCloseBorders( beRange );
// find out mutual orientation of borders
bool reverse = ( beRange[0]->myBNode1->FindCloseEdgeOfBorder( i ) != be1st &&
beRange[0]->myBNode2->FindCloseEdgeOfBorder( i ) != be1st );
// fill in a group
part._border = beRange[0]->myBorderID;
if ( reverse ) {
part._node1 = beRange[1]->myID + 1;
part._node2 = beRange[1]->myID;
part._nodeLast = beRange[0]->myID;
}
else {
part._node1 = beRange[0]->myID;
part._node2 = beRange[0]->myID + 1;
part._nodeLast = beRange[1]->myID + 1;
}
group.push_back( part );
be = beRange[0];
be->myInGroup = true;
while ( be != beRange[1] )
{
be->myInGroup = true;
be = be->myNext;
}
beRange[1]->myInGroup = true;
}
foundFreeBordes._coincidentGroups.push_back( group );
} // loop on free borders
}

View File

@ -439,8 +439,10 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
bool _outerFacesFound; bool _outerFacesFound;
set<const SMDS_MeshElement*> _outerFaces; // empty means "no internal faces at all" set<const SMDS_MeshElement*> _outerFaces; // empty means "no internal faces at all"
SMESH_ElementSearcherImpl( SMDS_Mesh& mesh, SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr()) SMESH_ElementSearcherImpl( SMDS_Mesh& mesh,
: _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(-1),_outerFacesFound(false) {} double tol=-1,
SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr())
: _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(tol),_outerFacesFound(false) {}
virtual ~SMESH_ElementSearcherImpl() virtual ~SMESH_ElementSearcherImpl()
{ {
if ( _ebbTree ) delete _ebbTree; _ebbTree = 0; if ( _ebbTree ) delete _ebbTree; _ebbTree = 0;
@ -1091,32 +1093,22 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
// get ordered nodes // get ordered nodes
vector< gp_XYZ > xyz; vector< SMESH_TNodeXYZ > xyz;
vector<const SMDS_MeshNode*> nodeList;
SMDS_ElemIteratorPtr nodeIt = element->nodesIterator(); SMDS_ElemIteratorPtr nodeIt = element->interlacedNodesElemIterator();
if ( element->IsQuadratic() ) {
nodeIt = element->interlacedNodesElemIterator();
// if (const SMDS_VtkFace* f=dynamic_cast<const SMDS_VtkFace*>(element))
// nodeIt = f->interlacedNodesElemIterator();
// else if (const SMDS_VtkEdge* e =dynamic_cast<const SMDS_VtkEdge*>(element))
// nodeIt = e->interlacedNodesElemIterator();
}
while ( nodeIt->more() ) while ( nodeIt->more() )
{ {
SMESH_TNodeXYZ node = nodeIt->next(); SMESH_TNodeXYZ node = nodeIt->next();
xyz.push_back( node ); xyz.push_back( node );
nodeList.push_back(node._node);
} }
int i, nbNodes = (int) nodeList.size(); // central node of biquadratic is missing int i, nbNodes = (int) xyz.size(); // central node of biquadratic is missing
if ( element->GetType() == SMDSAbs_Face ) // -------------------------------------------------- if ( element->GetType() == SMDSAbs_Face ) // --------------------------------------------------
{ {
// compute face normal // compute face normal
gp_Vec faceNorm(0,0,0); gp_Vec faceNorm(0,0,0);
xyz.push_back( xyz.front() ); xyz.push_back( xyz.front() );
nodeList.push_back( nodeList.front() );
for ( i = 0; i < nbNodes; ++i ) for ( i = 0; i < nbNodes; ++i )
{ {
gp_Vec edge1( xyz[i+1], xyz[i]); gp_Vec edge1( xyz[i+1], xyz[i]);
@ -1129,7 +1121,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
// degenerated face: point is out if it is out of all face edges // degenerated face: point is out if it is out of all face edges
for ( i = 0; i < nbNodes; ++i ) for ( i = 0; i < nbNodes; ++i )
{ {
SMDS_LinearEdge edge( nodeList[i], nodeList[i+1] ); SMDS_LinearEdge edge( xyz[i]._node, xyz[i+1]._node );
if ( !IsOut( &edge, point, tol )) if ( !IsOut( &edge, point, tol ))
return false; return false;
} }
@ -1216,13 +1208,28 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
// (we consider quadratic edge as being composed of two straight parts) // (we consider quadratic edge as being composed of two straight parts)
for ( i = 1; i < nbNodes; ++i ) for ( i = 1; i < nbNodes; ++i )
{ {
gp_Vec edge( xyz[i-1], xyz[i]); gp_Vec edge( xyz[i-1], xyz[i] );
gp_Vec n1p ( xyz[i-1], point); gp_Vec n1p ( xyz[i-1], point );
double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude(); // double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude();
if ( dist > tol ) // if ( dist > tol )
// continue;
// gp_Vec n2p( xyz[i], point );
// if ( fabs( edge.Magnitude() - n1p.Magnitude() - n2p.Magnitude()) > tol )
// continue;
double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
if ( u < 0. ) {
if ( n1p.SquareMagnitude() < tol * tol )
return false;
continue; continue;
gp_Vec n2p( xyz[i], point ); }
if ( fabs( edge.Magnitude() - n1p.Magnitude() - n2p.Magnitude()) > tol ) if ( u > 1. ) {
if ( point.SquareDistance( xyz[i] ) < tol * tol )
return false;
continue;
}
gp_XYZ proj = ( 1. - u ) * xyz[i-1] + u * xyz[i]; // projection of the point on the edge
double dist2 = point.SquareDistance( proj );
if ( dist2 > tol * tol )
continue; continue;
return false; // point is ON this part return false; // point is ON this part
} }
@ -1231,7 +1238,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
// Node or 0D element ------------------------------------------------------------------------- // Node or 0D element -------------------------------------------------------------------------
{ {
gp_Vec n2p ( xyz[0], point ); gp_Vec n2p ( xyz[0], point );
return n2p.Magnitude() <= tol; return n2p.SquareMagnitude() <= tol * tol;
} }
return true; return true;
} }
@ -1650,9 +1657,10 @@ SMESH_NodeSearcher* SMESH_MeshAlgos::GetNodeSearcher(SMDS_Mesh& mesh)
*/ */
//======================================================================= //=======================================================================
SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh) SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh,
double tolerance)
{ {
return new SMESH_ElementSearcherImpl( mesh ); return new SMESH_ElementSearcherImpl( mesh, tolerance );
} }
//======================================================================= //=======================================================================
@ -1662,7 +1670,8 @@ SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh)
//======================================================================= //=======================================================================
SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh, SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh,
SMDS_ElemIteratorPtr elemIt) SMDS_ElemIteratorPtr elemIt,
double tolerance)
{ {
return new SMESH_ElementSearcherImpl( mesh, elemIt ); return new SMESH_ElementSearcherImpl( mesh, tolerance, elemIt );
} }

View File

@ -156,10 +156,45 @@ namespace SMESH_MeshAlgos
* \brief Return SMESH_ElementSearcher. The caller is responsible for deleting it * \brief Return SMESH_ElementSearcher. The caller is responsible for deleting it
*/ */
SMESHUtils_EXPORT SMESHUtils_EXPORT
SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh ); SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
double tolerance=-1.);
SMESHUtils_EXPORT SMESHUtils_EXPORT
SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh, SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
SMDS_ElemIteratorPtr elemIt ); SMDS_ElemIteratorPtr elemIt,
} double tolerance=-1. );
typedef std::vector<const SMDS_MeshNode*> TFreeBorder;
typedef std::vector<TFreeBorder> TFreeBorderVec;
struct TFreeBorderPart
{
int _border; // border index within a TFreeBorderVec
int _node1; // node index within the border-th TFreeBorder
int _node2;
int _nodeLast;
};
typedef std::vector<TFreeBorderPart> TCoincidentGroup;
typedef std::vector<TCoincidentGroup> TCoincidentGroupVec;
struct CoincidentFreeBorders
{
TFreeBorderVec _borders; // nodes of all free borders
TCoincidentGroupVec _coincidentGroups; // groups of coincident parts of borders
};
/*!
* Returns TFreeBorder's coincident within the given tolerance.
* If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
* to free borders being compared is used.
*
* (Implemented in ./SMESH_FreeBorders.cxx)
*/
SMESHUtils_EXPORT
void FindCoincidentFreeBorders(SMDS_Mesh& mesh,
double tolerance,
CoincidentFreeBorders & foundFreeBordes);
} // SMESH_MeshAlgos
#endif #endif

View File

@ -2414,6 +2414,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
"Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject", "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject",
"FindCoincidentNodes","MergeNodes","FindEqualElements", "FindCoincidentNodes","MergeNodes","FindEqualElements",
"MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders", "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
"FindCoincidentFreeBorders", "SewCoincidentFreeBorders",
"SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes", "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
"GetLastCreatedElems", "GetLastCreatedElems",
"MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh","TranslateObjectMakeMesh", "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh","TranslateObjectMakeMesh",

View File

@ -547,6 +547,39 @@ namespace SMESH
DumpArray( theList, *this ); DumpArray( theList, *this );
return *this; return *this;
} }
TPythonDump& TPythonDump::operator<<(const SMESH::CoincidentFreeBorders& theCFB)
{
// dump CoincidentFreeBorders as a list of lists, each enclosed list
// contains node IDs of a group of coincident free borders where
// each consequent triple of IDs describe a free border: (n1, n2, nLast)
// For example [[1, 2, 10, 20, 21, 40], [11, 12, 15, 55, 54, 41]] describes
// two groups of coincident free borders, each group including two borders
myStream << "[";
for ( CORBA::ULong i = 0; i < theCFB.coincidentGroups.length(); ++i )
{
const SMESH::FreeBordersGroup& aGRP = theCFB.coincidentGroups[ i ];
if ( i ) myStream << ",";
myStream << "[";
for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
{
const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
if ( 0 <= aPART.border && aPART.border < theCFB.borders.length() )
{
if ( iP ) myStream << ", ";
const SMESH::FreeBorder& aBRD = theCFB.borders[ aPART.border ];
myStream << aBRD.nodeIDs[ aPART.node1 ] << ",";
myStream << aBRD.nodeIDs[ aPART.node2 ] << ",";
myStream << aBRD.nodeIDs[ aPART.nodeLast ];
}
}
myStream << "]";
}
myStream << "]";
return *this;
}
const char* TPythonDump::NotPublishedObjectName() const char* TPythonDump::NotPublishedObjectName()
{ {
return theNotPublishedObjectName; return theNotPublishedObjectName;

View File

@ -4572,6 +4572,182 @@ static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Se
return SMESH::SMESH_MeshEditor::SEW_OK; return SMESH::SMESH_MeshEditor::SEW_OK;
} }
//=======================================================================
/*!
* Returns groups of FreeBorder's coincident within the given tolerance.
* If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
* to free borders being compared is used.
*/
//=======================================================================
SMESH::CoincidentFreeBorders*
SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
{
SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
SMESH_TRY;
SMESH_MeshAlgos::CoincidentFreeBorders cfb;
SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
// copy free borders
aCFB->borders.length( cfb._borders.size() );
for ( size_t i = 0; i < cfb._borders.size(); ++i )
{
SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
SMESH::FreeBorder& aBRD = aCFB->borders[i];
aBRD.nodeIDs.length( nodes.size() );
for ( size_t iN = 0; iN < nodes.size(); ++iN )
aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
}
// copy coincident parts
aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
{
SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
aGRP.length( grp.size() );
for ( size_t iP = 0; iP < grp.size(); ++iP )
{
SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
SMESH::FreeBorderPart& aPART = aGRP[ iP ];
aPART.border = part._border;
aPART.node1 = part._node1;
aPART.node2 = part._node2;
aPART.nodeLast = part._nodeLast;
}
}
SMESH_CATCH( SMESH::doNothing );
TPythonDump() << "CoincidentFreeBorders = "
<< this << ".FindCoincidentFreeBorders( " << tolerance << " )";
return aCFB._retn();
}
//=======================================================================
/*!
* Sew FreeBorder's of each group
*/
//=======================================================================
CORBA::Short SMESH_MeshEditor_i::
SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
CORBA::Boolean createPolygons,
CORBA::Boolean createPolyhedra)
throw (SALOME::SALOME_Exception)
{
CORBA::Short nbSewed = 0;
SMESH_MeshAlgos::TFreeBorderVec groups;
SMESH_MeshAlgos::TFreeBorder borderNodes; // triples on nodes for every FreeBorderPart
// check the input
for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
{
const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
{
const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
if ( aPART.border < 0 || aPART.border >= freeBorders.borders.length() )
THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
if ( aPART.node1 < 0 || aPART.node1 > aBRD.nodeIDs.length() )
THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
if ( aPART.node2 < 0 || aPART.node2 > aBRD.nodeIDs.length() )
THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
if ( aPART.nodeLast < 0 || aPART.nodeLast > aBRD.nodeIDs.length() )
THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
// do not keep these nodes for further sewing as nodes can be removed by the sewing
const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
if ( !n1)
THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
if ( !n2 )
THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
if ( !n3 )
THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
}
}
//TIDSortedElemSet dummy;
::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
{
const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
if ( aGRP.length() < 2 )
continue;
//int n1bord2, n2bord2;
bool groupSewed = false;
for ( CORBA::ULong iP = 1; iP < aGRP.length(); ++iP )
{
const SMESH::FreeBorderPart& aPART_0 = aGRP[ 0 ];
const SMESH::FreeBorder& aBRD_0 = freeBorders.borders[ aPART_0.border ];
const SMDS_MeshNode* n0 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.node1 ]);
const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.node2 ]);
const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.nodeLast ]);
const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
const SMDS_MeshNode* n4 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
const SMDS_MeshNode* n5 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
continue;
// if ( iP == 1 )
// {
// n1bord2 = aBRD.nodeIDs[ aPART.node1 ];
// n2bord2 = aBRD.nodeIDs[ aPART.node2 ];
// }
// else if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, dummy, dummy ))
// {
// // a face including n0 and n1 was split;
// // find a new face starting at n0 in order to get a new n1
// const SMDS_MeshNode* n1test = getMeshDS()->FindNode( n1bord2 );
// const SMDS_MeshNode* n2test = getMeshDS()->FindNode( n2bord2 );
// if ( n1test && SMESH_MeshAlgos::FindFaceInSet( n0, n1test, dummy, dummy ))
// n1 = n1test;
// else if ( n2test && SMESH_MeshAlgos::FindFaceInSet( n0, n2test, dummy, dummy ))
// n1 = n2test;
// // else continue; ??????
// }
if ( iP > 1 )
{
n1 = n2; // at border-to-side sewing only last side node (n1) is needed
n2 = 0; // and n2 is not used
}
// 1st border moves to 2nd
res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
n0 ,n1 ,n2 ,// 2nd
/*2ndIsFreeBorder=*/ iP == 1,
createPolygons, createPolyhedra);
groupSewed = ( res == ok );
}
nbSewed += groupSewed;
}
TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
<< freeBorders << ", "
<< createPolygons << ", "
<< createPolyhedra << " )";
return nbSewed;
}
//======================================================================= //=======================================================================
//function : SewFreeBorders //function : SewFreeBorders
//purpose : //purpose :

View File

@ -538,6 +538,12 @@ public:
CORBA::Short GetPointState(CORBA::Double x, CORBA::Double y, CORBA::Double z) CORBA::Short GetPointState(CORBA::Double x, CORBA::Double y, CORBA::Double z)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
SMESH::CoincidentFreeBorders* FindCoincidentFreeBorders(CORBA::Double tolerance);
CORBA::Short SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
CORBA::Boolean createPolygons,
CORBA::Boolean createPolyedrs)
throw (SALOME::SALOME_Exception);
SMESH::SMESH_MeshEditor::Sew_Error SMESH::SMESH_MeshEditor::Sew_Error
SewFreeBorders(CORBA::Long FirstNodeID1, SewFreeBorders(CORBA::Long FirstNodeID1,
CORBA::Long SecondNodeID1, CORBA::Long SecondNodeID1,
@ -546,15 +552,13 @@ public:
CORBA::Long SecondNodeID2, CORBA::Long SecondNodeID2,
CORBA::Long LastNodeID2, CORBA::Long LastNodeID2,
CORBA::Boolean CreatePolygons, CORBA::Boolean CreatePolygons,
CORBA::Boolean CreatePolyedrs) CORBA::Boolean CreatePolyedrs) throw (SALOME::SALOME_Exception);
throw (SALOME::SALOME_Exception);
SMESH::SMESH_MeshEditor::Sew_Error SMESH::SMESH_MeshEditor::Sew_Error
SewConformFreeBorders(CORBA::Long FirstNodeID1, SewConformFreeBorders(CORBA::Long FirstNodeID1,
CORBA::Long SecondNodeID1, CORBA::Long SecondNodeID1,
CORBA::Long LastNodeID1, CORBA::Long LastNodeID1,
CORBA::Long FirstNodeID2, CORBA::Long FirstNodeID2,
CORBA::Long SecondNodeID2) CORBA::Long SecondNodeID2) throw (SALOME::SALOME_Exception);
throw (SALOME::SALOME_Exception);
SMESH::SMESH_MeshEditor::Sew_Error SMESH::SMESH_MeshEditor::Sew_Error
SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder, SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
CORBA::Long SecondNodeIDOnFreeBorder, CORBA::Long SecondNodeIDOnFreeBorder,
@ -562,16 +566,14 @@ public:
CORBA::Long FirstNodeIDOnSide, CORBA::Long FirstNodeIDOnSide,
CORBA::Long LastNodeIDOnSide, CORBA::Long LastNodeIDOnSide,
CORBA::Boolean CreatePolygons, CORBA::Boolean CreatePolygons,
CORBA::Boolean CreatePolyedrs) CORBA::Boolean CreatePolyedrs) throw (SALOME::SALOME_Exception);
throw (SALOME::SALOME_Exception);
SMESH::SMESH_MeshEditor::Sew_Error SMESH::SMESH_MeshEditor::Sew_Error
SewSideElements(const SMESH::long_array& IDsOfSide1Elements, SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
const SMESH::long_array& IDsOfSide2Elements, const SMESH::long_array& IDsOfSide2Elements,
CORBA::Long NodeID1OfSide1ToMerge, CORBA::Long NodeID1OfSide1ToMerge,
CORBA::Long NodeID1OfSide2ToMerge, CORBA::Long NodeID1OfSide2ToMerge,
CORBA::Long NodeID2OfSide1ToMerge, CORBA::Long NodeID2OfSide1ToMerge,
CORBA::Long NodeID2OfSide2ToMerge) CORBA::Long NodeID2OfSide2ToMerge) throw (SALOME::SALOME_Exception);
throw (SALOME::SALOME_Exception);
/*! /*!
* Set new nodes for given element. * Set new nodes for given element.

View File

@ -27,6 +27,7 @@
#include <SALOMEconfig.h> #include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Mesh) #include CORBA_SERVER_HEADER(SMESH_Mesh)
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
#include CORBA_SERVER_HEADER(GEOM_Gen) #include CORBA_SERVER_HEADER(GEOM_Gen)
#include CORBA_SERVER_HEADER(SALOMEDS) #include CORBA_SERVER_HEADER(SALOMEDS)
@ -229,6 +230,9 @@ namespace SMESH
TPythonDump& TPythonDump&
operator<<(const SMESH::ListOfIDSources& theList); operator<<(const SMESH::ListOfIDSources& theList);
TPythonDump&
operator<<(const SMESH::CoincidentFreeBorders& theCFB);
static const char* SMESHGenName() { return "smeshgen"; } static const char* SMESHGenName() { return "smeshgen"; }
static const char* MeshEditorName() { return "mesh_editor"; } static const char* MeshEditorName() { return "mesh_editor"; }
static const char* NotPublishedObjectName(); static const char* NotPublishedObjectName();

View File

@ -4519,6 +4519,52 @@ class Mesh:
def MergeEqualElements(self): def MergeEqualElements(self):
self.editor.MergeEqualElements() self.editor.MergeEqualElements()
## Returns groups of FreeBorder's coincident within the given tolerance.
# @param tolerance the tolerance. If the tolerance <= 0.0 then one tenth of an average
# size of elements adjacent to free borders being compared is used.
# @return SMESH.CoincidentFreeBorders structure
# @ingroup l2_modif_trsf
def FindCoincidentFreeBorders (self, tolerance=0.):
return self.editor.FindCoincidentFreeBorders( tolerance )
## Sew FreeBorder's of each group
# @param freeBorders either a SMESH.CoincidentFreeBorders structure or a list of lists
# where each enclosed list contains node IDs of a group of coincident free
# borders such that each consequent triple of IDs within a group describes
# a free border in a usual way: n1, n2, nLast - i.e. 1st node, 2nd node and
# last node of a border.
# For example [[1, 2, 10, 20, 21, 40], [11, 12, 15, 55, 54, 41]] describes two
# groups of coincident free borders, each group including two borders.
# @param createPolygons if @c True faces adjacent to free borders are converted to
# polygons if a node of opposite border falls on a face edge, else such
# faces are split into several ones.
# @param createPolyhedra if @c True volumes adjacent to free borders are converted to
# polyhedra if a node of opposite border falls on a volume edge, else such
# volumes, if any, remain intact and the mesh becomes non-conformal.
# @return a number of successfully sewed groups
# @ingroup l2_modif_trsf
def SewCoincidentFreeBorders (self, freeBorders, createPolygons=False, createPolyhedra=False):
if freeBorders and isinstance( freeBorders, list ):
# construct SMESH.CoincidentFreeBorders
if isinstance( freeBorders[0], int ):
freeBorders = [freeBorders]
borders = []
coincidentGroups = []
for nodeList in freeBorders:
if not nodeList or len( nodeList ) % 3:
raise ValueError, "Wrong number of nodes in this group: %s" % nodeList
group = []
while nodeList:
group.append ( SMESH.FreeBorderPart( len(borders), 0, 1, 2 ))
borders.append( SMESH.FreeBorder( nodeList[:3] ))
nodeList = nodeList[3:]
pass
coincidentGroups.append( group )
pass
freeBorders = SMESH.CoincidentFreeBorders( borders, coincidentGroups )
return self.editor.SewCoincidentFreeBorders( freeBorders, createPolygons, createPolyhedra )
## Sews free borders ## Sews free borders
# @return SMESH::Sew_Error # @return SMESH::Sew_Error
# @ingroup l2_modif_trsf # @ingroup l2_modif_trsf