#include "SMESH_MeshEditor_i.hxx"
+#include "DriverMED_R_SMESHDS_Mesh.h"
+#include "DriverMED_W_SMESHDS_Mesh.h"
+#include "SMDS_EdgePosition.hxx"
+#include "SMDS_ElemIterator.hxx"
+#include "SMDS_FacePosition.hxx"
+#include "SMDS_IteratorOnIterators.hxx"
#include "SMDS_LinearEdge.hxx"
#include "SMDS_Mesh0DElement.hxx"
#include "SMDS_MeshFace.hxx"
#include "SMDS_MeshVolume.hxx"
#include "SMDS_PolyhedralVolumeOfNodes.hxx"
#include "SMDS_SetIterator.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMESHDS_Command.hxx"
+#include "SMESHDS_CommandType.hxx"
#include "SMESHDS_Group.hxx"
+#include "SMESHDS_GroupOnGeom.hxx"
#include "SMESH_ControlsDef.hxx"
#include "SMESH_Filter_i.hxx"
+#include "SMESH_Filter_i.hxx"
#include "SMESH_Gen_i.hxx"
+#include "SMESH_Gen_i.hxx"
+#include "SMESH_Group.hxx"
+#include "SMESH_Group_i.hxx"
#include "SMESH_Group_i.hxx"
+#include "SMESH_MEDMesh_i.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMESH_MeshPartDS.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_PreMeshInfo.hxx"
+#include "SMESH_PythonDump.hxx"
#include "SMESH_PythonDump.hxx"
#include "SMESH_subMeshEventListener.hxx"
#include "SMESH_subMesh_i.hxx"
+#include "SMESH_subMesh_i.hxx"
#include "utilities.h"
#include "Utils_ExceptHandlers.hxx"
const SMDS_MeshElement * elem =
(aType == SMDSAbs_Node ? aMesh->FindNode(ind) : aMesh->FindElement(ind));
if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
- aMap.insert( elem );
+ aMap.insert( aMap.end(), elem );
}
}
//================================================================================
SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
{
+ deleteAuxIDSources();
}
//================================================================================
if ( deleteSearchers )
TSearchersDeleter::Delete();
}
+ myEditor.GetError().reset();
+ myEditor.CrearLastCreated();
}
//================================================================================
SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
{
- if ( myPreviewMode ) { // --- MeshPreviewStruct filling ---
+ const bool hasBadElems = ( myEditor.GetError() && myEditor.GetError()->HasBadElems() );
+
+ if ( myPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
list<int> aNodesConnectivity;
typedef map<int, int> TNodesMap;
TNodesMap nodesMap;
- SMESHDS_Mesh* aMeshDS = myEditor.GetMeshDS();
+ SMESHDS_Mesh* aMeshDS;
+ std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
+ if ( hasBadElems ) {
+ aMeshPartDS.reset( new SMESH_MeshPartDS( myEditor.GetError()->myBadElements ));
+ aMeshDS = aMeshPartDS.get();
+ }
+ else {
+ aMeshDS = myEditor.GetMeshDS();
+ }
int nbEdges = aMeshDS->NbEdges();
int nbFaces = aMeshDS->NbFaces();
int nbVolum = aMeshDS->NbVolumes();
myPreviewData = new SMESH::MeshPreviewStruct();
myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
- TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( myEditor.GetMesh() );
+
SMDSAbs_ElementType previewType = SMDSAbs_All;
- if (aPreviewMesh) {
- previewType = aPreviewMesh->myPreviewType;
- switch ( previewType ) {
- case SMDSAbs_Edge : nbFaces = nbVolum = 0; break;
- case SMDSAbs_Face : nbEdges = nbVolum = 0; break;
- case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
- default:;
+ if ( !hasBadElems )
+ if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( myEditor.GetMesh() )) {
+ previewType = aPreviewMesh->myPreviewType;
+ switch ( previewType ) {
+ case SMDSAbs_Edge : nbFaces = nbVolum = 0; break;
+ case SMDSAbs_Face : nbEdges = nbVolum = 0; break;
+ case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
+ default:;
+ }
}
- }
myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
int i = 0, j = 0;
return myLastCreatedElems._retn();
}
+//=======================================================================
+/*
+ * Returns description of an error/warning occured during the last operation
+ */
+//=======================================================================
+
+SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
+{
+ SMESH::ComputeError* errOut = new SMESH::ComputeError;
+ SMESH_ComputeErrorPtr& errIn = myEditor.GetError();
+ if ( errIn && !errIn->IsOK() )
+ {
+ errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
+ errOut->comment = errIn->myComment.c_str();
+ errOut->subShapeID = -1;
+ errOut->hasBadMesh = !errIn->myBadElements.empty();
+ }
+ return errOut;
+}
+
//=======================================================================
//function : MakeIDSource
//purpose : Wrap a sequence of ids in a SMESH_IDSource
//=======================================================================
-struct _IDSource : public POA_SMESH::SMESH_IDSource
+struct SMESH_MeshEditor_i::_IDSource : public POA_SMESH::SMESH_IDSource
{
SMESH::long_array _ids;
SMESH::ElementType _type;
SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
SMESH::ElementType type)
{
- _IDSource* anIDSource = new _IDSource;
- anIDSource->_ids = ids;
- anIDSource->_type = type;
- anIDSource->_mesh = myMesh_i->_this();
- SMESH::SMESH_IDSource_var anIDSourceVar = anIDSource->_this();
+ if ( myAuxIDSources.size() > 10 )
+ deleteAuxIDSources();
+
+ _IDSource* idSrc = new _IDSource;
+ idSrc->_mesh = myMesh_i->_this();
+ idSrc->_ids = ids;
+ idSrc->_type = type;
+ myAuxIDSources.push_back( idSrc );
+
+ SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
return anIDSourceVar._retn();
}
+void SMESH_MeshEditor_i::deleteAuxIDSources()
+{
+ std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
+ for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
+ delete *idSrcIt;
+ myAuxIDSources.clear();
+}
+
//=============================================================================
/*!
*
* AddPolyhedralVolumeByFaces
*/
//=============================================================================
+
CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
{
initData();
return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
}
+//=============================================================================
+//
+// \brief Create 0D elements on all nodes of the given object except those
+// nodes on which a 0D element already exists.
+// \param theObject object on whose nodes 0D elements will be created.
+// \param theGroupName optional name of a group to add 0D elements created
+// and/or found on nodes of \a theObject.
+// \return an object (a new group or a temporary SMESH_IDSource) holding
+// ids of new and/or found 0D elements.
+//
+//=============================================================================
+
+SMESH::SMESH_IDSource_ptr
+SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
+ const char* theGroupName)
+ throw (SALOME::SALOME_Exception)
+{
+ initData();
+
+ SMESH::SMESH_IDSource_var result;
+ TPythonDump pyDump;
+
+ TIDSortedElemSet elements, elems0D;
+ if ( idSourceToSet( theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
+ myEditor.Create0DElementsOnAllNodes( elements, elems0D );
+
+ SMESH::long_array_var newElems = new SMESH::long_array;
+ newElems->length( elems0D.size() );
+ TIDSortedElemSet::iterator eIt = elems0D.begin();
+ for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
+ newElems[ i ] = (*eIt)->GetID();
+
+ SMESH::SMESH_GroupBase_var groupToFill;
+ if ( theGroupName && strlen( theGroupName ))
+ {
+ // Get existing group named theGroupName
+ SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
+ for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
+ SMESH::SMESH_GroupBase_var group = groups[i];
+ if ( !group->_is_nil() ) {
+ CORBA::String_var name = group->GetName();
+ if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
+ groupToFill = group;
+ break;
+ }
+ }
+ }
+ if ( groupToFill->_is_nil() )
+ groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
+ else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
+ groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
+ }
+
+ if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
+ {
+ group_i->Add( newElems );
+ result = SMESH::SMESH_IDSource::_narrow( groupToFill );
+ pyDump << groupToFill;
+ }
+ else
+ {
+ result = MakeIDSource( newElems, SMESH::ELEM0D );
+ pyDump << "elem0DIDs";
+ }
+
+ pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
+ << theObject << ", '" << theGroupName << "' )";
+
+ return result._retn();
+}
+
//=============================================================================
/*!
* \brief Bind a node to a vertex
dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
SMESH::Controls::NumericalFunctorPtr aCrit;
if ( !aNumericalFunctor )
- aCrit.reset( new SMESH::Controls::AspectRatio() );
+ aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
else
aCrit = aNumericalFunctor->GetNumericalFunctor();
SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
{
- typedef list<int> TListOfIDs;
- set<const SMDS_MeshElement*> elems;
- SMESH::long_array_var aElementsId = theObject->GetIDs();
- SMESHDS_Mesh* aMesh = GetMeshDS();
-
- for(int i = 0; i < aElementsId->length(); i++) {
- CORBA::Long anID = aElementsId[i];
- const SMDS_MeshElement * elem = aMesh->FindElement(anID);
- if (elem) {
- elems.insert(elem);
- }
- }
+ TIDSortedElemSet elems;
+ idSourceToSet( theObject, GetMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
myEditor.FindEqualElements( elems, aListOfListOfElementsID );
GroupsOfElementsID = new SMESH::array_of_long_array;
GroupsOfElementsID->length( aListOfListOfElementsID.size() );
- ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin();
- for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) {
+ ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
+ aListOfListOfElementsID.begin();
+ for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
+ {
SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
- TListOfIDs& listOfIDs = *arraysIt;
+ list<int>& listOfIDs = *arraysIt;
aGroup.length( listOfIDs.size() );
- TListOfIDs::iterator idIt = listOfIDs.begin();
- for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
+ list<int>::iterator idIt = listOfIDs.begin();
+ for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
aGroup[ k ] = *idIt;
- }
}
TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
if (CORBA::is_nil(aGroup))
continue;
- groupNames.insert(aGroup->GetName());
+ CORBA::String_var name = aGroup->GetName();
+ groupNames.insert( name.in() );
}
// Find new name
string name = thePrefix;
int index = 0;
- while (!groupNames.insert(name).second) {
- if (index == 0) {
- name += "_1";
- }
- else {
- TCollection_AsciiString nbStr(index+1);
- name.resize( name.rfind('_')+1 );
- name += nbStr.ToCString();
- }
- ++index;
- }
+ while (!groupNames.insert(name).second)
+ name = SMESH_Comment( thePrefix ) << "_" << index;
return name;
}
return aResult;
}
+//================================================================================
+/*!
+ \brief Identify the elements that will be affected by node duplication (actual duplication is not performed.
+ This method is the first step of DoubleNodeElemGroupsInRegion.
+ \param theElems - list of groups of elements (edges or faces) to be replicated
+ \param theNodesNot - list of groups of nodes not to replicated
+ \param theShape - shape to detect affected elements (element which geometric center
+ located on or inside shape).
+ The replicated nodes should be associated to affected elements.
+ \return groups of affected elements
+ \sa DoubleNodeElemGroupsInRegion()
+ */
+//================================================================================
+SMESH::ListOfGroups*
+SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
+ const SMESH::ListOfGroups& theNodesNot,
+ GEOM::GEOM_Object_ptr theShape )
+{
+ MESSAGE("AffectedElemGroupsInRegion");
+ SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
+ bool isEdgeGroup = false;
+ bool isFaceGroup = false;
+ bool isVolumeGroup = false;
+ SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
+ SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
+ SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
+
+ initData();
+
+ ::SMESH_MeshEditor aMeshEditor(myMesh);
+
+ SMESHDS_Mesh* aMeshDS = GetMeshDS();
+ TIDSortedElemSet anElems, aNodes;
+ listOfGroupToSet(theElems, aMeshDS, anElems, false);
+ listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
+
+ TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
+ TIDSortedElemSet anAffected;
+ bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
+
+ storeResult(aMeshEditor);
+
+ myMesh->GetMeshDS()->Modified();
+ TPythonDump pyDump;
+ if (aResult)
+ {
+ myMesh->SetIsModified(true);
+
+ int lg = anAffected.size();
+ MESSAGE("lg="<< lg);
+ SMESH::long_array_var volumeIds = new SMESH::long_array;
+ volumeIds->length(lg);
+ SMESH::long_array_var faceIds = new SMESH::long_array;
+ faceIds->length(lg);
+ SMESH::long_array_var edgeIds = new SMESH::long_array;
+ edgeIds->length(lg);
+ int ivol = 0;
+ int iface = 0;
+ int iedge = 0;
+
+ TIDSortedElemSet::const_iterator eIt = anAffected.begin();
+ for (; eIt != anAffected.end(); ++eIt)
+ {
+ const SMDS_MeshElement* anElem = *eIt;
+ if (!anElem)
+ continue;
+ int elemId = anElem->GetID();
+ if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
+ volumeIds[ivol++] = elemId;
+ else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
+ faceIds[iface++] = elemId;
+ else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
+ edgeIds[iedge++] = elemId;
+ }
+ volumeIds->length(ivol);
+ faceIds->length(iface);
+ edgeIds->length(iedge);
+
+ aNewVolumeGroup->Add(volumeIds);
+ aNewFaceGroup->Add(faceIds);
+ aNewEdgeGroup->Add(edgeIds);
+ isVolumeGroup = (aNewVolumeGroup->Size() > 0);
+ isFaceGroup = (aNewFaceGroup->Size() > 0);
+ isEdgeGroup = (aNewEdgeGroup->Size() > 0);
+ }
+
+ int nbGroups = 0;
+ if (isEdgeGroup)
+ nbGroups++;
+ if (isFaceGroup)
+ nbGroups++;
+ if (isVolumeGroup)
+ nbGroups++;
+ aListOfGroups->length(nbGroups);
+
+ int i = 0;
+ if (isEdgeGroup)
+ aListOfGroups[i++] = aNewEdgeGroup._retn();
+ if (isFaceGroup)
+ aListOfGroups[i++] = aNewFaceGroup._retn();
+ if (isVolumeGroup)
+ aListOfGroups[i++] = aNewVolumeGroup._retn();
+
+ // Update Python script
+
+ pyDump << "[ ";
+ if (isEdgeGroup)
+ pyDump << aNewEdgeGroup << ", ";
+ if (isFaceGroup)
+ pyDump << aNewFaceGroup << ", ";
+ if (isVolumeGroup)
+ pyDump << aNewVolumeGroup << ", ";
+ pyDump << "] = ";
+ pyDump << this << ".AffectedElemGroupsInRegion( " << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
+
+ return aListOfGroups._retn();
+}
+
//================================================================================
/*!
\brief Generated skin mesh (containing 2D cells) from 3D mesh
return aResult;
}
+/*!
+ * \brief identify all the elements around a geom shape, get the faces delimiting the hole
+ * Build groups of volume to remove, groups of faces to replace on the skin of the object,
+ * groups of faces to remove inside the object, (idem edges).
+ * Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape)
+ */
+void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
+ GEOM::GEOM_Object_ptr theShape,
+ const char* groupName,
+ const SMESH::double_array& theNodesCoords,
+ SMESH::array_of_long_array_out GroupsOfNodes)
+throw (SALOME::SALOME_Exception)
+{
+ initData();
+ std::vector<std::vector<int> > aListOfListOfNodes;
+ ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+ theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
+ if ( !theNodeSearcher )
+ theNodeSearcher = aMeshEditor.GetNodeSearcher();
+
+ vector<double> nodesCoords;
+ for (int i = 0; i < theNodesCoords.length(); i++)
+ {
+ nodesCoords.push_back( theNodesCoords[i] );
+ }
+
+ TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
+ aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName, nodesCoords, aListOfListOfNodes);
+
+ GroupsOfNodes = new SMESH::array_of_long_array;
+ GroupsOfNodes->length( aListOfListOfNodes.size() );
+ std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
+ for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
+ {
+ vector<int>& aListOfNodes = *llIt;
+ vector<int>::iterator lIt = aListOfNodes.begin();;
+ SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
+ aGroup.length( aListOfNodes.size() );
+ for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
+ aGroup[ j ] = (*lIt);
+ }
+ TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
+ << radius << ", " << theShape << ", " << ", " << groupName << ", " << theNodesCoords << " )";
+}
+
+
// issue 20749 ===================================================================
/*!
* \brief Creates missing boundary elements