\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
</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>.
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
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
<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>
\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
<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
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
{
/*!
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,
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;
}
//=======================================================================
//function : SMDS_MeshNode
-//purpose :
+//purpose :
//=======================================================================
SMDS_MeshNode::SMDS_MeshNode() :
SMDS_MeshElement(-1, -1, 0),
//=======================================================================
//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)
//=======================================================================
//function : GetPosition
-//purpose :
+//purpose :
//=======================================================================
const SMDS_PositionPtr& SMDS_MeshNode::GetPosition() const
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;
};
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
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);
int SMDS_MeshNode::NbNodes() const
{
- return 1;
+ return 1;
}
double* SMDS_MeshNode::getCoord() const
SMDSAbs_ElementType SMDS_MeshNode::GetType() const
{
- return SMDSAbs_Node;
+ return SMDSAbs_Node;
}
vtkIdType SMDS_MeshNode::GetVtkType() 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;
}
///////////////////////////////////////////////////////////////////////////////
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;*/
}
//=======================================================================
//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
// ---------------------------------------------------------------
// 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 );
SMESHGUI_FieldSelectorWdg.h
SMESHGUI_DisplayEntitiesDlg.h
SMESHGUI_SplitBiQuad.h
+ SMESHGUI_PreVisualObj.h
+ SMESHGUI_IdPreview.h
)
# header files / no moc processing
SMESHGUI_FieldSelectorWdg.cxx
SMESHGUI_DisplayEntitiesDlg.cxx
SMESHGUI_SplitBiQuad.cxx
+ SMESHGUI_PreVisualObj.cxx
+ SMESHGUI_IdPreview.cxx
)
# sources / to compile
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
#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>
#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
{
enum ActionType { MERGE_NODES, MERGE_ELEMENTS, TYPE_AUTO=0, TYPE_MANUAL };
}
-namespace SMESH
-{
- 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();
- }
- };
+QPixmap SMESHGUI_MergeDlg::IconFirst()
+{
+ 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 :
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")));
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);
// 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;
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();
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 :
}
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
}
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
// 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
SMESHGUI_MergeDlg( SMESHGUI*, int );
~SMESHGUI_MergeDlg();
+ static QPixmap IconFirst();
+
private:
void Init();
void enterEvent( QEvent* ); /* mouse enter the QWidget */
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
SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter;
SUIT_SelectionFilter* mySubMeshOrGroupFilter;
- SMESH::TIdPreview* myIdPreview;
+ SMESHGUI_IdPreview* myIdPreview;
int myAction;
bool myIsBusy;
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
#include "SMESHGUI_SewingDlg.h"
#include "SMESHGUI.h"
+#include "SMESHGUI_IdPreview.h"
+#include "SMESHGUI_IdValidator.h"
+#include "SMESHGUI_MergeDlg.h"
+#include "SMESHGUI_MeshUtils.h"
+#include "SMESHGUI_PreVisualObj.h"
+#include "SMESHGUI_SpinBox.h"
#include "SMESHGUI_Utils.h"
#include "SMESHGUI_VTKUtils.h"
-#include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_IdValidator.h"
-#include <SMESH_Actor.h>
#include <SMDS_Mesh.hxx>
+#include <SMESH_Actor.h>
+#include <SMESH_TypeDefs.hxx>
// SALOME GUI includes
-#include <SUIT_Session.h>
-#include <SUIT_ResourceMgr.h>
+#include <LightApp_Application.h>
+#include <LightApp_SelectionMgr.h>
+#include <SALOME_ListIO.hxx>
#include <SUIT_Desktop.h>
#include <SUIT_MessageBox.h>
#include <SUIT_OverrideCursor.h>
-
-#include <LightApp_Application.h>
-#include <LightApp_SelectionMgr.h>
-
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
#include <SVTK_ViewModel.h>
#include <SVTK_ViewWindow.h>
-#include <SALOME_ListIO.hxx>
+#include <SalomeApp_IntSpinBox.h>
// OCCT includes
#include <TColStd_MapOfInteger.hxx>
// 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 <QToolButton>
#include <QVBoxLayout>
-#include <QGridLayout>
-#include <QKeyEvent>
-
-// IDL includes
-#include <SALOMEconfig.h>
-#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
#define SPACING 6
#define MARGIN 11
+namespace
+{
+ enum ActionType { MODE_AUTO=0, MODE_MANUAL,
+ MOVE_LEFT_1=0, MOVE_RIGHT_1, MOVE_LEFT_2, MOVE_RIGHT_2,
+ GROUP_COLOR=Qt::UserRole, GROUP_INDEX };
+}
+
+//=================================================================================
+/*!
+ * \brief Dispalayer of free borders
+ */
+//=================================================================================
+
+struct SMESHGUI_SewingDlg::BorderGroupDisplayer
+{
+ const SMESH::ListOfFreeBorders& myBorders;
+ const SMESH::FreeBordersGroup& myGroup;
+ QColor myColor;
+ SMESH::SMESH_Mesh_ptr myMesh;
+
+ std::vector< SMESH_Actor* > myPartActors;
+ SVTK_ViewWindow* myViewWindow;
+ SMESHGUI_IdPreview myIdPreview;
+
+ BorderGroupDisplayer( const SMESH::CoincidentFreeBorders& borders,
+ int groupIndex,
+ QColor color,
+ SMESH::SMESH_Mesh_ptr mesh);
+ ~BorderGroupDisplayer();
+ void Hide();
+ void ShowGroup( bool wholeBorders );
+ void ShowPart( int partIndex, bool toEdit );
+ void Update();
+
+private:
+ void getPartEnds( int partIndex, std::vector<int> & ids, std::list<gp_XYZ>& coords);
+};
+
//=================================================================================
// class : SMESHGUI_SewingDlg()
// purpose :
QPixmap image2 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_BORDERTOSIDE")));
QPixmap image3 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_SIDEELEMENTS")));
QPixmap image4 (mgr->loadPixmap("SMESH", tr("ICON_SELECT")));
+ QPixmap IconRemove(mgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
setModal(false);
setAttribute(Qt::WA_DeleteOnClose, true);
// Control for the polyedres creation to obtain conform mesh
CheckBoxPolyedrs = new QCheckBox(tr("CREATE_POLYEDRS_NEAR_BOUNDARY"), GroupArguments);
+ /***************************************************************/
+ // Controls to switch free borders mode ( auto || manual )
+
+ ModeGroup = new QGroupBox( tr( "SMESH_MODE" ), GroupArguments );
+ ModeButGrp = new QButtonGroup( ModeGroup );
+ QHBoxLayout* aModeGroupLayout = new QHBoxLayout( ModeGroup );
+ aModeGroupLayout->setMargin( MARGIN );
+ aModeGroupLayout->setSpacing( SPACING );
+
+ QRadioButton* rb1 = new QRadioButton( tr( "SMESH_AUTOMATIC" ), ModeGroup );
+ QRadioButton* rb2 = new QRadioButton( tr( "SMESH_MANUAL" ), ModeGroup );
+ ModeButGrp->addButton( rb1, MODE_AUTO );
+ ModeButGrp->addButton( rb2, MODE_MANUAL );
+ aModeGroupLayout->addWidget( rb1 );
+ aModeGroupLayout->addWidget( rb2 );
+ rb1->setChecked(true);
+
+ /***************************************************************/
+ // Controls for detecting coincident free borders
+
+ SewFreeBordersWidget = new QWidget( GroupArguments );
+ QVBoxLayout* aSewFreeBordersLayout = new QVBoxLayout( SewFreeBordersWidget );
+ aSewFreeBordersLayout->setMargin( 0 );
+ aSewFreeBordersLayout->setSpacing( SPACING );
+
+ // Tolerance
+ QWidget* TolAndAuto = new QWidget(SewFreeBordersWidget);
+ QLabel* TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), TolAndAuto);
+ SpinBoxTolerance = new SMESHGUI_SpinBox(TolAndAuto);
+ SpinBoxTolerance->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ SpinBoxTolerance->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision");
+ SpinBoxTolerance->SetValue(0.); // auto-tolerance
+
+ // Auto Sewing
+ AutoSewCheck = new QCheckBox(tr("AUTO_SEWING"), TolAndAuto);
+ AutoSewCheck->setChecked( true );
+
+ // mesh
+ QGroupBox* GroupMesh = new QGroupBox(tr("SMESH_SELECT_WHOLE_MESH"), SewFreeBordersWidget);
+ QHBoxLayout* GroupMeshLayout = new QHBoxLayout(GroupMesh);
+ GroupMeshLayout->setSpacing(SPACING);
+ GroupMeshLayout->setMargin(MARGIN);
+
+ QLabel* TextLabelName = new QLabel(tr("SMESH_NAME"), GroupMesh);
+ //SelectMeshButton = new QPushButton(GroupMesh);
+ //SelectMeshButton->setIcon(IconSelect);
+ LineEditMesh = new QLineEdit(GroupMesh);
+ LineEditMesh->setReadOnly(true);
+
+ GroupMeshLayout->addWidget(TextLabelName);
+ //GroupMeshLayout->addWidget(SelectMeshButton);
+ GroupMeshLayout->addWidget(LineEditMesh);
+
+ QGridLayout* TolAndAutoLayout = new QGridLayout( TolAndAuto );
+ TolAndAutoLayout->setSpacing(SPACING);
+ TolAndAutoLayout->setMargin(0);
+ TolAndAutoLayout->addWidget(GroupMesh, 0, 0, 1, 2 );
+ TolAndAutoLayout->addWidget(TextLabelTolerance, 1, 0 );
+ TolAndAutoLayout->addWidget(SpinBoxTolerance, 1, 1 );
+ TolAndAutoLayout->addWidget(AutoSewCheck, 2, 0 );
+
+ aSewFreeBordersLayout->addWidget( TolAndAuto );
+
+ /******************/
+ // Coincident group
+ GroupCoincidentWidget = new QWidget(SewFreeBordersWidget);
+ QGridLayout* GroupCoincidentLayout = new QGridLayout(GroupCoincidentWidget);
+ GroupCoincidentLayout->setSpacing(SPACING);
+ GroupCoincidentLayout->setMargin(0);
+
+ QGroupBox* GroupCoincident = new QGroupBox(tr("COINCIDENT_FREE_BORDERS"), GroupCoincidentWidget);
+ QGridLayout* aCoincidentLayout = new QGridLayout(GroupCoincident);
+ aCoincidentLayout->setSpacing(SPACING);
+ aCoincidentLayout->setMargin(MARGIN);
+
+ /*******/
+ // borders
+ ListCoincident = new QListWidget(GroupCoincident);
+ ListCoincident->setSelectionMode(QListWidget::ExtendedSelection);
+
+ DetectButton = new QPushButton(tr("DETECT"), GroupCoincident);
+ RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincident);
+
+ SelectAllCheck = new QCheckBox(tr("SELECT_ALL"), GroupCoincident);
+
+ aCoincidentLayout->addWidget(ListCoincident, 0, 0, 4, 2);
+ aCoincidentLayout->addWidget(DetectButton, 1, 2);
+ aCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
+ aCoincidentLayout->addWidget(SelectAllCheck, 4, 0);
+ aCoincidentLayout->setRowMinimumHeight(1, 10);
+ aCoincidentLayout->setRowStretch (1, 5);
+
+ GroupCoincidentLayout->addWidget( GroupCoincident );
+
+ /*****************************************/
+ // Controls for editing the selected group
+
+ QGroupBox* GroupEdit = new QGroupBox(tr("EDIT_SELECTED_GROUP"), GroupCoincidentWidget);
+ QGridLayout* GroupEditLayout = new QGridLayout(GroupEdit);
+ GroupEditLayout->setSpacing(SPACING);
+ GroupEditLayout->setMargin(MARGIN);
+
+ ListEdit = new QListWidget(GroupEdit);
+ ListEdit->setFlow( QListView::LeftToRight );
+ ListEdit->setSelectionMode(QListWidget::ExtendedSelection);
+ SetFirstButton = new QPushButton(GroupEdit);
+ SetFirstButton->setIcon(QPixmap(SMESHGUI_MergeDlg::IconFirst()));
+ RemoveElemButton = new QPushButton(GroupEdit);
+ RemoveElemButton->setIcon(IconRemove);
+
+ MoveBorderEndsButGrp = new QButtonGroup( GroupEdit );
+ QToolButton* moveBut1 = new QToolButton( GroupEdit );
+ QToolButton* moveBut2 = new QToolButton( GroupEdit );
+ QToolButton* moveBut3 = new QToolButton( GroupEdit );
+ QToolButton* moveBut4 = new QToolButton( GroupEdit );
+ moveBut1->setArrowType( Qt::LeftArrow );
+ moveBut2->setArrowType( Qt::RightArrow );
+ moveBut3->setArrowType( Qt::LeftArrow );
+ moveBut4->setArrowType( Qt::RightArrow );
+ MoveBorderEndsButGrp->addButton( moveBut1, MOVE_LEFT_1 );
+ MoveBorderEndsButGrp->addButton( moveBut2, MOVE_RIGHT_1 );
+ MoveBorderEndsButGrp->addButton( moveBut3, MOVE_LEFT_2 );
+ MoveBorderEndsButGrp->addButton( moveBut4, MOVE_RIGHT_2 );
+
+ SwapBut = new QPushButton( "<->", GroupEdit );
+ BorderEndLine[0] = new QLineEdit( GroupEdit );
+ BorderEndLine[1] = new QLineEdit( GroupEdit );
+ BorderEndLine[0]->setReadOnly(true);
+ BorderEndLine[1]->setReadOnly(true);
+ QLabel* StepLabel = new QLabel(tr("STEP"), GroupEdit );
+ StepSpin = new SalomeApp_IntSpinBox( 1, 100000, 1, GroupEdit,
+ /*acceptNames=*/false, /*showTip=*/false );
+ StepSpin->setValue( 1 );
+
+ GroupEditLayout->addWidget(ListEdit, 0, 0, 1, 8);
+ GroupEditLayout->addWidget(SetFirstButton, 0, 8);
+ GroupEditLayout->addWidget(RemoveElemButton, 0, 9);
+ GroupEditLayout->addWidget(moveBut1, 1, 0);
+ GroupEditLayout->addWidget(BorderEndLine[0], 1, 1);
+ GroupEditLayout->addWidget(moveBut2, 1, 2);
+ GroupEditLayout->addWidget(moveBut3, 1, 3);
+ GroupEditLayout->addWidget(BorderEndLine[1], 1, 4);
+ GroupEditLayout->addWidget(moveBut4, 1, 5);
+ GroupEditLayout->setColumnStretch( 6, 5 );
+ GroupEditLayout->addWidget(SwapBut, 1, 7);
+ GroupEditLayout->addWidget(StepLabel, 1, 8);
+ GroupEditLayout->addWidget(StepSpin, 1, 9);
+
+ GroupCoincidentLayout->addWidget( GroupEdit );
+ aSewFreeBordersLayout->addWidget( GroupCoincidentWidget );
+
// layout
+ GroupArgumentsLayout->addWidget(ModeGroup);
GroupArgumentsLayout->addWidget(SubGroup1);
GroupArgumentsLayout->addWidget(SubGroup2);
+ GroupArgumentsLayout->addWidget(SewFreeBordersWidget);
GroupArgumentsLayout->addWidget(CheckBoxMerge);
GroupArgumentsLayout->addWidget(CheckBoxPolygons);
GroupArgumentsLayout->addWidget(CheckBoxPolyedrs);
SMESHGUI_SewingDlgLayout->addWidget(ConstructorsBox);
SMESHGUI_SewingDlgLayout->addWidget(GroupArguments);
SMESHGUI_SewingDlgLayout->addWidget(GroupButtons);
+ //SMESHGUI_SewingDlgLayout->setStretch( 2, 10 );
/* Initialisations */
RadioButton1->setChecked(true);
myHelpFileName = "sewing_meshes_page.html";
+ myActor = 0;
+ setDisplayMode();
+
Init();
/* signals and slots connections */
connect(LineEdit5, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
connect(LineEdit6, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
+ connect(ModeButGrp, SIGNAL(buttonClicked(int)), SLOT(onModeChange(int)));
+ connect(AutoSewCheck, SIGNAL(stateChanged(int)), SLOT(onAutoSew(int)));
+ connect(DetectButton, SIGNAL(clicked()), SLOT(onDetectClicked()));
+ connect(RemoveGroupButton, SIGNAL(clicked()), SLOT(onRemoveGroupClicked()));
+ connect(ListCoincident, SIGNAL(itemSelectionChanged()), SLOT(onSelectGroup()));
+ connect(SelectAllCheck, SIGNAL(stateChanged(int)), SLOT(onSelectAll(int)));
+ connect(ListEdit, SIGNAL(itemSelectionChanged()), SLOT(onSelectBorderPartFromGroup()));
+ connect(SetFirstButton, SIGNAL(clicked()), SLOT(onSetFirstClicked()));
+ connect(RemoveElemButton, SIGNAL(clicked()), SLOT(onRemoveElemClicked()));
+ connect(MoveBorderEndsButGrp, SIGNAL(buttonClicked(int)), SLOT(onMoveBorderEnd(int)));
+ connect(SwapBut, SIGNAL(clicked()), SLOT(onSwapClicked()));
+
ConstructorsClicked(0);
}
//=================================================================================
SMESHGUI_SewingDlg::~SMESHGUI_SewingDlg()
{
+ for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+ {
+ delete myBorderDisplayers[ i ];
+ myBorderDisplayers[ i ] = 0;
+ }
+ myBorderDisplayers.clear();
}
//=================================================================================
{
myBusy = false;
- myEditCurrentArgument = LineEdit1;
- LineEdit1->setFocus();
- myActor = 0;
+ if ( LineEdit1->isVisible() )
+ myEditCurrentArgument = LineEdit1;
+ else
+ myEditCurrentArgument = LineEditMesh;
+ myEditCurrentArgument->setFocus();
+ //myActor = 0;
myMesh = SMESH::SMESH_Mesh::_nil();
- CheckBoxMerge->setChecked(false);
- CheckBoxPolygons->setChecked(false);
- CheckBoxPolyedrs->setChecked(false);
+ // CheckBoxMerge->setChecked(false);
+ // CheckBoxPolygons->setChecked(false);
+ // CheckBoxPolyedrs->setChecked(false);
SelectionIntoArgument();
}
CheckBoxPolyedrs->hide();
}
+ if (( !SubGroup1->isVisible() ) &&
+ ( constructorId != 0 || ModeButGrp->checkedId() == MODE_MANUAL ))
+ {
+ SubGroup1->show();
+ SubGroup2->show();
+ }
+
+ if ( constructorId != 0 )
+ {
+ ModeGroup->hide();
+ SewFreeBordersWidget->hide();
+ }
+
+ bool isNodeSelection = true;
+
switch (constructorId) {
case 0:
- {
- GroupArguments->setTitle(tr("SEW_FREE_BORDERS"));
- SubGroup1->setTitle(tr("BORDER_1"));
- SubGroup2->setTitle(tr("BORDER_2"));
+ {
+ GroupArguments->setTitle(tr("SEW_FREE_BORDERS"));
+ SubGroup1->setTitle(tr("BORDER_1"));
+ SubGroup2->setTitle(tr("BORDER_2"));
- if (!CheckBoxPolygons->isVisible())
- CheckBoxPolygons->show();
- if (!CheckBoxPolyedrs->isVisible())
- CheckBoxPolyedrs->show();
+ if (!CheckBoxPolygons->isVisible())
+ CheckBoxPolygons->show();
+ if (!CheckBoxPolyedrs->isVisible())
+ CheckBoxPolyedrs->show();
- break;
+ if ( !ModeGroup->isVisible() )
+ {
+ ModeGroup->show();
}
+ onModeChange( ModeButGrp->checkedId() );
+
+ isNodeSelection = ( ModeButGrp->checkedId() == MODE_MANUAL );
+
+ break;
+ }
case 1:
- {
- GroupArguments->setTitle(tr("SEW_CONFORM_FREE_BORDERS"));
- SubGroup1->setTitle(tr("BORDER_1"));
- SubGroup2->setTitle(tr("BORDER_2"));
+ {
+ GroupArguments->setTitle(tr("SEW_CONFORM_FREE_BORDERS"));
+ SubGroup1->setTitle(tr("BORDER_1"));
+ SubGroup2->setTitle(tr("BORDER_2"));
- TextLabel6->setEnabled(false);
- SelectButton6->setEnabled(false);
- LineEdit6->setEnabled(false);
+ TextLabel6->setEnabled(false);
+ SelectButton6->setEnabled(false);
+ LineEdit6->setEnabled(false);
- myOk6 = true;
+ myOk6 = true;
- break;
- }
+ break;
+ }
case 2:
- {
- GroupArguments->setTitle(tr("SEW_BORDER_TO_SIDE"));
- SubGroup1->setTitle(tr("BORDER"));
- SubGroup2->setTitle(tr("SIDE"));
-
- TextLabel5->setEnabled(false);
- SelectButton5->setEnabled(false);
- LineEdit5->setEnabled(false);
-
- if (!CheckBoxPolygons->isVisible())
- CheckBoxPolygons->show();
- if (!CheckBoxPolyedrs->isVisible())
- CheckBoxPolyedrs->show();
-
- myOk5 = true;
-
- break;
- }
- case 3:
- {
- GroupArguments->setTitle(tr("SEW_SIDE_ELEMENTS"));
- SubGroup1->setTitle(tr("SIDE_1"));
- SubGroup2->setTitle(tr("SIDE_2"));
+ {
+ GroupArguments->setTitle(tr("SEW_BORDER_TO_SIDE"));
+ SubGroup1->setTitle(tr("BORDER"));
+ SubGroup2->setTitle(tr("SIDE"));
- TextLabel1->setText(tr("SMESH_ID_ELEMENTS"));
- TextLabel2->setText(tr("NODE1_TO_MERGE"));
- TextLabel3->setText(tr("NODE2_TO_MERGE"));
- TextLabel4->setText(tr("SMESH_ID_ELEMENTS"));
- TextLabel5->setText(tr("NODE1_TO_MERGE"));
- TextLabel6->setText(tr("NODE2_TO_MERGE"));
+ TextLabel5->setEnabled(false);
+ SelectButton5->setEnabled(false);
+ LineEdit5->setEnabled(false);
- LineEdit1->setValidator(new SMESHGUI_IdValidator(this));
- LineEdit4->setValidator(new SMESHGUI_IdValidator(this));
+ if (!CheckBoxPolygons->isVisible())
+ CheckBoxPolygons->show();
+ if (!CheckBoxPolyedrs->isVisible())
+ CheckBoxPolyedrs->show();
- SMESH::SetPointRepresentation(false);
+ myOk5 = true;
- if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
- aViewWindow->SetSelectionMode(CellSelection);
- break;
- }
+ break;
+ }
+ case 3:
+ {
+ GroupArguments->setTitle(tr("SEW_SIDE_ELEMENTS"));
+ SubGroup1->setTitle(tr("SIDE_1"));
+ SubGroup2->setTitle(tr("SIDE_2"));
+
+ TextLabel1->setText(tr("SMESH_ID_ELEMENTS"));
+ TextLabel2->setText(tr("NODE1_TO_MERGE"));
+ TextLabel3->setText(tr("NODE2_TO_MERGE"));
+ TextLabel4->setText(tr("SMESH_ID_ELEMENTS"));
+ TextLabel5->setText(tr("NODE1_TO_MERGE"));
+ TextLabel6->setText(tr("NODE2_TO_MERGE"));
+
+ LineEdit1->setValidator(new SMESHGUI_IdValidator(this));
+ LineEdit4->setValidator(new SMESHGUI_IdValidator(this));
+
+ isNodeSelection = false;
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+ aViewWindow->SetSelectionMode(CellSelection);
+ break;
+ }
}
if (constructorId != 3) {
LineEdit1->setValidator(new SMESHGUI_IdValidator(this, 1));
LineEdit4->setValidator(new SMESHGUI_IdValidator(this, 1));
+ }
+ if ( isNodeSelection )
+ {
SMESH::SetPointRepresentation(true);
-
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
aViewWindow->SetSelectionMode(NodeSelection);
}
+ UpdateButtons();
+
connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
mySelectionMgr->setSelectedObjects( io );
QApplication::instance()->processEvents();
updateGeometry();
+
+ resize(100,100);
+}
+
+//=======================================================================
+//function : storeDisplayMode
+//purpose : save representation of a mesh and switch it to wireframe mode
+//=======================================================================
+
+void SMESHGUI_SewingDlg::setDisplayMode()
+{
+ myStoredEntityMode = 0;
+ myStoredRepresentation = -1;
+ if ( myActor )
+ {
+ myStoredEntityMode = myActor->GetEntityMode();
+ myStoredRepresentation = myActor->GetRepresentation();
+
+ myActor->SetEntityMode( myStoredEntityMode & ~SMESH_Actor::eVolumes );
+ myActor->SetRepresentation( SMESH_Actor::eEdge );
+ }
+}
+
+//=======================================================================
+//function : restoreDisplayMode
+//purpose : restore representation of a mesh
+//=======================================================================
+
+void SMESHGUI_SewingDlg::restoreDisplayMode()
+{
+ if ( myActor && myStoredEntityMode )
+ {
+ if ( myActor->GetEntityMode() == ( myStoredEntityMode & ~SMESH_Actor::eVolumes ))
+ myActor->SetEntityMode( myStoredEntityMode );
+
+ if ( myActor->GetRepresentation() == SMESH_Actor::eEdge )
+ myActor->SetRepresentation( myStoredRepresentation );
+
+ myStoredEntityMode = 0;
+ myStoredRepresentation = -1;
+ }
+}
+
+//=======================================================================
+//function : onModeChange
+//purpose : SLOT called when mode (auto or manual) of Sew free borders change
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onModeChange( int mode )
+{
+ if ( mode == MODE_MANUAL )
+ {
+ myEditCurrentArgument = LineEdit1;
+ if ( !SubGroup1->isVisible() )
+ SubGroup1->show(), SubGroup2->show();
+ SewFreeBordersWidget->hide();
+ }
+ else
+ {
+ myEditCurrentArgument = LineEditMesh;
+ SubGroup1->hide(), SubGroup2->hide();
+ if ( !SewFreeBordersWidget->isVisible() )
+ SewFreeBordersWidget->show();
+ }
+ onAutoSew( AutoSewCheck->isChecked() );
+
+ QApplication::instance()->processEvents();
+ updateGeometry();
+
resize(100,100);
}
+//=======================================================================
+//function : onAutoSew
+//purpose : SLOT called when Auto Sewing check box is checked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onAutoSew( int isAuto )
+{
+ GroupCoincidentWidget->setVisible( !isAuto );
+
+ QApplication::instance()->processEvents();
+
+ SewFreeBordersWidget->hide();
+ if ( ModeButGrp->checkedId() == MODE_AUTO )
+ SewFreeBordersWidget->show();
+
+ UpdateButtons();
+
+ updateGeometry();
+ resize(minimumSizeHint());
+}
+
+//=======================================================================
+//function : haveBorders
+//purpose : Returns true if myBorders have been initialized
+//=======================================================================
+
+bool SMESHGUI_SewingDlg::haveBorders()
+{
+ return ( & myBorders.in() &&
+ myBorders->borders.length() &&
+ myBorders->coincidentGroups.length() );
+}
+
+//=======================================================================
+//function : getGroupText
+//purpose : Returns a text of a given group of coincident free borders
+//=======================================================================
+
+QString SMESHGUI_SewingDlg::getPartText(const SMESH::FreeBorderPart& aPART)
+{
+ QString text;
+ if ( 0 <= aPART.border && aPART.border < myBorders->borders.length() )
+ {
+ const SMESH::FreeBorder& aBRD = myBorders->borders[ aPART.border ];
+ if ( 0 <= aPART.node1 && aPART.node1 < aBRD.nodeIDs.length() &&
+ 0 <= aPART.nodeLast && aPART.nodeLast < aBRD.nodeIDs.length() )
+ {
+ text += QString("( %1 %2 ) ")
+ .arg( aBRD.nodeIDs[ aPART.node1 ] )
+ .arg( aBRD.nodeIDs[ aPART.nodeLast ] );
+ }
+ }
+ return text;
+}
+
+//=======================================================================
+//function : getGroupText
+//purpose : Returns a text of a given group of coincident free borders
+//=======================================================================
+
+QString SMESHGUI_SewingDlg::getGroupText(int groupIndex)
+{
+ QString text;
+
+ if ( haveBorders() &&
+ groupIndex >= 0 &&
+ groupIndex < myBorders->coincidentGroups.length() )
+ {
+ const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ groupIndex ];
+
+ for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
+ {
+ QString partText = getPartText( aGRP[ iP ]);
+ if ( partText.isEmpty() )
+ return "";
+ text += partText;
+ }
+ }
+ return text;
+}
+
+//=======================================================================
+//function : onDetectClicked
+//purpose : SLOT called when [Detect] is clicked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onDetectClicked()
+{
+ ListCoincident->clear();
+
+ if ( myMesh->_is_nil() )
+ return;
+
+ SUIT_OverrideCursor wc;
+
+ SMESH::SMESH_MeshEditor_var editor = myMesh->GetMeshEditor();
+ myBorders = editor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() );
+ if ( !haveBorders() )
+ return;
+
+ for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+ {
+ delete myBorderDisplayers[ i ];
+ myBorderDisplayers[ i ] = 0;
+ }
+ myBorderDisplayers.resize( myBorders->coincidentGroups.length(), 0 );
+
+ for ( CORBA::ULong i = 0; i < myBorders->coincidentGroups.length(); ++i )
+ {
+ QString groupText = getGroupText( i );
+ if ( groupText.isEmpty() )
+ continue;
+
+ QColor groupColor;
+ groupColor.setHsvF( float(i) / myBorders->coincidentGroups.length(), 1., 1. );
+ QPixmap icon( QSize( 20, 20 ));
+ icon.fill( groupColor );
+
+ QListWidgetItem * item = new QListWidgetItem( icon, groupText, ListCoincident );
+ item->setData( GROUP_COLOR, groupColor );
+ item->setData( GROUP_INDEX, i );
+ }
+
+ onSelectGroup();
+
+ UpdateButtons();
+}
+
+//=======================================================================
+//function : onRemoveGroupClicked
+//purpose :
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onRemoveGroupClicked()
+{
+ QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
+ for ( int i = 0; i < selItems.count(); ++i )
+ {
+ QListWidgetItem* item = selItems[ i ];
+ item->setSelected( false );
+ int groupIndex = item->data( GROUP_INDEX ).toInt();
+ delete item;
+ myBorderDisplayers[ groupIndex ]->Hide();
+ SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+ aGRP.length( 0 );
+ }
+ UpdateButtons();
+}
+
+//=======================================================================
+//function : showGroup
+//purpose : display a group of coincident free borders in the Viewer
+//=======================================================================
+
+void SMESHGUI_SewingDlg::showGroup( QListWidgetItem* item )
+{
+ if ( !item ||
+ item->listWidget() != ListCoincident ||
+ !haveBorders() )
+ return;
+
+ int groupIndex = item->data( GROUP_INDEX ).toInt();
+ QColor groupColor = item->data( GROUP_COLOR ).value<QColor>();
+ if ( groupIndex >= 0 &&
+ groupIndex < myBorders->coincidentGroups.length() )
+ {
+ if ( !myBorderDisplayers[ groupIndex ])
+ myBorderDisplayers[ groupIndex ] = new BorderGroupDisplayer( myBorders, groupIndex, groupColor, myMesh );
+ bool wholeBorders = setCurrentGroup();
+ myBorderDisplayers[ groupIndex ]->ShowGroup( wholeBorders );
+ }
+}
+
+//=======================================================================
+//function : setCurrentGroup
+//purpose : set index of a current free border group to myCurGroupIndex
+//=======================================================================
+
+bool SMESHGUI_SewingDlg::setCurrentGroup()
+{
+ if ( !haveBorders() )
+ return false;
+
+ QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
+ if ( selItems.count() != 1 )
+ return false;
+
+ myCurGroupIndex = selItems[0]->data( GROUP_INDEX ).toInt();
+
+ return ( myCurGroupIndex >= 0 && myCurGroupIndex < myBorders->coincidentGroups.length() );
+}
+
+//=======================================================================
+//function : setCurrentPart
+//purpose : set index of a current free border of a current group to myCurPartIndex
+//=======================================================================
+
+bool SMESHGUI_SewingDlg::setCurrentPart()
+{
+ if ( !setCurrentGroup() )
+ return false;
+
+ if ( ListEdit->selectedItems().count() != 1 )
+ return false;
+
+ myCurPartIndex = ListEdit->currentRow();
+ const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+
+ return ( myCurPartIndex >= 0 && myCurPartIndex < aGRP.length() );
+}
+
+//=======================================================================
+//function : onSelectGroup
+//purpose : SLOT called when selection of coincident free borders change
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSelectGroup()
+{
+ if ( myBusy )
+ return;
+ ListEdit->clear();
+ BorderEndLine[0]->clear();
+ BorderEndLine[1]->clear();
+ for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+ if ( myBorderDisplayers[ i ])
+ myBorderDisplayers[ i ]->Hide();
+
+ QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
+
+ RemoveGroupButton->setEnabled( selItems.count() > 0 );
+
+ onSelectBorderPartFromGroup(); // enable buttons
+
+ if ( !haveBorders() )
+ return;
+
+ SelectAllCheck->blockSignals( true );
+ if ( ListCoincident->count() != selItems.count() )
+ SelectAllCheck->setChecked( false );
+ SelectAllCheck->blockSignals( false );
+
+ if ( selItems.empty() ) // nothing selected - show all
+ for ( int i = 0; i < ListCoincident->count(); ++i )
+ showGroup( ListCoincident->item( i ));
+ else
+ for ( int i = 0; i < selItems.count(); ++i )
+ showGroup( selItems[ i ]);
+
+ if ( setCurrentGroup() ) // edit a selected group
+ {
+ const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+ for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
+ new QListWidgetItem( getPartText( aGRP[ iP ]), ListEdit );
+ }
+ SMESH::RepaintCurrentView();
+}
+
+//=======================================================================
+//function : onSelectAll
+//purpose : SLOT called when Select All is checked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSelectAll(int isOn)
+{
+ if ( isOn )
+ ListCoincident->selectAll();
+ else
+ ListCoincident->clearSelection();
+}
+
+//=======================================================================
+//function : onSelectBorderPartFromGroup
+//purpose : SLOT called when selection of borders in an edited group changes
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSelectBorderPartFromGroup()
+{
+ if ( myBusy ) return;
+ BorderEndLine[0]->setText("");
+ BorderEndLine[1]->setText("");
+ MoveBorderEndsButGrp->button( MOVE_LEFT_1 )->setEnabled( false );
+ MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->setEnabled( false );
+ MoveBorderEndsButGrp->button( MOVE_LEFT_2 )->setEnabled( false );
+ MoveBorderEndsButGrp->button( MOVE_RIGHT_2 )->setEnabled( false );
+ SwapBut->setEnabled( false );
+ SetFirstButton->setEnabled( false );
+ RemoveElemButton->setEnabled ( ListEdit->count() > 2 );
+
+ if ( !setCurrentGroup() )
+ return;
+
+ if ( !myBorderDisplayers[ myCurGroupIndex ]) return;
+ myBorderDisplayers[ myCurGroupIndex ]->Hide();
+
+ QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
+ bool editPart = ( setCurrentPart() );
+ for ( int i = 0; i < selItems.count(); ++i )
+ myBorderDisplayers[ myCurGroupIndex ]->ShowPart( ListEdit->row( selItems[i] ), editPart );
+
+ if ( selItems.isEmpty() )
+ myBorderDisplayers[ myCurGroupIndex ]->ShowGroup( /*wholeBorders=*/ true );
+
+ if ( editPart )
+ {
+ SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+ SMESH::FreeBorderPart& aPRT = aGRP[ myCurPartIndex ];
+ SMESH::FreeBorder& aBRD = myBorders->borders[ aPRT.border ];
+
+ BorderEndLine[0]->setText( QString::number( aBRD.nodeIDs[ aPRT.node1 ]));
+ BorderEndLine[1]->setText( QString::number( aBRD.nodeIDs[ aPRT.nodeLast ]));
+ SwapBut->setEnabled( true );
+ SetFirstButton->setEnabled( myCurPartIndex > 0 );
+
+ int size = (int) aBRD.nodeIDs.length();
+ bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
+ if ( !isClosed )
+ {
+ bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+ int dn = ( isFwd ? +1 : -1 ) * StepSpin->value();
+ MoveBorderEndsButGrp->button( MOVE_LEFT_1 )->
+ setEnabled( 0 <= aPRT.node1-dn && aPRT.node1-dn < size );
+ MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->
+ setEnabled( 0 <= aPRT.node1+dn && aPRT.node1+dn < size );
+ MoveBorderEndsButGrp->button( MOVE_LEFT_2 )->
+ setEnabled( 0 <= aPRT.nodeLast-dn && aPRT.nodeLast-dn < size );
+ MoveBorderEndsButGrp->button( MOVE_RIGHT_2 )->
+ setEnabled( 0 <= aPRT.nodeLast+dn && aPRT.nodeLast+dn < size );
+ }
+ else
+ {
+ MoveBorderEndsButGrp->button( MOVE_LEFT_1 )->setEnabled( true );
+ MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->setEnabled( true );
+ MoveBorderEndsButGrp->button( MOVE_LEFT_2 )->setEnabled( true );
+ MoveBorderEndsButGrp->button( MOVE_RIGHT_2 )->setEnabled( true );
+ }
+ }
+ SMESH::RepaintCurrentView();
+}
+
+//=======================================================================
+//function : onGroupChange
+//purpose : Update after modification of a current group by the user
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onGroupChange( bool partChange )
+{
+ ListCoincident->currentItem()->setText( getGroupText( myCurGroupIndex ));
+
+ const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+ for ( int i = 0; i < ListEdit->count(); ++i )
+ ListEdit->item( i )->setText( getPartText( aGRP[ i ]));
+
+ myBorderDisplayers[ myCurGroupIndex ]->Update();
+
+ if ( partChange )
+ onSelectBorderPartFromGroup();
+}
+
+//=======================================================================
+//function : onSetFirstClicked
+//purpose : STOL called when |<< is clicked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSetFirstClicked()
+{
+ if ( !setCurrentPart() || myCurPartIndex == 0 || ListEdit->count() == 0 )
+ return;
+
+ SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+
+ SMESH::FreeBorderPart new1st = aGRP[ myCurPartIndex ];
+ for ( ; myCurPartIndex > 0; --myCurPartIndex )
+ aGRP[ myCurPartIndex ] = aGRP[ myCurPartIndex - 1 ];
+
+ aGRP[ 0 ] = new1st;
+
+ onGroupChange();
+
+ myBusy = true;
+ ListEdit->clearSelection();
+ myBusy = false;
+ ListEdit->setCurrentItem( ListEdit->item(0) );//ListEdit->item(0)->setSelected(true);
+}
+
+//=======================================================================
+//function : onRemoveElemClicked
+//purpose :
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onRemoveElemClicked()
+{
+ if ( !setCurrentGroup() )
+ return;
+
+ SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+
+ QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
+ for ( int i = 0; i < selItems.count(); ++i )
+ {
+ int part = ListEdit->row( selItems[i] );
+ for ( ; part + 1 < aGRP.length(); ++part )
+ aGRP[ part ] = aGRP[ part + 1 ];
+ aGRP.length( aGRP.length() - 1 );
+ delete selItems[i];
+ }
+
+ if ( aGRP.length() == 0 )
+ onRemoveGroupClicked();
+ else
+ onGroupChange( /*partChange=*/true );
+}
+
+//=======================================================================
+//function : onMoveBorderEnd
+//purpose :
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onMoveBorderEnd(int button)
+{
+ if ( !setCurrentPart() )
+ return;
+
+ SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+ SMESH::FreeBorderPart& aPRT = aGRP[ myCurPartIndex ];
+ SMESH::FreeBorder& aBRD = myBorders->borders[ aPRT.border ];
+ int size = (int) aBRD.nodeIDs.length();
+
+ bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
+ if ( isClosed ) --size;
+
+ bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+ int dn = ( isFwd ? +1 : -1 ) * StepSpin->value();
+ if ( button == MOVE_LEFT_1 || button == MOVE_LEFT_2 )
+ dn *= -1;
+
+ switch ( button ) {
+ case MOVE_LEFT_1:
+ case MOVE_RIGHT_1:
+ if (( isClosed ) ||
+ ( 0 <= aPRT.node1+dn && aPRT.node1+dn < size ))
+ {
+ aPRT.node1 = ( aPRT.node1 + size + dn ) % size;
+ aPRT.node2 = ( aPRT.node2 + size + dn ) % size;
+ break;
+ }
+ case MOVE_LEFT_2:
+ case MOVE_RIGHT_2:
+ if (( isClosed ) ||
+ ( 0 <= aPRT.nodeLast+dn && aPRT.nodeLast+dn < size ))
+ {
+ aPRT.nodeLast = ( aPRT.nodeLast + size + dn ) % size;
+ break;
+ }
+ default:
+ return; // impossible to move
+ }
+
+ onGroupChange( /*partChange=*/true );
+}
+
+//=======================================================================
+//function : onSwapClicked
+//purpose : SLOT called when <-> is clicked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSwapClicked()
+{
+ if ( !setCurrentPart() )
+ return;
+
+ SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+ SMESH::FreeBorderPart& aPRT = aGRP[ myCurPartIndex ];
+ SMESH::FreeBorder& aBRD = myBorders->borders[ aPRT.border ];
+ int size = (int) aBRD.nodeIDs.length();
+
+ bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
+ if ( isClosed ) --size;
+
+ bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+
+ std::swap( aPRT.nodeLast, aPRT.node1 );
+
+ aPRT.node2 = ( aPRT.node1 + ( isFwd ? -1 : +1 ) + size ) % size;
+
+ onGroupChange( /*partChange=*/true );
+}
+
//=================================================================================
// function : ClickOnApply()
// purpose :
bool aResult = false;
- if (IsValid()) {
- bool toMerge = CheckBoxMerge->isChecked();
+ if (IsValid())
+ {
+ bool toMerge = CheckBoxMerge->isChecked();
bool toCreatePolygons = CheckBoxPolygons->isChecked();
bool toCreatePolyedrs = CheckBoxPolyedrs->isChecked();
-
try {
SUIT_OverrideCursor aWaitCursor;
SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
SMESH::SMESH_MeshEditor::Sew_Error anError;
if (aConstructorId == 0)
- anError = aMeshEditor->SewFreeBorders(LineEdit1->text().toLong(),
- LineEdit2->text().toLong(),
- LineEdit3->text().toLong(),
- LineEdit4->text().toLong(),
- LineEdit5->text().toLong(),
- LineEdit6->text().toLong(),
- toCreatePolygons,
- toCreatePolyedrs);
+ {
+ if ( ModeButGrp->checkedId() == MODE_MANUAL )
+ {
+ anError = aMeshEditor->SewFreeBorders(LineEdit1->text().toLong(),
+ LineEdit2->text().toLong(),
+ LineEdit3->text().toLong(),
+ LineEdit4->text().toLong(),
+ LineEdit5->text().toLong(),
+ LineEdit6->text().toLong(),
+ toCreatePolygons,
+ toCreatePolyedrs);
+ }
+ else
+ {
+ int nbCoincGroups = ListCoincident->count();
+ if ( AutoSewCheck->isChecked() )
+ {
+ myBorders = aMeshEditor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() );
+ nbCoincGroups = myBorders->coincidentGroups.length();
+ }
+ CORBA::Short nbSewed = aMeshEditor->SewCoincidentFreeBorders( myBorders.inout(),
+ toCreatePolygons,
+ toCreatePolyedrs);
+ QString msg;
+ if ( nbCoincGroups == 0 )
+ msg = tr("NO_BORDERS_TO_SEW");
+ else if ( nbSewed < nbCoincGroups )
+ msg = tr("NOT_ALL_BORDERS_SEWED").arg( nbSewed ).arg( nbCoincGroups );
+ else
+ msg = tr("ALL_BORDERS_SEWED").arg( nbSewed );
+ SUIT_MessageBox::information( this, tr("SMESH_INFORMATION"), msg );
+
+ anError = SMESH::SMESH_MeshEditor::SEW_OK;
+ }
+ }
else if (aConstructorId == 1)
+ {
anError = aMeshEditor->SewConformFreeBorders(LineEdit1->text().toLong(),
LineEdit2->text().toLong(),
LineEdit3->text().toLong(),
LineEdit4->text().toLong(),
LineEdit5->text().toLong());
+ }
else if (aConstructorId == 2)
+ {
anError = aMeshEditor->SewBorderToSide(LineEdit1->text().toLong(),
LineEdit2->text().toLong(),
LineEdit3->text().toLong(),
LineEdit6->text().toLong(),
toCreatePolygons,
toCreatePolyedrs);
+ }
else if (aConstructorId == 3) {
QStringList aListElementsId1 = LineEdit1->text().split(" ", QString::SkipEmptyParts);
QStringList aListElementsId2 = LineEdit4->text().split(" ", QString::SkipEmptyParts);
}
if (aResult) {
- Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
-
- SALOME_ListIO aList;
- aList.Append(anIO);
- mySelectionMgr->setSelectedObjects(aList, false);
- SMESH::UpdateView();
+ if ( myActor )
+ {
+ Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
+ SALOME_ListIO aList;
+ aList.Append(anIO);
+ mySelectionMgr->setSelectedObjects(aList, false);
+ SMESH::UpdateView();
+ }
Init();
ConstructorsClicked(GetConstructorId());
{
DeactivateActiveDialog();
mySelector = 0;
+
+ for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+ {
+ delete myBorderDisplayers[ i ];
+ myBorderDisplayers[ i ] = 0;
+ }
+ myBorderDisplayers.clear();
}
//=================================================================================
//=================================================================================
void SMESHGUI_SewingDlg::reject()
{
+ restoreDisplayMode();
//mySelectionMgr->clearSelected();
SMESH::SetPointRepresentation(false);
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
else if (send == LineEdit6)
myOk6 = false;
- buttonOk->setEnabled(false);
- buttonApply->setEnabled(false);
-
// hilight entered elements/nodes
SMDS_Mesh* aMesh = 0;
}
}
- if (IsValid()) {
- buttonOk->setEnabled(true);
- buttonApply->setEnabled(true);
- }
+ UpdateButtons();
myBusy = false;
}
if (myBusy) return;
// clear
+ restoreDisplayMode();
if (isSelectionChanged)
myActor = 0;
myBusy = true;
myEditCurrentArgument->setText(aString);
+ ListCoincident->clear();
+ ListEdit->clear();
myBusy = false;
+ onSelectGroup(); // erase preview
+
if (!GroupButtons->isEnabled()) // inactive
return;
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
+ DetectButton->setEnabled(false);
// get selected mesh
SALOME_ListIO aList;
return;
Handle(SALOME_InteractiveObject) IO = aList.First();
- myMesh = SMESH::GetMeshByIO(IO); //@ SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(IO);
+ myMesh = SMESH::GetMeshByIO(IO);
myActor = SMESH::FindActorByEntry(aList.First()->getEntry());
+ if (myMesh->_is_nil())
+ return;
+
+ CheckBoxPolyedrs->setEnabled( myMesh->NbVolumes() > 0 );
+
+ if ( myEditCurrentArgument == LineEditMesh )
+ {
+ LineEditMesh->setText( IO->getName() );
+ ListCoincident->clear();
+ if ( AutoSewCheck->isChecked() )
+ {
+ buttonOk->setEnabled(true);
+ buttonApply->setEnabled(true);
+ }
+ DetectButton->setEnabled( myMesh->NbFaces() > 0 );
+ setDisplayMode();
+ return;
+ }
- if (myMesh->_is_nil() || !myActor)
+ if (!myActor)
return;
// get selected elements/nodes
int aNbUnits = 0;
- if (GetConstructorId() != 3 ||
- (myEditCurrentArgument != LineEdit1 && myEditCurrentArgument != LineEdit4)) {
+ if (( GetConstructorId() != 3 ) ||
+ ( myEditCurrentArgument != LineEdit1 && myEditCurrentArgument != LineEdit4))
+ {
aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
if (aNbUnits != 1)
return;
- } else {
+ }
+ else {
aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, IO, aString);
if (aNbUnits < 1)
return;
else if (myEditCurrentArgument == LineEdit6)
myOk6 = true;
- if (IsValid()) {
- buttonOk->setEnabled(true);
- buttonApply->setEnabled(true);
- }
+ UpdateButtons();
}
//=================================================================================
//=================================================================================
bool SMESHGUI_SewingDlg::IsValid()
{
+ if ( myMesh->_is_nil() )
+ return false;
+
+ if ( GetConstructorId() == 0 && ModeButGrp->checkedId() == MODE_AUTO )
+ {
+ if ( AutoSewCheck->isChecked() )
+ return true;
+
+ int nbGroups = 0;
+ if ( haveBorders() )
+ for ( int i = 0; i < ListCoincident->count(); ++i )
+ {
+ int groupIndex = ListCoincident->item(i)->data( GROUP_INDEX ).toInt();
+ nbGroups += ( !getGroupText( groupIndex ).isEmpty() );
+ }
+ return nbGroups > 0;
+ }
return (myOk1 && myOk2 && myOk3 && myOk4 && myOk5 && myOk6);
}
+//=======================================================================
+//function : UpdateButtons
+//purpose : activate [Apply] buttons
+//=======================================================================
+
+void SMESHGUI_SewingDlg::UpdateButtons()
+{
+ bool ok = IsValid();
+ buttonOk->setEnabled( ok );
+ buttonApply->setEnabled( ok );
+}
+
//=================================================================================
// function : keyPressEvent()
// purpose :
ClickOnHelp();
}
}
+
+SMESHGUI_SewingDlg::
+BorderGroupDisplayer::BorderGroupDisplayer( const SMESH::CoincidentFreeBorders& borders,
+ int groupIndex,
+ QColor color,
+ SMESH::SMESH_Mesh_ptr mesh):
+ myBorders ( borders.borders ),
+ myGroup ( borders.coincidentGroups[ groupIndex ]),
+ myColor ( color ),
+ myMesh ( mesh ),
+ myViewWindow( SMESH::GetCurrentVtkView() ),
+ myIdPreview ( myViewWindow )
+{
+ Update();
+}
+
+SMESHGUI_SewingDlg::BorderGroupDisplayer::~BorderGroupDisplayer()
+{
+ for ( size_t i = 0; i < myPartActors.size(); ++i )
+ {
+ if ( myPartActors[ i ]) {
+ myViewWindow->RemoveActor( myPartActors[i] );
+ myPartActors[i]->Delete();
+ }
+ }
+ myIdPreview.SetPointsLabeled(false);
+ //myViewWindow->Repaint();
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::Hide()
+{
+ for ( size_t i = 0; i < myPartActors.size(); ++i )
+ if ( myPartActors[ i ])
+ myPartActors[ i ]->SetVisibility(false);
+
+ myIdPreview.SetPointsLabeled(false);
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::ShowGroup( bool wholeBorders )
+{
+ std::vector<int> ids;
+ std::list<gp_XYZ> coords;
+ for ( size_t i = 0; i < myPartActors.size(); ++i )
+ if ( myPartActors[ i ])
+ {
+ myPartActors[ i ]->SetPointRepresentation( wholeBorders );
+ myPartActors[ i ]->SetVisibility( true );
+ if ( wholeBorders )
+ getPartEnds( i, ids, coords );
+ }
+ if ( wholeBorders )
+ myIdPreview.SetElemsData( ids, coords );
+ myIdPreview.SetPointsLabeled( wholeBorders, true );
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::ShowPart( int partIndex, bool toEdit )
+{
+ if ( partIndex < (int) myPartActors.size() )
+ {
+ myPartActors[partIndex]->SetVisibility(true);
+ myPartActors[partIndex]->SetPointRepresentation(toEdit);
+
+ if ( toEdit )
+ {
+ std::vector<int> ids;
+ std::list<gp_XYZ> coords;
+ getPartEnds( partIndex, ids, coords );
+
+ myIdPreview.SetElemsData( ids, coords );
+ myIdPreview.SetPointsLabeled( true, /*show=*/true );
+ }
+ }
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::getPartEnds( int partIndex,
+ std::vector<int> & ids,
+ std::list<gp_XYZ>& coords)
+{
+ const SMESH::FreeBorderPart& aPART = myGroup [ partIndex ];
+ const SMESH::FreeBorder& aBRD = myBorders[ aPART.border ];
+
+ ids.push_back( aBRD.nodeIDs[ aPART.node1 ]);
+ ids.push_back( aBRD.nodeIDs[ aPART.nodeLast ]);
+
+ SMDS_Mesh* mesh = myPartActors[ partIndex ]->GetObject()->GetMesh();
+
+ coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.node1+1 )));
+ coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.nodeLast+1 )));
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::Update()
+{
+ Hide();
+ myPartActors.resize( myGroup.length(), 0 );
+
+ for ( size_t i = 0; i < myPartActors.size(); ++i )
+ {
+ TVisualObjPtr obj;
+ if ( myPartActors[ i ])
+ obj = myPartActors[ i ]->GetObject();
+ else
+ obj = TVisualObjPtr( new SMESHGUI_PreVisualObj() );
+ SMDS_Mesh* mesh = obj->GetMesh();
+ mesh->Clear();
+
+ // add nodes
+ const SMESH::FreeBorderPart& aPRT = myGroup[ i ];
+ const SMESH::FreeBorder& aBRD = myBorders[ aPRT.border ];
+ for ( CORBA::ULong iN = 0; iN < aBRD.nodeIDs.length(); ++iN )
+ {
+ SMESH::double_array_var xyz = myMesh->GetNodeXYZ( aBRD.nodeIDs[ iN ]);
+ if ( xyz->length() == 3 )
+ mesh->AddNode( xyz[0], xyz[1], xyz[2] );
+ }
+
+ // add edges
+ bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+ int dn = isFwd ? +1 : -1;
+ int size = (int) aBRD.nodeIDs.length();
+ int n2, n1 = aPRT.node1;
+ for ( n2 = n1 + dn; ( n2 >= 0 && n2 < size ); n2 += dn )
+ {
+ mesh->AddEdgeWithID( n1+1, n2+1, mesh->NbEdges() + 1 );
+ n1 = n2;
+ if ( n2 == aPRT.nodeLast )
+ break;
+ }
+ if ( n2 % size != aPRT.nodeLast )
+ {
+ if ( n2 < 0 ) n1 = size;
+ else n1 = 0;
+ for ( n2 = n1 + dn; ( n2 >= 0 && n2 < size ); n2 += dn )
+ {
+ mesh->AddEdgeWithID( n1+1, n2+1, mesh->NbEdges() + 1 );
+ n1 = n2;
+ if ( n2 == aPRT.nodeLast )
+ break;
+ }
+ }
+
+ if ( !myPartActors[ i ]) // TVisualObj must be filled before actor creation
+ {
+ myPartActors[ i ] = SMESH_Actor::New( obj, "", "", 1 );
+ myPartActors[ i ]->SetEdgeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
+ myPartActors[ i ]->SetLineWidth( 3 * SMESH::GetFloat("SMESH:element_width",1));
+ myPartActors[ i ]->SetPickable( false );
+ myPartActors[ i ]->SetNodeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
+ myPartActors[ i ]->SetMarkerStd( VTK::MT_POINT, 13 );
+ myViewWindow->AddActor( myPartActors[ i ]);
+ myViewWindow->Repaint();
+ }
+ }
+}
+
// IDL includes
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+
+#include <vector>
class QButtonGroup;
class QGroupBox;
class SMESH_Actor;
class SVTK_Selector;
class LightApp_SelectionMgr;
+class SMESHGUI_SpinBox;
+class SalomeApp_IntSpinBox;
+class QListWidget;
+class QListWidgetItem;
//=================================================================================
// class : SMESHGUI_SewingDlg
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;
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();
</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>
<source>SELECT</source>
<translation>Select: </translation>
</message>
- <message>
- <source></source>
- <translation></translation>
- </message>
</context>
<context>
<name>SMESHGUI_ExtrusionAlongPathDlg</name>
<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>
SMESH_File.cxx
SMESH_MeshAlgos.cxx
SMESH_MAT2d.cxx
+ SMESH_FreeBorders.cxx
)
# --- rules ---
--- /dev/null
+// 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
+}
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;
// 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]);
// 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;
}
// (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
}
// Node or 0D element -------------------------------------------------------------------------
{
gp_Vec n2p ( xyz[0], point );
- return n2p.Magnitude() <= tol;
+ return n2p.SquareMagnitude() <= tol * tol;
}
return true;
}
*/
//=======================================================================
-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 );
}
//=======================================================================
//=======================================================================
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 );
}
* \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
"Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject",
"FindCoincidentNodes","MergeNodes","FindEqualElements",
"MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
+ "FindCoincidentFreeBorders", "SewCoincidentFreeBorders",
"SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
"GetLastCreatedElems",
"MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh","TranslateObjectMakeMesh",
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;
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 :
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 );
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;
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;
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,
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,
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.
#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)
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();
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