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"
<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
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>
<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
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>
Mesh module distinguishes between the three Group types:
<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
created);
</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
array of dedicated operations;</li>
<li>\subpage grouping_elements_page "creating groups of mesh
elements";</li>
<li>\subpage grouping_elements_page "creating groups" of mesh
elements;</li>
<li>filtering mesh entities (nodes or elements) using
\subpage filters_page "Filters" functionality for \ref
grouping_elements_page "creating groups" and applying \ref
modifying_meshes_page "mesh modifications";</li>
<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",
allowing to highlight important elements;</li>
<li>taking various \subpage measurements_page "measurements" of the

View File

@ -21,10 +21,10 @@ then converted to the single node.
processed.
<li>\b Tolerance is a maximum distance between nodes sufficient for
merging.</li>
<li>Activation of <b>No merge of corner and medium nodes</b> check-box
prevents merging medium nodes of quadratic elements with corner
nodes. This check-box is enabled provided that the selected mesh
includes quadratic elements.</li>
<li>Activation of <b>No merge of corner and medium nodes of quadratic
cells</b> check-box prevents merging medium nodes of quadratic
elements with corner nodes. This check-box is enabled provided
that the selected mesh includes quadratic elements.</li>
<li><b>Exclude Groups</b> group box allows to ignore the nodes which
belong to the specified mesh groups.</li>
<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>
The <b>Mesh Information</b> dialog box provides three tab pages:
- <b>\ref advanced_mesh_infos_anchor "Base Info"</b> - to show base
information about the selected mesh object.
- <b>\ref advanced_mesh_infos_anchor "Base Info"</b> - to show
base and quantitative information about the selected mesh object.
- <b>\ref mesh_element_info_anchor "Element Info"</b> - to show
detailed information about the selected mesh node or element.
- <b>\ref mesh_addition_info_anchor "Additional Info"</b> - to show additional information available
for the selected mesh, sub-mesh or group object.
detailed information about the selected mesh nodes or elements.
- <b>\ref mesh_addition_info_anchor "Additional Info"</b> - to show
additional information available for the selected mesh, sub-mesh or
group object.
- <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
<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
<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

View File

@ -26,8 +26,11 @@ information about the mesh.</li>
<li>\subpage find_element_by_point_page "Find Element by Point" -
allows to find all mesh elements, to which belongs a point with the
given coordinates.</li>
<li><b>Auto Color</b> - switch on / off auto-assigning colors for the groups.</li>
<li>\subpage numbering_page "Numbering" - allows to display the ID
<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
numbers of all meshing elements or nodes composing your mesh in the
viewer.</li>
<li>\subpage display_mode_page "Display Mode" - allows to select between

View File

@ -29,13 +29,37 @@
module SMESH
{
interface NumericalFunctor;
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.
*/
interface NumericalFunctor;
interface SMESH_MeshEditor
{
/*!
@ -723,6 +747,21 @@ module SMESH
short GetPointState(in double x, in double y, in double z)
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 {
SEW_OK,
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 )
return false;
vector<int> anIds( nbNodes );
SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
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 ];
}
theNodeId1 = anElem->GetNode( theEdgeNum - 1 )->GetID();
theNodeId2 = anElem->GetNode( theEdgeNum % nbNodes )->GetID();
return true;
}

View File

@ -42,7 +42,7 @@ int SMDS_MeshNode::nbNodes =0;
//=======================================================================
//function : SMDS_MeshNode
//purpose :
//purpose :
//=======================================================================
SMDS_MeshNode::SMDS_MeshNode() :
SMDS_MeshElement(-1, -1, 0),
@ -83,31 +83,31 @@ SMDS_MeshNode::~SMDS_MeshNode()
//=======================================================================
//function : RemoveInverseElement
//purpose :
//purpose :
//=======================================================================
void SMDS_MeshNode::RemoveInverseElement(const SMDS_MeshElement * parent)
{
//MESSAGE("RemoveInverseElement " << myID << " " << parent->GetID());
const SMDS_MeshCell* cell = dynamic_cast<const SMDS_MeshCell*>(parent);
MYASSERT(cell);
SMDS_Mesh::_meshList[myMeshId]->getGrid()->RemoveReferenceToCell(myVtkID, cell->getVtkId());
//MESSAGE("RemoveInverseElement " << myID << " " << parent->GetID());
const SMDS_MeshCell* cell = dynamic_cast<const SMDS_MeshCell*>(parent);
MYASSERT(cell);
SMDS_Mesh::_meshList[myMeshId]->getGrid()->RemoveReferenceToCell(myVtkID, cell->getVtkId());
}
//=======================================================================
//function : Print
//purpose :
//purpose :
//=======================================================================
void SMDS_MeshNode::Print(ostream & OS) const
{
OS << "Node <" << myID << "> : X = " << X() << " Y = "
<< Y() << " Z = " << Z() << endl;
OS << "Node <" << myID << "> : X = " << X() << " Y = "
<< Y() << " Z = " << Z() << endl;
}
//=======================================================================
//function : SetPosition
//purpose :
//purpose :
//=======================================================================
void SMDS_MeshNode::SetPosition(const SMDS_PositionPtr& aPos)
@ -121,7 +121,7 @@ void SMDS_MeshNode::SetPosition(const SMDS_PositionPtr& aPos)
//=======================================================================
//function : GetPosition
//purpose :
//purpose :
//=======================================================================
const SMDS_PositionPtr& SMDS_MeshNode::GetPosition() const
@ -178,10 +178,10 @@ public:
int smdsId = myMesh->fromVtkToSmds(vtkId);
const SMDS_MeshElement* elem = myMesh->FindElement(smdsId);
if (!elem)
{
MESSAGE("SMDS_MeshNode_MyInvIterator problem Null element");
throw SALOME_Exception("SMDS_MeshNode_MyInvIterator problem Null element");
}
{
MESSAGE("SMDS_MeshNode_MyInvIterator problem Null element");
throw SALOME_Exception("SMDS_MeshNode_MyInvIterator problem Null element");
}
//MESSAGE("vtkId " << vtkId << " smdsId " << smdsId << " " << elem->GetType());
iter++;
return elem;
@ -189,11 +189,11 @@ public:
};
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);
//MESSAGE("myID " << myID << " ncells " << l.ncells);
return SMDS_ElemIteratorPtr(new SMDS_MeshNode_MyInvIterator(SMDS_Mesh::_meshList[myMeshId], l.cells, l.ncells, type));
vtkCellLinks::Link l = SMDS_Mesh::_meshList[myMeshId]->getGrid()->GetCellLinks()->GetLink(myVtkID);
//MESSAGE("myID " << myID << " ncells " << l.ncells);
return SMDS_ElemIteratorPtr(new SMDS_MeshNode_MyInvIterator(SMDS_Mesh::_meshList[myMeshId], l.cells, l.ncells, type));
}
// Same as GetInverseElementIterator but the create iterator only return
@ -208,47 +208,47 @@ private:
int iter;
vector<SMDS_MeshElement*> myFiltCells;
public:
public:
SMDS_MeshNode_MyIterator(SMDS_Mesh *mesh,
vtkIdType* cells,
int ncells,
SMDSAbs_ElementType type):
myMesh(mesh), myCells(cells), myNcells(ncells), myType(type), iter(0)
{
//MESSAGE("myNcells " << myNcells);
for (; iter<ncells; iter++)
{
int vtkId = myCells[iter];
int smdsId = myMesh->fromVtkToSmds(vtkId);
//MESSAGE("vtkId " << vtkId << " smdsId " << smdsId);
const SMDS_MeshElement* elem = myMesh->FindElement(smdsId);
if (elem->GetType() == type)
myFiltCells.push_back((SMDS_MeshElement*)elem);
}
myNcells = myFiltCells.size();
//MESSAGE("myNcells " << myNcells);
iter = 0;
//MESSAGE("SMDS_MeshNode_MyIterator (filter) " << ncells << " " << myNcells);
//MESSAGE("myNcells " << myNcells);
for (; iter<ncells; iter++)
{
int vtkId = myCells[iter];
int smdsId = myMesh->fromVtkToSmds(vtkId);
//MESSAGE("vtkId " << vtkId << " smdsId " << smdsId);
const SMDS_MeshElement* elem = myMesh->FindElement(smdsId);
if (elem->GetType() == type)
myFiltCells.push_back((SMDS_MeshElement*)elem);
}
myNcells = myFiltCells.size();
//MESSAGE("myNcells " << myNcells);
iter = 0;
//MESSAGE("SMDS_MeshNode_MyIterator (filter) " << ncells << " " << myNcells);
}
bool more()
{
return (iter< myNcells);
return (iter< myNcells);
}
const SMDS_MeshElement* next()
{
const SMDS_MeshElement* elem = myFiltCells[iter];
iter++;
return elem;
const SMDS_MeshElement* elem = myFiltCells[iter];
iter++;
return elem;
}
};
SMDS_ElemIteratorPtr SMDS_MeshNode::
elementsIterator(SMDSAbs_ElementType type) const
elementsIterator(SMDSAbs_ElementType type) const
{
if(type==SMDSAbs_Node)
return SMDS_MeshElement::elementsIterator(SMDSAbs_Node);
return SMDS_MeshElement::elementsIterator(SMDSAbs_Node);
else
{
vtkCellLinks::Link l = SMDS_Mesh::_meshList[myMeshId]->getGrid()->GetCellLinks()->GetLink(myVtkID);
@ -258,7 +258,7 @@ SMDS_ElemIteratorPtr SMDS_MeshNode::
int SMDS_MeshNode::NbNodes() const
{
return 1;
return 1;
}
double* SMDS_MeshNode::getCoord() const
@ -305,7 +305,7 @@ void SMDS_MeshNode::setXYZ(double x, double y, double z)
SMDSAbs_ElementType SMDS_MeshNode::GetType() const
{
return SMDSAbs_Node;
return SMDSAbs_Node;
}
vtkIdType SMDS_MeshNode::GetVtkType() const
@ -358,11 +358,11 @@ int SMDS_MeshNode::NbInverseElements(SMDSAbs_ElementType type) const
int nb = 0;
SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
for (int i=0; i<l.ncells; i++)
{
const SMDS_MeshElement* elem = mesh->FindElement(mesh->fromVtkToSmds(l.cells[i]));
if (elem->GetType() == type)
nb++;
}
{
const SMDS_MeshElement* elem = mesh->FindElement(mesh->fromVtkToSmds(l.cells[i]));
if (elem->GetType() == type)
nb++;
}
return nb;
}
@ -371,14 +371,14 @@ int SMDS_MeshNode::NbInverseElements(SMDSAbs_ElementType type) const
///////////////////////////////////////////////////////////////////////////////
bool operator<(const SMDS_MeshNode& e1, const SMDS_MeshNode& e2)
{
return e1.getVtkId()<e2.getVtkId();
/*if(e1.myX<e2.myX) return true;
else if(e1.myX==e2.myX)
{
if(e1.myY<e2.myY) return true;
else if(e1.myY==e2.myY) return (e1.myZ<e2.myZ);
else return false;
}
else return false;*/
return e1.getVtkId()<e2.getVtkId();
/*if(e1.myX<e2.myX) return true;
else if(e1.myX==e2.myX)
{
if(e1.myY<e2.myY) return true;
else if(e1.myY==e2.myY) return (e1.myZ<e2.myZ);
else return false;
}
else return false;*/
}

View File

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

View File

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

View File

@ -142,6 +142,8 @@ SET(_moc_HEADERS
SMESHGUI_FieldSelectorWdg.h
SMESHGUI_DisplayEntitiesDlg.h
SMESHGUI_SplitBiQuad.h
SMESHGUI_PreVisualObj.h
SMESHGUI_IdPreview.h
)
# header files / no moc processing
@ -251,6 +253,8 @@ SET(_other_SOURCES
SMESHGUI_FieldSelectorWdg.cxx
SMESHGUI_DisplayEntitiesDlg.cxx
SMESHGUI_SplitBiQuad.cxx
SMESHGUI_PreVisualObj.cxx
SMESHGUI_IdPreview.cxx
)
# 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.h"
#include "SMESHGUI_Utils.h"
#include "SMESHGUI_VTKUtils.h"
#include "SMESHGUI_IdPreview.h"
#include "SMESHGUI_MeshUtils.h"
#include "SMESHGUI_SpinBox.h"
#include "SMESHGUI_Utils.h"
#include "SMESHGUI_VTKUtils.h"
#include <SMESH_Actor.h>
#include <SMESH_TypeFilter.hxx>
@ -61,34 +62,20 @@
#include CORBA_SERVER_HEADER(SMESH_Group)
#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
#include <QApplication>
#include <QButtonGroup>
#include <QCheckBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QKeyEvent>
#include <QButtonGroup>
#define SPACING 6
#define MARGIN 11
@ -97,208 +84,27 @@ namespace
{
enum ActionType { MERGE_NODES, MERGE_ELEMENTS, TYPE_AUTO=0, TYPE_MANUAL };
}
namespace SMESH
QPixmap SMESHGUI_MergeDlg::IconFirst()
{
class TIdPreview
{ // to display in the viewer IDs of the selected elements
SVTK_ViewWindow* myViewWindow;
vtkUnstructuredGrid* myIdGrid;
SALOME_Actor* myIdActor;
vtkUnstructuredGrid* myPointsNumDataSet;
vtkMaskPoints* myPtsMaskPoints;
vtkSelectVisiblePoints* myPtsSelectVisiblePoints;
vtkLabeledDataMapper* myPtsLabeledDataMapper;
vtkTextProperty* aPtsTextProp;
bool myIsPointsLabeled;
vtkActor2D* myPointLabels;
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",
" . . ",
" .. .. .. ",
" .. ... ... ",
" .. .... .... ",
" .. ..... ..... ",
" .. ..... ..... ",
" .. .... .... ",
" .. ... ... ",
" .. .. .. ",
" . . "};
return iconFirst;
}
static const char * IconFirst[] = {
"18 10 2 1",
" g None",
". g #000000",
" . . ",
" .. .. .. ",
" .. ... ... ",
" .. .... .... ",
" .. ..... ..... ",
" .. ..... ..... ",
" .. .... .... ",
" .. ... ... ",
" .. .. .. ",
" . . "};
//=================================================================================
// class : SMESHGUI_MergeDlg()
// purpose :
@ -313,7 +119,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
setAttribute(Qt::WA_DeleteOnClose, true);
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 );
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->setIcon(IconRemove);
SetFirstButton = new QPushButton(GroupEdit);
SetFirstButton->setIcon(QPixmap(IconFirst));
SetFirstButton->setIcon(IconFirst());
GroupEditLayout->addWidget(ListEdit, 0, 0, 2, 1);
GroupEditLayout->addWidget(AddElemButton, 0, 1);
@ -645,8 +451,9 @@ void SMESHGUI_MergeDlg::Init()
// function : FindGravityCenter()
// purpose :
//=================================================================================
void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
std::list< gp_XYZ > & theGrCentersXYZ)
void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
std::vector<int>& theIDs,
std::list< gp_XYZ > & theGrCentersXYZ)
{
if (!myActor)
return;
@ -658,11 +465,13 @@ void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
int nbNodes;
theIDs.reserve( theElemsIdMap.Extent() );
TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap );
for( ; idIter.More(); idIter.Next() ) {
const SMDS_MeshElement* anElem = aMesh->FindElement(idIter.Key());
if ( !anElem )
continue;
theIDs.push_back( idIter.Key() );
gp_XYZ anXYZ(0., 0., 0.);
SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator();
@ -948,7 +757,7 @@ void SMESHGUI_MergeDlg::onDetect()
SMESH::SMESH_IDSource_var src;
if ( mySubMeshOrGroup->_is_nil() ) src = SMESH::SMESH_IDSource::_duplicate( myMesh );
else src = SMESH::SMESH_IDSource::_duplicate( mySubMeshOrGroup );
else src = SMESH::SMESH_IDSource::_duplicate( mySubMeshOrGroup );
switch (myAction) {
case MERGE_NODES :
@ -1034,8 +843,9 @@ void SMESHGUI_MergeDlg::onSelectGroup()
}
else {
std::list< gp_XYZ > aGrCentersXYZ;
FindGravityCenter(anIndices, aGrCentersXYZ);
myIdPreview->SetElemsData( anIndices, aGrCentersXYZ);
std::vector<int> anIDs;
FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
myIdPreview->SetElemsData( anIDs, aGrCentersXYZ );
myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
}
else
@ -1087,8 +897,9 @@ void SMESHGUI_MergeDlg::onSelectElementFromGroup()
}
else {
std::list< gp_XYZ > aGrCentersXYZ;
FindGravityCenter(anIndices, aGrCentersXYZ);
myIdPreview->SetElemsData(anIndices, aGrCentersXYZ);
std::vector<int> anIDs;
FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
myIdPreview->SetElemsData(anIDs, aGrCentersXYZ);
myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
}
else

View File

@ -38,25 +38,27 @@
// STL includes
#include <list>
#include <vector>
// IDL includes
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Mesh)
class LightApp_SelectionMgr;
class QButtonGroup;
class QCheckBox;
class QGroupBox;
class QLabel;
class QLineEdit;
class QListWidget;
class QPushButton;
class QRadioButton;
class QCheckBox;
class QListWidget;
class QButtonGroup;
class SMESHGUI;
class SMESHGUI_IdPreview;
class SMESHGUI_SpinBox;
class SMESH_Actor;
class SVTK_Selector;
class LightApp_SelectionMgr;
class SUIT_SelectionFilter;
class SVTK_Selector;
class TColStd_MapOfInteger;
namespace SMESH
@ -76,6 +78,8 @@ public:
SMESHGUI_MergeDlg( SMESHGUI*, int );
~SMESHGUI_MergeDlg();
static QPixmap IconFirst();
private:
void Init();
void enterEvent( QEvent* ); /* mouse enter the QWidget */
@ -84,7 +88,8 @@ private:
bool isKeepNodesIDsSelection();
bool isNewKeepNodesGroup( const char* entry );
void FindGravityCenter( TColStd_MapOfInteger&,
void FindGravityCenter( TColStd_MapOfInteger&,
std::vector<int>& ,
std::list<gp_XYZ>& );
// add the centers of gravity of ElemsIdMap elements to the GrCentersXYZ list
@ -103,7 +108,7 @@ private:
SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter;
SUIT_SelectionFilter* mySubMeshOrGroupFilter;
SMESH::TIdPreview* myIdPreview;
SMESHGUI_IdPreview* myIdPreview;
int myAction;
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
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Mesh)
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
#include <vector>
class QButtonGroup;
class QGroupBox;
@ -48,6 +51,10 @@ class SMESHGUI;
class SMESH_Actor;
class SVTK_Selector;
class LightApp_SelectionMgr;
class SMESHGUI_SpinBox;
class SalomeApp_IntSpinBox;
class QListWidget;
class QListWidgetItem;
//=================================================================================
// class : SMESHGUI_SewingDlg
@ -67,7 +74,8 @@ private:
void keyPressEvent( QKeyEvent* );
int GetConstructorId();
bool IsValid();
void UpdateButtons();
SMESHGUI* mySMESHGUI; /* Current SMESHGUI object */
LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */
int myOk1, myOk2, myOk3, myOk4, myOk5, myOk6;
@ -114,13 +122,67 @@ private:
QCheckBox* CheckBoxPolygons;
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;
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();
private slots:
private slots:
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();
bool ClickOnApply();
void ClickOnHelp();

View File

@ -5141,7 +5141,7 @@ Please select a group and try again</translation>
</message>
<message>
<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>
<source>KEEP_NODES</source>
@ -5155,10 +5155,6 @@ Please select a group and try again</translation>
<source>SELECT</source>
<translation>Select: </translation>
</message>
<message>
<source></source>
<translation></translation>
</message>
</context>
<context>
<name>SMESHGUI_ExtrusionAlongPathDlg</name>
@ -6665,6 +6661,42 @@ It is impossible to read point coordinates from file</translation>
<source>SIDE_2</source>
<translation>Side 2</translation>
</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>
<name>SMESHGUI_ShapeByMeshDlg</name>

View File

@ -79,6 +79,7 @@ SET(SMESHUtils_SOURCES
SMESH_File.cxx
SMESH_MeshAlgos.cxx
SMESH_MAT2d.cxx
SMESH_FreeBorders.cxx
)
# --- 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;
set<const SMDS_MeshElement*> _outerFaces; // empty means "no internal faces at all"
SMESH_ElementSearcherImpl( SMDS_Mesh& mesh, SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr())
: _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(-1),_outerFacesFound(false) {}
SMESH_ElementSearcherImpl( SMDS_Mesh& mesh,
double tol=-1,
SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr())
: _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(tol),_outerFacesFound(false) {}
virtual ~SMESH_ElementSearcherImpl()
{
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
vector< gp_XYZ > xyz;
vector<const SMDS_MeshNode*> nodeList;
vector< SMESH_TNodeXYZ > xyz;
SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
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();
}
SMDS_ElemIteratorPtr nodeIt = element->interlacedNodesElemIterator();
while ( nodeIt->more() )
{
SMESH_TNodeXYZ node = nodeIt->next();
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 ) // --------------------------------------------------
{
// compute face normal
gp_Vec faceNorm(0,0,0);
xyz.push_back( xyz.front() );
nodeList.push_back( nodeList.front() );
for ( i = 0; i < nbNodes; ++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
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 ))
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)
for ( i = 1; i < nbNodes; ++i )
{
gp_Vec edge( xyz[i-1], xyz[i]);
gp_Vec n1p ( xyz[i-1], point);
double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude();
if ( dist > tol )
gp_Vec edge( xyz[i-1], xyz[i] );
gp_Vec n1p ( xyz[i-1], point );
// double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude();
// 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;
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;
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 -------------------------------------------------------------------------
{
gp_Vec n2p ( xyz[0], point );
return n2p.Magnitude() <= tol;
return n2p.SquareMagnitude() <= tol * tol;
}
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,
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
*/
SMESHUtils_EXPORT
SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh );
SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
double tolerance=-1.);
SMESHUtils_EXPORT
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

View File

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

View File

@ -547,6 +547,39 @@ namespace SMESH
DumpArray( theList, *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()
{
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;
}
//=======================================================================
/*!
* 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
//purpose :
@ -4621,14 +4797,14 @@ SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
SMESH::SMESH_MeshEditor::Sew_Error error =
convError( getEditor().SewFreeBorder (aBorderFirstNode,
aBorderSecondNode,
aBorderLastNode,
aSide2FirstNode,
aSide2SecondNode,
aSide2ThirdNode,
true,
CreatePolygons,
CreatePolyedrs) );
aBorderSecondNode,
aBorderLastNode,
aSide2FirstNode,
aSide2SecondNode,
aSide2ThirdNode,
true,
CreatePolygons,
CreatePolyedrs) );
declareMeshModified( /*isReComputeSafe=*/false );
@ -4681,13 +4857,13 @@ SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
SMESH::SMESH_MeshEditor::Sew_Error error =
convError( getEditor().SewFreeBorder (aBorderFirstNode,
aBorderSecondNode,
aBorderLastNode,
aSide2FirstNode,
aSide2SecondNode,
aSide2ThirdNode,
true,
false, false) );
aBorderSecondNode,
aBorderLastNode,
aSide2FirstNode,
aSide2SecondNode,
aSide2ThirdNode,
true,
false, false) );
declareMeshModified( /*isReComputeSafe=*/false );
return error;
@ -4743,14 +4919,14 @@ SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
SMESH::SMESH_MeshEditor::Sew_Error error =
convError( getEditor().SewFreeBorder (aBorderFirstNode,
aBorderSecondNode,
aBorderLastNode,
aSide2FirstNode,
aSide2SecondNode,
aSide2ThirdNode,
false,
CreatePolygons,
CreatePolyedrs) );
aBorderSecondNode,
aBorderLastNode,
aSide2FirstNode,
aSide2SecondNode,
aSide2ThirdNode,
false,
CreatePolygons,
CreatePolyedrs) );
declareMeshModified( /*isReComputeSafe=*/false );
return error;

View File

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

View File

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

View File

@ -4519,6 +4519,52 @@ class Mesh:
def MergeEqualElements(self):
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
# @return SMESH::Sew_Error
# @ingroup l2_modif_trsf