-// 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
#include <algorithm>
#include <sstream>
+#include <boost/tuple/tuple.hpp>
+
#include <Standard_Failure.hxx>
#include <Standard_ErrorHandler.hxx>
vecNewNodes[ 1 ]->second.back())) {
myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
vecNewNodes[ 1 ]->second.back()));
- srcElements.Append( myLastCreatedElems.Last() );
+ srcElements.Append( elem );
}
}
else {
myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
vecNewNodes[ 1 ]->second.back(),
vecNewNodes[ 2 ]->second.back()));
- srcElements.Append( myLastCreatedElems.Last() );
+ srcElements.Append( elem );
}
}
}
int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
- // check if a link is free
+ // check if a link n1-n2 is free
if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
hasFreeLinks = true;
- // make an edge and a ceiling for a new edge
- if ( !aMesh->FindEdge( n1, n2 )) {
- myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // free link edge
+ // make a new edge and a ceiling for a new edge
+ const SMDS_MeshElement* edge;
+ if ( ! ( edge = aMesh->FindEdge( n1, n2 ))) {
+ myLastCreatedElems.Append( edge = aMesh->AddEdge( n1, n2 )); // free link edge
srcElements.Append( myLastCreatedElems.Last() );
}
n1 = vecNewNodes[ iNode ]->second.back();
n2 = vecNewNodes[ iNext ]->second.back();
if ( !aMesh->FindEdge( n1, n2 )) {
- myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // ceiling edge
- srcElements.Append( myLastCreatedElems.Last() );
+ myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // new edge ceiling
+ srcElements.Append( edge );
}
}
}
// find medium node
if ( !aMesh->FindEdge( n1, n2, n3 )) {
myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // free link edge
- srcElements.Append( myLastCreatedElems.Last() );
+ srcElements.Append( elem );
}
n1 = vecNewNodes[ iNode ]->second.back();
n2 = vecNewNodes[ iNext ]->second.back();
n3 = vecNewNodes[ iNode+nbn ]->second.back();
if ( !aMesh->FindEdge( n1, n2, n3 )) {
myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // ceiling edge
- srcElements.Append( myLastCreatedElems.Last() );
+ srcElements.Append( elem );
}
}
}
}
while ( srcElements.Length() < myLastCreatedElems.Length() )
- srcElements.Append( myLastCreatedElems.Last() );
+ srcElements.Append( elem );
}
} // loop on swept elements
}
// Sort existing groups by types and collect their names
- // to store an old group and a generated new one
- typedef pair< SMESHDS_GroupBase*, SMESHDS_Group* > TOldNewGroup;
+ // to store an old group and a generated new ones
+ using boost::tuple;
+ using boost::make_tuple;
+ typedef tuple< SMESHDS_GroupBase*, SMESHDS_Group*, SMESHDS_Group* > TOldNewGroup;
vector< list< TOldNewGroup > > groupsByType( SMDSAbs_NbElementTypes );
vector< TOldNewGroup* > orderedOldNewGroups; // in order of old groups
// group names
if ( !group ) continue;
SMESHDS_GroupBase* groupDS = group->GetGroupDS();
if ( !groupDS || groupDS->IsEmpty() ) continue;
- groupNames.insert( group->GetName() );
+ groupNames.insert ( group->GetName() );
groupDS->SetStoreName( group->GetName() );
- SMESHDS_Group* newGroup = new SMESHDS_Group( newGroupID++, mesh->GetMeshDS(),
- groupDS->GetType() );
- groupsByType[ groupDS->GetType() ].push_back( make_pair( groupDS, newGroup ));
+ 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() );
}
const SMESH_SequenceOfElemPtr& gens = isNodes ? nodeGens : elemGens;
const SMESH_SequenceOfElemPtr& elems = isNodes ? myLastCreatedNodes : myLastCreatedElems;
if ( gens.Length() != elems.Length() )
- throw SALOME_Exception(LOCALIZED("invalid args"));
+ throw SALOME_Exception("SMESH_MeshEditor::generateGroups(): invalid args");
// loop on created elements
for (int iElem = 1; iElem <= elems.Length(); ++iElem )
++iElem; // skip all elements made by sourceElem
continue;
}
- // collect all elements made by sourceElem
+ // collect all elements made by the iElem-th sourceElem
list< const SMDS_MeshElement* > resultElems;
if ( const SMDS_MeshElement* resElem = elems( iElem ))
if ( resElem != sourceElem )
list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end();
for ( gOldNew = groupsOldNew.begin(); gOldNew != gLast; ++gOldNew )
{
- SMESHDS_GroupBase* oldGroup = gOldNew->first;
+ SMESHDS_GroupBase* oldGroup = gOldNew->get<0>();
if ( oldGroup->Contains( sourceElem )) // sourceElem is in oldGroup
{
// fill in a new group
- SMDS_MeshGroup & newGroup = gOldNew->second->SMDSGroup();
+ 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 )
- newGroup.Add( *resElemIt );
+ if ( !newGroup.Add( *resElemIt ))
+ rejectedElems.push_back( *resElemIt );
+
+ // fill "top" group
+ if ( !rejectedElems.empty() )
+ {
+ SMDS_MeshGroup & newTopGroup = gOldNew->get<2>()->SMDSGroup();
+ resLast = rejectedElems.end();
+ for ( resElemIt = rejectedElems.begin(); resElemIt != resLast; ++resElemIt )
+ !newTopGroup.Add( *resElemIt );
+ }
}
}
} // loop on created elements
// Create new SMESH_Groups from SMESHDS_Groups and remove empty SMESHDS_Groups
+ list<int> topGrouIds;
for ( size_t i = 0; i < orderedOldNewGroups.size(); ++i )
{
- SMESHDS_GroupBase* oldGroupDS = orderedOldNewGroups[i]->first;
- SMESHDS_Group* newGroupDS = orderedOldNewGroups[i]->second;
- if ( newGroupDS->IsEmpty() )
- {
- mesh->GetMeshDS()->RemoveGroup( newGroupDS );
- }
- else
- {
- // make a name
- string name = oldGroupDS->GetStoreName();
- if ( !targetMesh ) {
- name += "_";
- name += postfix;
- int nb = 1;
- while ( !groupNames.insert( name ).second ) // name exists
- name = SMESH_Comment( oldGroupDS->GetStoreName() ) << "_" << postfix << "_" << nb++;
+ SMESHDS_GroupBase* oldGroupDS = orderedOldNewGroups[i]->get<0>();
+ SMESHDS_Group* newGroups[2] = { orderedOldNewGroups[i]->get<1>(),
+ orderedOldNewGroups[i]->get<2>() };
+ const int nbNewGroups = !newGroups[0]->IsEmpty() + !newGroups[1]->IsEmpty();
+ for ( int is2nd = 0; is2nd < 2; ++is2nd )
+ {
+ SMESHDS_Group* newGroupDS = newGroups[ is2nd ];
+ if ( newGroupDS->IsEmpty() )
+ {
+ mesh->GetMeshDS()->RemoveGroup( newGroupDS );
+ }
+ else
+ {
+ // set group type
+ newGroupDS->SetType( newGroupDS->GetElements()->next()->GetType() );
+
+ // make a name
+ const bool isTop = ( nbNewGroups == 2 &&
+ newGroupDS->GetType() == oldGroupDS->GetType() );
+ string name = oldGroupDS->GetStoreName();
+ if ( !targetMesh ) {
+ string suffix = ( isTop ? "top": postfix.c_str() );
+ name += "_";
+ name += suffix;
+ int nb = 1;
+ while ( !groupNames.insert( name ).second ) // name exists
+ name = SMESH_Comment( oldGroupDS->GetStoreName() ) << "_" << suffix << "_" << nb++;
+ }
+ else if ( isTop ) {
+ name += "_top";
+ }
+ newGroupDS->SetStoreName( name.c_str() );
+
+ // make a SMESH_Groups
+ mesh->AddGroup( newGroupDS );
+ if ( isTop )
+ topGrouIds.push_back( newGroupDS->GetID() );
+ else
+ newGroupIDs->push_back( newGroupDS->GetID() );
}
- newGroupDS->SetStoreName( name.c_str() );
-
- // make a SMESH_Groups
- mesh->AddGroup( newGroupDS );
- newGroupIDs->push_back( newGroupDS->GetID() );
-
- // set group type
- newGroupDS->SetType( newGroupDS->GetElements()->next()->GetType() );
}
}
+ newGroupIDs->splice( newGroupIDs->end(), topGrouIds );
return newGroupIDs;
}
//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 )