#include <algorithm>
#include <sstream>
+#include <boost/tuple/tuple.hpp>
+
#include <Standard_Failure.hxx>
#include <Standard_ErrorHandler.hxx>
{
}
+//================================================================================
+/*!
+ * \brief Clears myLastCreatedNodes and myLastCreatedElems
+ */
+//================================================================================
+
+void SMESH_MeshEditor::CrearLastCreated()
+{
+ myLastCreatedNodes.Clear();
+ myLastCreatedElems.Clear();
+}
+
+
//=======================================================================
/*!
* \brief Add element
return removed;
}
+//================================================================================
+/*!
+ * \brief Create 0D elements on all nodes of the given object except those
+ * nodes on which a 0D element already exists.
+ * \param elements - Elements on whose nodes to create 0D elements; if empty,
+ * the all mesh is treated
+ * \param all0DElems - returns all 0D elements found or created on nodes of \a elements
+ */
+//================================================================================
+
+void SMESH_MeshEditor::Create0DElementsOnAllNodes( const TIDSortedElemSet& elements,
+ TIDSortedElemSet& all0DElems )
+{
+ typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator> TSetIterator;
+ SMDS_ElemIteratorPtr elemIt;
+ if ( elements.empty() )
+ elemIt = GetMeshDS()->elementsIterator( SMDSAbs_Node );
+ else
+ elemIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
+
+ while ( elemIt->more() )
+ {
+ const SMDS_MeshElement* e = elemIt->next();
+ SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
+ while ( nodeIt->more() )
+ {
+ const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
+ SMDS_ElemIteratorPtr it0D = n->GetInverseElementIterator( SMDSAbs_0DElement );
+ if ( it0D->more() )
+ all0DElems.insert( it0D->next() );
+ else {
+ myLastCreatedElems.Append( GetMeshDS()->Add0DElement( n ));
+ all0DElems.insert( myLastCreatedElems.Last() );
+ }
+ }
+ }
+}
+
//=======================================================================
//function : FindShape
//purpose : Return an index of the shape theElem is on
* \brief Reorient faces.
* \param theFaces - the faces to reorient. If empty the whole mesh is meant
* \param theDirection - desired direction of normal of \a theFace
- * \param theFace - one of \a theFaces that sould be orientated according to
+ * \param theFace - one of \a theFaces that sould be oriented according to
* \a theDirection and whose orientation defines orientation of other faces
* \return number of reoriented faces.
*/
// Orient other faces
- set< const SMDS_MeshElement* > startFaces;
+ set< const SMDS_MeshElement* > startFaces, visitedFaces;
TIDSortedElemSet avoidSet;
set< SMESH_TLink > checkedLinks;
pair< set< SMESH_TLink >::iterator, bool > linkIt_isNew;
theFaces.erase( theFace );
startFaces.insert( theFace );
+ int nodeInd1, nodeInd2;
+ const SMDS_MeshElement* otherFace;
+ vector< const SMDS_MeshElement* > facesNearLink;
+ vector< std::pair< int, int > > nodeIndsOfFace;
+
set< const SMDS_MeshElement* >::iterator startFace = startFaces.begin();
- while ( startFace != startFaces.end() )
+ while ( !startFaces.empty() )
{
+ startFace = startFaces.begin();
theFace = *startFace;
- const int nbNodes = theFace->NbCornerNodes();
+ startFaces.erase( startFace );
+ if ( !visitedFaces.insert( theFace ).second )
+ continue;
avoidSet.clear();
avoidSet.insert(theFace);
NLink link( theFace->GetNode( 0 ), 0 );
+
+ const int nbNodes = theFace->NbCornerNodes();
for ( int i = 0; i < nbNodes; ++i ) // loop on links of theFace
{
link.second = theFace->GetNode(( i+1 ) % nbNodes );
{
// link has already been checked and won't be encountered more
// if the group (theFaces) is manifold
- checkedLinks.erase( linkIt_isNew.first );
+ //checkedLinks.erase( linkIt_isNew.first );
}
else
{
- int nodeInd1, nodeInd2;
- const SMDS_MeshElement* otherFace = FindFaceInSet( link.first, link.second,
- theFaces, avoidSet,
- & nodeInd1, & nodeInd2);
+ facesNearLink.clear();
+ nodeIndsOfFace.clear();
+ while (( otherFace = FindFaceInSet( link.first, link.second,
+ theFaces, avoidSet, &nodeInd1, &nodeInd2 )))
+ if ( otherFace != theFace)
+ {
+ facesNearLink.push_back( otherFace );
+ nodeIndsOfFace.push_back( make_pair( nodeInd1, nodeInd2 ));
+ avoidSet.insert( otherFace );
+ }
+ if ( facesNearLink.size() > 1 )
+ {
+ // NON-MANIFOLD mesh shell !
+ // select a face most co-directed with theFace,
+ // other faces won't be visited this time
+ gp_XYZ NF, NOF;
+ SMESH_Algo::FaceNormal( theFace, NF, /*normalized=*/false );
+ double proj, maxProj = -1;
+ for ( size_t i = 0; i < facesNearLink.size(); ++i ) {
+ SMESH_Algo::FaceNormal( facesNearLink[i], NOF, /*normalized=*/false );
+ if (( proj = Abs( NF * NOF )) > maxProj ) {
+ maxProj = proj;
+ otherFace = facesNearLink[i];
+ nodeInd1 = nodeIndsOfFace[i].first;
+ nodeInd2 = nodeIndsOfFace[i].second;
+ }
+ }
+ // not to visit rejected faces
+ for ( size_t i = 0; i < facesNearLink.size(); ++i )
+ if ( facesNearLink[i] != otherFace && theFaces.size() > 1 )
+ visitedFaces.insert( facesNearLink[i] );
+ }
+ else if ( facesNearLink.size() == 1 )
+ {
+ otherFace = facesNearLink[0];
+ nodeInd1 = nodeIndsOfFace.back().first;
+ nodeInd2 = nodeIndsOfFace.back().second;
+ }
if ( otherFace && otherFace != theFace)
{
- // link must be reversed in otherFace if orientation ot otherFace
+ // link must be reverse in otherFace if orientation ot otherFace
// is same as that of theFace
if ( abs(nodeInd2-nodeInd1) == 1 ? nodeInd2 > nodeInd1 : nodeInd1 > nodeInd2 )
{
- // cout << "Reorient " << otherFace->GetID() << " near theFace=" <<theFace->GetID()
- // << " \tlink( " << link.first->GetID() << " " << link.second->GetID() << endl;
nbReori += Reorient( otherFace );
}
startFaces.insert( otherFace );
- if ( theFaces.size() > 1 ) // leave 1 face to prevent finding not selected faces
- theFaces.erase( otherFace );
}
}
- std::swap( link.first, link.second );
+ std::swap( link.first, link.second ); // reverse the link
}
- startFaces.erase( startFace );
- startFace = startFaces.begin();
}
return nbReori;
}
if( !elem->IsQuadratic() ) {
// split liner quadrangle
-
+ // for MaxElementLength2D functor we return minimum diagonal for splitting,
+ // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
if ( aBadRate1 <= aBadRate2 ) {
// tr1 + tr2 is better
newElem1 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
-
+ // for MaxElementLength2D functor we return minimum diagonal for splitting,
+ // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
return 1; // diagonal 1-3
SMDS_FaceIteratorPtr fIt = aMesh->facesIterator();
while ( fIt->more() ) {
const SMDS_MeshElement* face = fIt->next();
- theElems.insert( face );
+ theElems.insert( theElems.end(), face );
}
}
// get all face ids theElems are on
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
}
if ( BRep_Tool::Degenerated( aTrackEdge ) )
return EXTR_BAD_PATH_SHAPE;
TopExp::Vertices( aTrackEdge, aV1, aV2 );
- aItN = theTrack->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN1 = aItN->next();
- aItN = theTrack->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN2 = aItN->next();
+ const SMDS_MeshNode* aN1 = 0;
+ const SMDS_MeshNode* aN2 = 0;
+ if ( theTrack->GetSubMesh( aV1 ) && theTrack->GetSubMesh( aV1 )->GetSubMeshDS() ) {
+ aItN = theTrack->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes();
+ aN1 = aItN->next();
+ }
+ if ( theTrack->GetSubMesh( aV2 ) && theTrack->GetSubMesh( aV2 )->GetSubMeshDS() ) {
+ aItN = theTrack->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes();
+ aN2 = aItN->next();
+ }
// starting node must be aN1 or aN2
if ( !( aN1 == theN1 || aN2 == theN1 ) )
return EXTR_BAD_STARTING_NODE;
}
}
list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
- int startNid = theN1->GetID();
+ TopoDS_Vertex aVprev;
TColStd_MapOfInteger UsedNums;
int NbEdges = Edges.Length();
int i = 1;
SMESH_subMesh* locTrack = *itLSM;
SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
TopExp::Vertices( aTrackEdge, aV1, aV2 );
- aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN1 = aItN->next();
- aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN2 = aItN->next();
- // starting node must be aN1 or aN2
- if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue;
+ bool aN1isOK = false, aN2isOK = false;
+ if ( aVprev.IsNull() ) {
+ // if previous vertex is not yet defined, it means that we in the beginning of wire
+ // and we have to find initial vertex corresponding to starting node theN1
+ const SMDS_MeshNode* aN1 = 0;
+ const SMDS_MeshNode* aN2 = 0;
+
+ if ( locTrack->GetFather()->GetSubMesh(aV1) && locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS() ) {
+ aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes();
+ aN1 = aItN->next();
+ }
+ if ( locTrack->GetFather()->GetSubMesh(aV2) && locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS() ) {
+ aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes();
+ aN2 = aItN->next();
+ }
+ // starting node must be aN1 or aN2
+ aN1isOK = ( aN1 && aN1 == theN1 );
+ aN2isOK = ( aN2 && aN2 == theN1 );
+ }
+ else {
+ // we have specified ending vertex of the previous edge on the previous iteration
+ // and we have just to check that it corresponds to any vertex in current segment
+ aN1isOK = aVprev.IsSame( aV1 );
+ aN2isOK = aVprev.IsSame( aV2 );
+ }
+ if ( !aN1isOK && !aN2isOK ) continue;
// 2. Collect parameters on the track edge
aPrms.clear();
aItN = locMeshDS->GetNodes();
while ( aItN->more() ) {
- const SMDS_MeshNode* pNode = aItN->next();
+ const SMDS_MeshNode* pNode = aItN->next();
const SMDS_EdgePosition* pEPos =
static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
double aT = pEPos->GetUParameter();
}
list<SMESH_MeshEditor_PathPoint> LPP;
//Extrusion_Error err =
- MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
+ MakeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
LLPPs.push_back(LPP);
UsedNums.Add(k);
// update startN for search following egde
- if( aN1->GetID() == startNid ) startNid = aN2->GetID();
- else startNid = aN1->GetID();
+ if ( aN1isOK ) aVprev = aV2;
+ else aVprev = aV1;
break;
}
}
SMESH_MeshEditor_PathPoint PP2 = currList.front();
gp_Dir D1 = PP1.Tangent();
gp_Dir D2 = PP2.Tangent();
- gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
- (D1.Z()+D2.Z())/2 ) );
+ gp_Dir Dnew( ( D1.XYZ() + D2.XYZ() ) / 2 );
PP1.SetTangent(Dnew);
fullList.push_back(PP1);
itPP++;
SMDSAbs_GeometryType geomType = elem->GetGeomType();
int nbNodes = elem->NbNodes();
- if ( geomType == SMDSGeom_POINT ) continue; // node
+ if ( geomType == SMDSGeom_NONE ) continue; // node
switch ( geomType ) {
// 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
set< string > groupNames;
-
+
SMESH_Mesh::GroupIteratorPtr groupIt = GetMesh()->GetGroups();
if ( !groupIt->more() ) return newGroupIDs;
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;
}
}
else if ( tree->NbNodes() ) // put a tree to the treeMap
{
- const Bnd_B3d& box = tree->getBox();
+ const Bnd_B3d& box = *tree->getBox();
double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() ));
pair<TDistTreeMap::iterator,bool> it_in = treeMap.insert( make_pair( sqDist, tree ));
if ( !it_in.second ) // not unique distance to box center
TDistTreeMap::iterator sqDist_tree = treeMap.begin();
if ( treeMap.size() > 5 ) {
SMESH_OctreeNode* closestTree = sqDist_tree->second;
- const Bnd_B3d& box = closestTree->getBox();
+ const Bnd_B3d& box = *closestTree->getBox();
double limit = sqrt( sqDist_tree->first ) + sqrt ( box.SquareExtent() );
sqLimit = limit * limit;
}
protected:
ElementBndBoxTree():_size(0) {}
- SMESH_Octree* allocateOctreeChild() const { return new ElementBndBoxTree; }
+ SMESH_Octree* newChild() const { return new ElementBndBoxTree; }
void buildChildrenData();
Bnd_B3d* buildRootBox();
private:
//================================================================================
ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance)
- :SMESH_Octree( new SMESH_Octree::Limit( MaxLevel, /*minSize=*/0. ))
+ :SMESH_Octree( new SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ))
{
int nbElems = mesh.GetMeshInfo().NbElements( elemType );
_elements.reserve( nbElems );
{
for (int j = 0; j < 8; j++)
{
- if ( !_elements[i]->IsOut( myChildren[j]->getBox() ))
+ if ( !_elements[i]->IsOut( *myChildren[j]->getBox() ))
{
_elements[i]->_refCount++;
((ElementBndBoxTree*)myChildren[j])->_elements.push_back( _elements[i]);
void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt& point,
TIDSortedElemSet& foundElems)
{
- if ( getBox().IsOut( point.XYZ() ))
+ if ( getBox()->IsOut( point.XYZ() ))
return;
if ( isLeaf() )
void ElementBndBoxTree::getElementsNearLine( const gp_Ax1& line,
TIDSortedElemSet& foundElems)
{
- if ( getBox().IsOut( line ))
+ if ( getBox()->IsOut( line ))
return;
if ( isLeaf() )
const double radius,
TIDSortedElemSet& foundElems)
{
- if ( getBox().IsOut( center, radius ))
+ if ( getBox()->IsOut( center, radius ))
return;
if ( isLeaf() )
* \brief Find elements of given type where the given point is IN or ON.
* Returns nb of found elements and elements them-selves.
*
- * 'ALL' type means elements of any type excluding nodes, balls and 0D elements
+ * 'ALL' type means elements of any type excluding nodes, balls and 0D elements
*/
//=======================================================================
}
TIDSortedElemSet suspectElems;
_ebbTree->getElementsNearPoint( point, suspectElems );
-
+
if ( suspectElems.empty() && _ebbTree->maxSize() > 0 )
{
- gp_Pnt boxCenter = 0.5 * ( _ebbTree->getBox().CornerMin() +
- _ebbTree->getBox().CornerMax() );
+ gp_Pnt boxCenter = 0.5 * ( _ebbTree->getBox()->CornerMin() +
+ _ebbTree->getBox()->CornerMax() );
double radius;
- if ( _ebbTree->getBox().IsOut( point.XYZ() ))
+ if ( _ebbTree->getBox()->IsOut( point.XYZ() ))
radius = point.Distance( boxCenter ) - 0.5 * _ebbTree->maxSize();
else
radius = _ebbTree->maxSize() / pow( 2., _ebbTree->getHeight()) / 2;
POS_ALL = POS_LEFT | POS_RIGHT | POS_VERTEX };
struct PointPos
{
- PositionName _name;
+ PositionName _name;
int _index; // index of vertex or segment
PointPos( PositionName n, int i=-1 ): _name(n), _index(i) {}
//purpose : Return list of group of elements built on the same nodes.
// Search among theElements or in the whole mesh if theElements is empty
//=======================================================================
-void SMESH_MeshEditor::FindEqualElements(set<const SMDS_MeshElement*> & theElements,
- TListOfListOfElementsID & theGroupsOfElementsID)
+
+void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet & theElements,
+ TListOfListOfElementsID & theGroupsOfElementsID)
{
myLastCreatedElems.Clear();
myLastCreatedNodes.Clear();
- typedef set<const SMDS_MeshElement*> TElemsSet;
typedef map< SortableElement, int > TMapOfNodeSet;
typedef list<int> TGroupOfElems;
- TElemsSet elems;
if ( theElements.empty() )
{ // get all elements in the mesh
SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
while ( eIt->more() )
- elems.insert( elems.end(), eIt->next());
+ theElements.insert( theElements.end(), eIt->next());
}
- else
- elems = theElements;
vector< TGroupOfElems > arrayOfGroups;
TGroupOfElems groupOfElems;
TMapOfNodeSet mapOfNodeSet;
- TElemsSet::iterator elemIt = elems.begin();
- for ( int i = 0, j=0; elemIt != elems.end(); ++elemIt, ++j ) {
+ TIDSortedElemSet::iterator elemIt = theElements.begin();
+ for ( int i = 0, j=0; elemIt != theElements.end(); ++elemIt, ++j ) {
const SMDS_MeshElement* curElem = *elemIt;
SortableElement SE(curElem);
int ind = -1;
void SMESH_MeshEditor::MergeEqualElements()
{
- set<const SMDS_MeshElement*> aMeshElements; /* empty input -
- to merge equal elements in the whole mesh */
+ TIDSortedElemSet aMeshElements; /* empty input ==
+ to merge equal elements in the whole mesh */
TListOfListOfElementsID aGroupsOfElementsID;
FindEqualElements(aMeshElements, aGroupsOfElementsID);
MergeElements(aGroupsOfElementsID);
{
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() )
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;
if ( !theForce3d )
{ // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
aHelper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
- aHelper.FixQuadraticElements();
+ aHelper.FixQuadraticElements(myError);
}
}
//================================================================================
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 )
if ( !theForce3d && !getenv("NO_FixQuadraticElements"))
{ // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
helper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
- helper.FixQuadraticElements();
+ helper.FixQuadraticElements( myError );
}
}
groupDS = group->GetGroupDS();
if ( !groupDS || groupDS->IsEmpty() ) continue;
std::string grpName = group->GetName();
+ //MESSAGE("grpName=" << grpName);
if (grpName == groupName)
break;
+ else
+ groupDS = 0;
}
bool isNodeGroup = false;
if (nodesCoords.size() > 0)
isNodeCoords = true; // a list o nodes given by their coordinates
+ //MESSAGE("---" << isNodeGroup << " " << isNodeCoords);
// --- define groups to build