-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2013 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
using namespace std;
using namespace SMESH::Controls;
-typedef map<const SMDS_MeshElement*, list<const SMDS_MeshNode*> > TElemOfNodeListMap;
-typedef map<const SMDS_MeshElement*, list<const SMDS_MeshElement*> > TElemOfElemListMap;
-
typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator> TSetIterator;
//=======================================================================
const SMDSAbs_ElementType type = groupDS->GetType();
SMESHDS_Group* newGroup = new SMESHDS_Group( newGroupID++, mesh->GetMeshDS(), type );
SMESHDS_Group* newTopGroup = new SMESHDS_Group( newGroupID++, mesh->GetMeshDS(), type );
- groupsByType[ groupDS->GetType() ].push_back( make_tuple( groupDS, newGroup, newTopGroup ));
- orderedOldNewGroups.push_back( & groupsByType[ groupDS->GetType() ].back() );
+ groupsByType[ type ].push_back( make_tuple( groupDS, newGroup, newTopGroup ));
+ orderedOldNewGroups.push_back( & groupsByType[ type ].back() );
}
// Loop on nodes and elements to add them in new groups
if ( resElem != sourceElem )
resultElems.push_back( resElem );
- // add resultElems to groups made by ones the sourceElem belongs to
+ // there must be a top element
+ const SMDS_MeshElement* topElem = 0;
+ if ( isNodes )
+ {
+ topElem = resultElems.back();
+ resultElems.pop_back();
+ }
+ else
+ {
+ list< const SMDS_MeshElement* >::reverse_iterator resElemIt = resultElems.rbegin();
+ for ( ; resElemIt != resultElems.rend() ; ++resElemIt )
+ if ( (*resElemIt)->GetType() == sourceElem->GetType() )
+ {
+ topElem = *resElemIt;
+ resultElems.erase( --(resElemIt.base()) ); // erase *resElemIt
+ break;
+ }
+ }
+
+ // add resultElems to groups originted from ones the sourceElem belongs to
list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end();
for ( gOldNew = groupsOldNew.begin(); gOldNew != gLast; ++gOldNew )
{
{
// fill in a new group
SMDS_MeshGroup & newGroup = gOldNew->get<1>()->SMDSGroup();
- list< const SMDS_MeshElement* > rejectedElems; // elements of other type
list< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt;
for ( resElemIt = resultElems.begin(); resElemIt != resLast; ++resElemIt )
- if ( !newGroup.Add( *resElemIt ))
- rejectedElems.push_back( *resElemIt );
+ newGroup.Add( *resElemIt );
- // fill "top" group
- if ( !rejectedElems.empty() )
+ // fill a "top" group
+ if ( topElem )
{
SMDS_MeshGroup & newTopGroup = gOldNew->get<2>()->SMDSGroup();
- resLast = rejectedElems.end();
- for ( resElemIt = rejectedElems.begin(); resElemIt != resLast; ++resElemIt )
- !newTopGroup.Add( *resElemIt );
+ newTopGroup.Add( topElem );
}
}
}
// make a name
const bool isTop = ( nbNewGroups == 2 &&
- newGroupDS->GetType() == oldGroupDS->GetType() );
+ newGroupDS->GetType() == oldGroupDS->GetType() &&
+ is2nd );
+
string name = oldGroupDS->GetStoreName();
if ( !targetMesh ) {
string suffix = ( isTop ? "top": postfix.c_str() );
//MESSAGE(" node to remove " << nToRemove->GetID());
rmNodeIds.push_back( nToRemove->GetID() );
AddToSameGroups( nToKeep, nToRemove, aMesh );
+ // set _alwaysComputed to a sub-mesh of VERTEX to enable mesh computing
+ // after MergeNodes() w/o creating node in place of merged ones.
+ const SMDS_PositionPtr& pos = nToRemove->GetPosition();
+ if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
+ if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() ))
+ sm->SetIsAlwaysComputed( true );
}
SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
{
nbElem++;
const SMDS_MeshElement* elem = ElemItr->next();
- if( !elem || elem->IsQuadratic() ) continue;
+ if( !elem ) continue;
+ const SMDSAbs_EntityType aGeomType = elem->GetEntityType();
+ if ( elem->IsQuadratic() )
+ {
+ bool alreadyOK;
+ switch ( aGeomType ) {
+ case SMDSEntity_Quad_Quadrangle:
+ case SMDSEntity_Quad_Hexa: alreadyOK = !theHelper.GetIsBiQuadratic(); break;
+ case SMDSEntity_BiQuad_Quadrangle:
+ case SMDSEntity_TriQuad_Hexa: alreadyOK = theHelper.GetIsBiQuadratic(); break;
+ default: alreadyOK = true;
+ }
+ if ( alreadyOK ) continue;
+ }
// get elem data needed to re-create it
//
- const int id = elem->GetID();
- const int nbNodes = elem->NbNodes();
- const SMDSAbs_ElementType aType = elem->GetType();
- const SMDSAbs_EntityType aGeomType = elem->GetEntityType();
+ const int id = elem->GetID();
+ const int nbNodes = elem->NbCornerNodes();
+ const SMDSAbs_ElementType aType = elem->GetType();
nodes.assign(elem->begin_nodes(), elem->end_nodes());
if ( aGeomType == SMDSEntity_Polyhedra )
nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
break;
case SMDSEntity_Hexa:
+ case SMDSEntity_Quad_Hexa:
+ case SMDSEntity_TriQuad_Hexa:
NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
break;
}
return nbElem;
}
-
//=======================================================================
//function : ConvertToQuadratic
//purpose :
//=======================================================================
-void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
+void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theToBiQuad)
{
SMESHDS_Mesh* meshDS = GetMeshDS();
SMESH_MesherHelper aHelper(*myMesh);
+
aHelper.SetIsQuadratic( true );
+ aHelper.SetIsBiQuadratic( theToBiQuad );
+ aHelper.SetElementsOnShape(true);
int nbCheckedElems = 0;
if ( myMesh->HasShapeToMesh() )
int totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes();
if ( nbCheckedElems < totalNbElems ) // not all elements are in submeshes
{
+ aHelper.SetElementsOnShape(false);
SMESHDS_SubMesh *smDS = 0;
SMDS_EdgeIteratorPtr aEdgeItr = meshDS->edgesIterator();
while(aEdgeItr->more())
while(aFaceItr->more())
{
const SMDS_MeshFace* face = aFaceItr->next();
- if(!face || face->IsQuadratic() ) continue;
+ if ( !face ) continue;
+
+ const SMDSAbs_EntityType type = face->GetEntityType();
+ if (( theToBiQuad && type == SMDSEntity_BiQuad_Quadrangle ) ||
+ ( !theToBiQuad && type == SMDSEntity_Quad_Quadrangle ))
+ continue;
const int id = face->GetID();
- const SMDSAbs_EntityType type = face->GetEntityType();
vector<const SMDS_MeshNode *> nodes ( face->begin_nodes(), face->end_nodes());
meshDS->RemoveFreeElement(face, smDS, /*fromGroups=*/false);
const SMDS_MeshVolume* volume = aVolumeItr->next();
if(!volume || volume->IsQuadratic() ) continue;
- const int id = volume->GetID();
const SMDSAbs_EntityType type = volume->GetEntityType();
+ if (( theToBiQuad && type == SMDSEntity_TriQuad_Hexa ) ||
+ ( !theToBiQuad && type == SMDSEntity_Quad_Hexa ))
+ continue;
+
+ const int id = volume->GetID();
vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
if ( type == SMDSEntity_Polyhedra )
nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();
NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d );
break;
case SMDSEntity_Hexa:
+ case SMDSEntity_Quad_Hexa:
+ case SMDSEntity_TriQuad_Hexa:
NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
break;
//================================================================================
void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d,
- TIDSortedElemSet& theElements)
+ TIDSortedElemSet& theElements,
+ const bool theToBiQuad)
{
if ( theElements.empty() ) return;
const SMDS_MeshElement* e = invIt->next();
if ( e->IsQuadratic() )
{
- quadAdjacentElems[ e->GetType() ].insert( e );
- continue;
+ bool alreadyOK;
+ switch ( e->GetEntityType() ) {
+ case SMDSEntity_Quad_Quadrangle:
+ case SMDSEntity_Quad_Hexa: alreadyOK = !theToBiQuad; break;
+ case SMDSEntity_BiQuad_Quadrangle:
+ case SMDSEntity_TriQuad_Hexa: alreadyOK = theToBiQuad; break;
+ default: alreadyOK = true;
+ }
+ if ( alreadyOK )
+ {
+ quadAdjacentElems[ e->GetType() ].insert( e );
+ continue;
+ }
}
if ( e->GetType() >= elemType )
{
SMESH_MesherHelper helper(*myMesh);
helper.SetIsQuadratic( true );
+ helper.SetIsBiQuadratic( theToBiQuad );
// add links of quadratic adjacent elements to the helper
helper.AddTLinks( static_cast< const SMDS_MeshVolume*> (*eIt) );
}
- // make quadratic elements instead of linear ones
+ // make quadratic (or bi-tri-quadratic) elements instead of linear ones
- SMESHDS_Mesh* meshDS = GetMeshDS();
+ SMESHDS_Mesh* meshDS = GetMeshDS();
SMESHDS_SubMesh* smDS = 0;
for ( eIt = theElements.begin(); eIt != theElements.end(); ++eIt )
{
const SMDS_MeshElement* elem = *eIt;
- if( elem->IsQuadratic() || elem->NbNodes() < 2 || elem->IsPoly() )
+ if( elem->NbNodes() < 2 || elem->IsPoly() )
continue;
- const int id = elem->GetID();
+ if ( elem->IsQuadratic() )
+ {
+ bool alreadyOK;
+ switch ( elem->GetEntityType() ) {
+ case SMDSEntity_Quad_Quadrangle:
+ case SMDSEntity_Quad_Hexa: alreadyOK = !theToBiQuad; break;
+ case SMDSEntity_BiQuad_Quadrangle:
+ case SMDSEntity_TriQuad_Hexa: alreadyOK = theToBiQuad; break;
+ default: alreadyOK = true;
+ }
+ if ( alreadyOK ) continue;
+ }
+
const SMDSAbs_ElementType type = elem->GetType();
+ const int id = elem->GetID();
+ const int nbNodes = elem->NbCornerNodes();
vector<const SMDS_MeshNode *> nodes ( elem->begin_nodes(), elem->end_nodes());
if ( !smDS || !smDS->Contains( elem ))
meshDS->RemoveFreeElement(elem, smDS, /*fromGroups=*/false);
SMDS_MeshElement * newElem = 0;
- switch( nodes.size() )
+ switch( nbNodes )
{
case 4: // cases for most frequently used element types go first (for optimization)
if ( type == SMDSAbs_Volume )
/*!
* \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
- * The list of groups must describe a partition of the mesh volumes.
- * The nodes of the internal faces at the boundaries of the groups are doubled.
- * In option, the internal faces are replaced by flat elements.
- * Triangles are transformed in prisms, and quadrangles in hexahedrons.
- * The flat elements are stored in groups of volumes.
+ * The list of groups must contain at least two groups. The groups have to be disjoint: no common element into two different groups.
+ * The nodes of the internal faces at the boundaries of the groups are doubled. Optionally, the internal faces are replaced by flat elements.
+ * Triangles are transformed into prisms, and quadrangles into hexahedrons.
+ * The flat elements are stored in groups of volumes. These groups are named according to the position of the group in the list:
+ * the group j_n_p is the group of the flat elements that are built between the group #n and the group #p in the list.
+ * If there is no shared faces between the group #n and the group #p in the list, the group j_n_p is not created.
+ * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
+ * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
* @param theElems - list of groups of volumes, where a group of volume is a set of
* SMDS_MeshElements sorted by Id.
* @param createJointElems - if TRUE, create the elements
std::set<int> emptySet;
emptyMap.clear();
+ MESSAGE(".. Number of domains :"<<theElems.size());
+
+ // Check if the domains do not share an element
+ for (int idom = 0; idom < theElems.size()-1; idom++)
+ {
+// MESSAGE("... Check of domain #" << idom);
+ const TIDSortedElemSet& domain = theElems[idom];
+ TIDSortedElemSet::const_iterator elemItr = domain.begin();
+ for (; elemItr != domain.end(); ++elemItr)
+ {
+ SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
+ int idombisdeb = idom + 1 ;
+ for (int idombis = idombisdeb; idombis < theElems.size(); idombis++) // check if the element belongs to a domain further in the list
+ {
+ const TIDSortedElemSet& domainbis = theElems[idombis];
+ if ( domainbis.count(anElem) )
+ {
+ MESSAGE(".... Domain #" << idom);
+ MESSAGE(".... Domain #" << idombis);
+ throw SALOME_Exception("The domains are not disjoint.");
+ return false ;
+ }
+ }
+ }
+ }
+
for (int idom = 0; idom < theElems.size(); idom++)
{
// and corresponding volume of this domain, for each shared face.
// a volume has a face shared by 2 domains if it has a neighbor which is not in his domain.
- //MESSAGE("Domain " << idom);
+ MESSAGE("... Neighbors of domain #" << idom);
const TIDSortedElemSet& domain = theElems[idom];
TIDSortedElemSet::const_iterator elemItr = domain.begin();
for (; elemItr != domain.end(); ++elemItr)
const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
if (! domain.count(elem)) // neighbor is in another domain : face is shared
{
- DownIdType face(downIds[n], downTypes[n]);
- if (!faceDomains.count(face))
- faceDomains[face] = emptyMap; // create an empty entry for face
- if (!faceDomains[face].count(idom))
- {
- faceDomains[face][idom] = vtkId; // volume associated to face in this domain
- celldom[vtkId] = idom;
- //MESSAGE(" cell with a border " << vtkId << " domain " << idom);
- }
+ bool ok = false ;
+ for (int idombis = 0; idombis < theElems.size(); idombis++) // check if the neighbor belongs to another domain of the list
+ {
+ // MESSAGE("Domain " << idombis);
+ const TIDSortedElemSet& domainbis = theElems[idombis];
+ if ( domainbis.count(elem)) ok = true ; // neighbor is in a correct domain : face is kept
+ }
+ if ( ok ) // the characteristics of the face is stored
+ {
+ DownIdType face(downIds[n], downTypes[n]);
+ if (!faceDomains.count(face))
+ faceDomains[face] = emptyMap; // create an empty entry for face
+ if (!faceDomains[face].count(idom))
+ {
+ faceDomains[face][idom] = vtkId; // volume associated to face in this domain
+ celldom[vtkId] = idom;
+ //MESSAGE(" cell with a border " << vtkId << " domain " << idom);
+ }
+ }
}
}
}
std::map<int, std::vector<int> > mutipleNodes; // nodes multi domains with domain order
std::map<int, std::vector<int> > mutipleNodesToFace; // nodes multi domains with domain order to transform in Face (junction between 3 or more 2D domains)
+ MESSAGE(".. Duplication of the nodes");
for (int idomain = 0; idomain < theElems.size(); idomain++)
{
itface = faceDomains.begin();
}
}
+ MESSAGE(".. Creation of elements");
for (int idomain = 0; idomain < theElems.size(); idomain++)
{
itface = faceDomains.begin();
std::map<int, std::map<long,int> > nodeQuadDomains;
std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
+ MESSAGE(".. Creation of elements: simple junction");
if (createJointElems)
{
int idg;
// iterate on mutipleNodesToFace
// iterate on edgesMultiDomains
+ MESSAGE(".. Creation of elements: multiple junction");
if (createJointElems)
{
// --- iterate on mutipleNodesToFace
faceOrEdgeDom.clear();
feDom.clear();
+ MESSAGE(".. Modification of elements");
for (int idomain = 0; idomain < theElems.size(); idomain++)
{
std::map<int, std::map<int, int> >::const_iterator itnod = nodeDomains.begin();