52846: It is impossible to select edge in OB as reversed edge for hypothesis

52826: Radial Quadrangle algorithm meshes a quad face from which a circle was cut from but it must fail
52227: Group is not shown during edition
52780: Wrong mesh after STL re-import of a polygonal element
52825: Sew Borders does not care of segment adjacent to split faces, thus segments become non-conformal
52824: Sew Free Borders sews borders as conformal thus producing very skewed quads instead of polygons
This commit is contained in:
eap 2015-08-19 17:32:58 +03:00
parent 741a54331a
commit 87c954b31c
9 changed files with 383 additions and 340 deletions

View File

@ -338,7 +338,41 @@ namespace
++nbBadTria; ++nbBadTria;
} }
} }
return false;
// the polygon is invalid; add triangles with positive area
nbBadTria = 0;
while ( nbBadTria < nbVertices )
{
isGoodTria = v->TriaArea() > minArea;
if ( isGoodTria )
{
v->GetTriaNodes( &nodes[ iN ] );
iN += 3;
v = v->Delete();
if ( --nbVertices == 3 )
{
// last triangle remains
v->GetTriaNodes( &nodes[ iN ] );
return true;
}
nbBadTria = 0;
}
else
{
v = v->_next;
++nbBadTria;
}
}
// add all the rest triangles
while ( nbVertices >= 3 )
{
v->GetTriaNodes( &nodes[ iN ] );
iN += 3;
v = v->Delete();
}
return true;
} // triangulate() } // triangulate()
} // namespace } // namespace
@ -394,15 +428,15 @@ static int getTriangles( const SMDS_MeshElement* face,
case SMDSEntity_BiQuad_Quadrangle: case SMDSEntity_BiQuad_Quadrangle:
nbTria = ( type == SMDSEntity_BiQuad_Triangle ) ? 6 : 8; nbTria = ( type == SMDSEntity_BiQuad_Triangle ) ? 6 : 8;
nodes[ i++ ] = face->GetNode( nbTria ); nodes[ i++ ] = face->GetNode( nbTria );
while ( i < 3*(nbTria-1) ) for ( i = 3; i < 3*(nbTria-1); i += 3 )
{ {
nodes[ i++ ] = nodes[ i-2 ]; nodes[ i+0 ] = nodes[ i-2 ];
nodes[ i++ ] = nIt->next(); nodes[ i+1 ] = nIt->next();
nodes[ i++ ] = nodes[ 2 ]; nodes[ i+2 ] = nodes[ 2 ];
} }
nodes[ i++ ] = nodes[ i-2 ]; nodes[ i+0 ] = nodes[ i-2 ];
nodes[ i++ ] = nodes[ 0 ]; nodes[ i+1 ] = nodes[ 0 ];
nodes[ i++ ] = nodes[ 2 ]; nodes[ i+2 ] = nodes[ 2 ];
break; break;
case SMDSEntity_Triangle: case SMDSEntity_Triangle:
nbTria = 1; nbTria = 1;

View File

@ -2484,7 +2484,7 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode
int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes(); int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
if ( nbNodesToCheck == nodes.size() ) if ( nbNodesToCheck == nodes.size() )
{ {
for ( int i = 1; e && i < nodes.size(); ++ i ) for ( size_t i = 1; e && i < nodes.size(); ++i )
{ {
int nodeIndex = e->GetNodeIndex( nodes[ i ]); int nodeIndex = e->GetNodeIndex( nodes[ i ]);
if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck ) if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )

View File

@ -2975,7 +2975,6 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
} }
AddToSameGroups( newElem1, elem, aMesh ); AddToSameGroups( newElem1, elem, aMesh );
AddToSameGroups( newElem2, elem, aMesh ); AddToSameGroups( newElem2, elem, aMesh );
//aMesh->RemoveFreeElement(elem, aMesh->MeshElements(aShapeId), true);
aMesh->RemoveElement( elem ); aMesh->RemoveElement( elem );
} }
@ -8089,6 +8088,24 @@ static const SMDS_MeshElement* findAdjacentFace(const SMDS_MeshNode* n1,
return SMESH_MeshAlgos::FindFaceInSet( n1, n2, elemSet, avoidSet ); return SMESH_MeshAlgos::FindFaceInSet( n1, n2, elemSet, avoidSet );
} }
//=======================================================================
//function : findSegment
//purpose : Return a mesh segment by two nodes one of which can be medium
//=======================================================================
static const SMDS_MeshElement* findSegment(const SMDS_MeshNode* n1,
const SMDS_MeshNode* n2)
{
SMDS_ElemIteratorPtr it = n1->GetInverseElementIterator( SMDSAbs_Edge );
while ( it->more() )
{
const SMDS_MeshElement* seg = it->next();
if ( seg->GetNodeIndex( n2 ) >= 0 )
return seg;
}
return 0;
}
//======================================================================= //=======================================================================
//function : FindFreeBorder //function : FindFreeBorder
//purpose : //purpose :
@ -8113,7 +8130,6 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst
theNodes.push_back( theFirstNode ); theNodes.push_back( theFirstNode );
theNodes.push_back( theSecondNode ); theNodes.push_back( theSecondNode );
//vector<const SMDS_MeshNode*> nodes;
const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode; const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
TIDSortedElemSet foundElems; TIDSortedElemSet foundElems;
bool needTheLast = ( theLastNode != 0 ); bool needTheLast = ( theLastNode != 0 );
@ -8125,17 +8141,16 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst
// find all free border faces sharing form nStart // find all free border faces sharing form nStart
list< const SMDS_MeshElement* > curElemList; list< const SMDS_MeshElement* > curElemList;
list< const SMDS_MeshNode* > nStartList; list< const SMDS_MeshNode* > nStartList;
SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face); SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face);
while ( invElemIt->more() ) { while ( invElemIt->more() ) {
const SMDS_MeshElement* e = invElemIt->next(); const SMDS_MeshElement* e = invElemIt->next();
if ( e == curElem || foundElems.insert( e ).second ) { if ( e == curElem || foundElems.insert( e ).second ) {
// get nodes // get nodes
int iNode = 0, nbNodes = e->NbNodes(); int iNode = 0, nbNodes = e->NbNodes();
//const SMDS_MeshNode* nodes[nbNodes+1];
vector<const SMDS_MeshNode*> nodes(nbNodes+1); vector<const SMDS_MeshNode*> nodes(nbNodes+1);
if(e->IsQuadratic()) { if ( e->IsQuadratic() ) {
const SMDS_VtkFace* F = const SMDS_VtkFace* F =
dynamic_cast<const SMDS_VtkFace*>(e); dynamic_cast<const SMDS_VtkFace*>(e);
if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
@ -8275,9 +8290,9 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
// find side nodes and elements // find side nodes and elements
// ==================================== // ====================================
list< const SMDS_MeshNode* > nSide[ 2 ]; list< const SMDS_MeshNode* > nSide[ 2 ];
list< const SMDS_MeshElement* > eSide[ 2 ]; list< const SMDS_MeshElement* > eSide[ 2 ];
list< const SMDS_MeshNode* >::iterator nIt[ 2 ]; list< const SMDS_MeshNode* >::iterator nIt[ 2 ];
list< const SMDS_MeshElement* >::iterator eIt[ 2 ]; list< const SMDS_MeshElement* >::iterator eIt[ 2 ];
// Free border 1 // Free border 1
@ -8516,9 +8531,23 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
int nbNodes[] = { nSide[0].size(), nSide[1].size() }; int nbNodes[] = { nSide[0].size(), nSide[1].size() };
int maxNbNodes = Max( nbNodes[0], nbNodes[1] ); int maxNbNodes = Max( nbNodes[0], nbNodes[1] );
bool toMergeConformal = ( nbNodes[0] == nbNodes[1] );
if ( toMergeConformal && toCreatePolygons )
{
// do not merge quadrangles if polygons are OK (IPAL0052824)
eIt[0] = eSide[0].begin();
eIt[1] = eSide[1].begin();
bool allQuads[2] = { true, true };
for ( int iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders
for ( ; allQuads[iBord] && eIt[iBord] != eSide[iBord].end(); ++eIt[iBord] )
allQuads[iBord] = ( (*eIt[iBord])->NbCornerNodes() == 4 );
}
toMergeConformal = ( !allQuads[0] && !allQuads[1] );
}
TListOfListOfNodes nodeGroupsToMerge; TListOfListOfNodes nodeGroupsToMerge;
if ( nbNodes[0] == nbNodes[1] || if (( toMergeConformal ) ||
( theSideIsFreeBorder && !theSideThirdNode)) { ( theSideIsFreeBorder && !theSideThirdNode )) {
// all nodes are to be merged // all nodes are to be merged
@ -8536,10 +8565,9 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
// insert new nodes into the border and the side to get equal nb of segments // insert new nodes into the border and the side to get equal nb of segments
// get normalized parameters of nodes on the borders // get normalized parameters of nodes on the borders
//double param[ 2 ][ maxNbNodes ]; vector< double > param[ 2 ];
double* param[ 2 ]; param[0].resize( maxNbNodes );
param[0] = new double [ maxNbNodes ]; param[1].resize( maxNbNodes );
param[1] = new double [ maxNbNodes ];
int iNode, iBord; int iNode, iBord;
for ( iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders for ( iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders
list< const SMDS_MeshNode* >& nodes = nSide[ iBord ]; list< const SMDS_MeshNode* >& nodes = nSide[ iBord ];
@ -8584,8 +8612,8 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
if ( i[ iBord ] > 0 ) if ( i[ iBord ] > 0 )
prevParam = Max( prevParam, param[iBord][ i[iBord] - 1 ]); prevParam = Max( prevParam, param[iBord][ i[iBord] - 1 ]);
} }
double minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]); double minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
double maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]); double maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
double minSegLen = Min( nextParam - minParam, maxParam - prevParam ); double minSegLen = Min( nextParam - minParam, maxParam - prevParam );
// choose to insert or to merge nodes // choose to insert or to merge nodes
@ -8609,10 +8637,10 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
// insert // insert
// ------ // ------
int intoBord = ( du < 0 ) ? 0 : 1; int intoBord = ( du < 0 ) ? 0 : 1;
const SMDS_MeshElement* elem = *eIt[ intoBord ]; const SMDS_MeshElement* elem = *eIt [ intoBord ];
const SMDS_MeshNode* n1 = nPrev[ intoBord ]; const SMDS_MeshNode* n1 = nPrev[ intoBord ];
const SMDS_MeshNode* n2 = *nIt[ intoBord ]; const SMDS_MeshNode* n2 = *nIt [ intoBord ];
const SMDS_MeshNode* nIns = *nIt[ 1 - intoBord ]; const SMDS_MeshNode* nIns = *nIt [ 1 - intoBord ];
if ( intoBord == 1 ) { if ( intoBord == 1 ) {
// move node of the border to be on a link of elem of the side // move node of the border to be on a link of elem of the side
gp_XYZ p1 (n1->X(), n1->Y(), n1->Z()); gp_XYZ p1 (n1->X(), n1->Y(), n1->Z());
@ -8622,7 +8650,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() ); GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() );
} }
insertMapIt = insertMap.find( elem ); insertMapIt = insertMap.find( elem );
bool notFound = ( insertMapIt == insertMap.end() ); bool notFound = ( insertMapIt == insertMap.end() );
bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 ); bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 );
if ( otherLink ) { if ( otherLink ) {
// insert into another link of the same element: // insert into another link of the same element:
@ -8632,12 +8660,11 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
const SMDS_MeshNode* n22 = nodeList.front(); nodeList.pop_front(); const SMDS_MeshNode* n22 = nodeList.front(); nodeList.pop_front();
InsertNodesIntoLink( elem, n12, n22, nodeList, toCreatePolygons ); InsertNodesIntoLink( elem, n12, n22, nodeList, toCreatePolygons );
// 2. perform insertion into the link of adjacent faces // 2. perform insertion into the link of adjacent faces
while (true) { while ( const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem )) {
const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem ); InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons );
if ( adjElem ) }
InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons ); while ( const SMDS_MeshElement* seg = findSegment( n12, n22 )) {
else InsertNodesIntoLink( seg, n12, n22, nodeList );
break;
} }
if (toCreatePolyedrs) { if (toCreatePolyedrs) {
// perform insertion into the links of adjacent volumes // perform insertion into the links of adjacent volumes
@ -8649,8 +8676,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
} }
if ( notFound || otherLink ) { if ( notFound || otherLink ) {
// add element and nodes of the side into the insertMap // add element and nodes of the side into the insertMap
insertMapIt = insertMap.insert insertMapIt = insertMap.insert( make_pair( elem, list<const SMDS_MeshNode*>() )).first;
( TElemOfNodeListMap::value_type( elem, list<const SMDS_MeshNode*>() )).first;
(*insertMapIt).second.push_back( n1 ); (*insertMapIt).second.push_back( n1 );
(*insertMapIt).second.push_back( n2 ); (*insertMapIt).second.push_back( n2 );
} }
@ -8684,14 +8710,14 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
InsertNodesIntoLink( elem, n1, n2, nodeList, toCreatePolygons ); InsertNodesIntoLink( elem, n1, n2, nodeList, toCreatePolygons );
while ( const SMDS_MeshElement* seg = findSegment( n1, n2 )) {
InsertNodesIntoLink( seg, n1, n2, nodeList );
}
if ( !theSideIsFreeBorder ) { if ( !theSideIsFreeBorder ) {
// look for and insert nodes into the faces adjacent to elem // look for and insert nodes into the faces adjacent to elem
while (true) { while ( const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem )) {
const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem ); InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons );
if ( adjElem )
InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons );
else
break;
} }
} }
if (toCreatePolyedrs) { if (toCreatePolyedrs) {
@ -8699,69 +8725,144 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
UpdateVolumes(n1, n2, nodeList); UpdateVolumes(n1, n2, nodeList);
} }
} }
delete param[0];
delete param[1];
} // end: insert new nodes } // end: insert new nodes
MergeNodes ( nodeGroupsToMerge ); MergeNodes ( nodeGroupsToMerge );
// Remove coincident segments
// get new segments
TIDSortedElemSet segments;
SMESH_SequenceOfElemPtr newFaces;
for ( int i = 1; i <= myLastCreatedElems.Length(); ++i )
{
if ( !myLastCreatedElems(i) ) continue;
if ( myLastCreatedElems(i)->GetType() == SMDSAbs_Edge )
segments.insert( segments.end(), myLastCreatedElems(i) );
else
newFaces.Append( myLastCreatedElems(i) );
}
// find coincident
TListOfListOfElementsID equalGroups;
FindEqualElements( segments, equalGroups );
if ( !equalGroups.empty() )
{
// remove from segments those that will be removed
TListOfListOfElementsID::iterator itGroups = equalGroups.begin();
for ( ; itGroups != equalGroups.end(); ++itGroups )
{
list< int >& group = *itGroups;
list< int >::iterator id = group.begin();
for ( ++id; id != group.end(); ++id )
if ( const SMDS_MeshElement* seg = GetMeshDS()->FindElement( *id ))
segments.erase( seg );
}
// remove equal segments
MergeElements( equalGroups );
// restore myLastCreatedElems
myLastCreatedElems = newFaces;
TIDSortedElemSet::iterator seg = segments.begin();
for ( ; seg != segments.end(); ++seg )
myLastCreatedElems.Append( *seg );
}
return aResult; return aResult;
} }
//======================================================================= //=======================================================================
//function : InsertNodesIntoLink //function : InsertNodesIntoLink
//purpose : insert theNodesToInsert into theFace between theBetweenNode1 //purpose : insert theNodesToInsert into theElement between theBetweenNode1
// and theBetweenNode2 and split theElement // and theBetweenNode2 and split theElement
//======================================================================= //=======================================================================
void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theElement,
const SMDS_MeshNode* theBetweenNode1, const SMDS_MeshNode* theBetweenNode1,
const SMDS_MeshNode* theBetweenNode2, const SMDS_MeshNode* theBetweenNode2,
list<const SMDS_MeshNode*>& theNodesToInsert, list<const SMDS_MeshNode*>& theNodesToInsert,
const bool toCreatePoly) const bool toCreatePoly)
{ {
if ( !theElement ) return;
SMESHDS_Mesh *aMesh = GetMeshDS();
vector<const SMDS_MeshElement*> newElems;
if ( theElement->GetType() == SMDSAbs_Edge )
{
theNodesToInsert.push_front( theBetweenNode1 );
theNodesToInsert.push_back ( theBetweenNode2 );
list<const SMDS_MeshNode*>::iterator n = theNodesToInsert.begin();
const SMDS_MeshNode* n1 = *n;
for ( ++n; n != theNodesToInsert.end(); ++n )
{
const SMDS_MeshNode* n2 = *n;
if ( const SMDS_MeshElement* seg = aMesh->FindEdge( n1, n2 ))
AddToSameGroups( seg, theElement, aMesh );
else
newElems.push_back( aMesh->AddEdge ( n1, n2 ));
n1 = n2;
}
theNodesToInsert.pop_front();
theNodesToInsert.pop_back();
if ( theElement->IsQuadratic() ) // add a not split part
{
vector<const SMDS_MeshNode*> nodes( theElement->begin_nodes(),
theElement->end_nodes() );
int iOther = 0, nbN = nodes.size();
for ( ; iOther < nbN; ++iOther )
if ( nodes[iOther] != theBetweenNode1 &&
nodes[iOther] != theBetweenNode2 )
break;
if ( iOther == 0 )
{
if ( const SMDS_MeshElement* seg = aMesh->FindEdge( nodes[0], nodes[1] ))
AddToSameGroups( seg, theElement, aMesh );
else
newElems.push_back( aMesh->AddEdge ( nodes[0], nodes[1] ));
}
else if ( iOther == 2 )
{
if ( const SMDS_MeshElement* seg = aMesh->FindEdge( nodes[1], nodes[2] ))
AddToSameGroups( seg, theElement, aMesh );
else
newElems.push_back( aMesh->AddEdge ( nodes[1], nodes[2] ));
}
}
// treat new elements
for ( size_t i = 0; i < newElems.size(); ++i )
if ( newElems[i] )
{
aMesh->SetMeshElementOnShape( newElems[i], theElement->getshapeId() );
myLastCreatedElems.Append( newElems[i] );
}
ReplaceElemInGroups( theElement, newElems, aMesh );
aMesh->RemoveElement( theElement );
return;
} // if ( theElement->GetType() == SMDSAbs_Edge )
const SMDS_MeshElement* theFace = theElement;
if ( theFace->GetType() != SMDSAbs_Face ) return; if ( theFace->GetType() != SMDSAbs_Face ) return;
// find indices of 2 link nodes and of the rest nodes // find indices of 2 link nodes and of the rest nodes
int iNode = 0, il1, il2, i3, i4; int iNode = 0, il1, il2, i3, i4;
il1 = il2 = i3 = i4 = -1; il1 = il2 = i3 = i4 = -1;
//const SMDS_MeshNode* nodes[ theFace->NbNodes() ];
vector<const SMDS_MeshNode*> nodes( theFace->NbNodes() ); vector<const SMDS_MeshNode*> nodes( theFace->NbNodes() );
if(theFace->IsQuadratic()) { SMDS_NodeIteratorPtr nodeIt = theFace->interlacedNodesIterator();
const SMDS_VtkFace* F = while ( nodeIt->more() ) {
dynamic_cast<const SMDS_VtkFace*>(theFace); const SMDS_MeshNode* n = nodeIt->next();
if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); if ( n == theBetweenNode1 )
// use special nodes iterator il1 = iNode;
SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); else if ( n == theBetweenNode2 )
while( anIter->more() ) { il2 = iNode;
const SMDS_MeshNode* n = cast2Node(anIter->next()); else if ( i3 < 0 )
if ( n == theBetweenNode1 ) i3 = iNode;
il1 = iNode; else
else if ( n == theBetweenNode2 ) i4 = iNode;
il2 = iNode; nodes[ iNode++ ] = n;
else if ( i3 < 0 )
i3 = iNode;
else
i4 = iNode;
nodes[ iNode++ ] = n;
}
}
else {
SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
while ( nodeIt->more() ) {
const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
if ( n == theBetweenNode1 )
il1 = iNode;
else if ( n == theBetweenNode2 )
il2 = iNode;
else if ( i3 < 0 )
i3 = iNode;
else
i4 = iNode;
nodes[ iNode++ ] = n;
}
} }
if ( il1 < 0 || il2 < 0 || i3 < 0 ) if ( il1 < 0 || il2 < 0 || i3 < 0 )
return ; return ;
@ -8791,9 +8892,8 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace,
// add nodes of face up to first node of link // add nodes of face up to first node of link
bool isFLN = false; bool isFLN = false;
if(theFace->IsQuadratic()) { if ( theFace->IsQuadratic() ) {
const SMDS_VtkFace* F = const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>(theFace);
dynamic_cast<const SMDS_VtkFace*>(theFace);
if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
// use special nodes iterator // use special nodes iterator
SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
@ -8835,28 +8935,12 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace,
} }
} }
// edit or replace the face // make a new face
SMESHDS_Mesh *aMesh = GetMeshDS(); newElems.push_back( aMesh->AddPolygonalFace( poly_nodes ));
if (theFace->IsPoly()) {
aMesh->ChangePolygonNodes(theFace, poly_nodes);
}
else {
int aShapeId = FindShape( theFace );
SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
aMesh->RemoveElement(theFace);
}
return;
} }
SMESHDS_Mesh *aMesh = GetMeshDS(); else if ( !theFace->IsQuadratic() )
if( !theFace->IsQuadratic() ) { {
// put aNodesToInsert between theBetweenNode1 and theBetweenNode2 // put aNodesToInsert between theBetweenNode1 and theBetweenNode2
int nbLinkNodes = 2 + aNodesToInsert.size(); int nbLinkNodes = 2 + aNodesToInsert.size();
//const SMDS_MeshNode* linkNodes[ nbLinkNodes ]; //const SMDS_MeshNode* linkNodes[ nbLinkNodes ];
@ -8905,41 +8989,32 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace,
} }
// create new elements // create new elements
int aShapeId = FindShape( theFace );
i1 = 0; i2 = 1; i1 = 0; i2 = 1;
for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) { for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) {
SMDS_MeshElement* newElem = 0; SMDS_MeshElement* newElem = 0;
if ( iSplit == iBestQuad ) if ( iSplit == iBestQuad )
newElem = aMesh->AddFace (linkNodes[ i1++ ], newElems.push_back( aMesh->AddFace (linkNodes[ i1++ ],
linkNodes[ i2++ ], linkNodes[ i2++ ],
nodes[ i3 ], nodes[ i3 ],
nodes[ i4 ]); nodes[ i4 ]));
else else
newElem = aMesh->AddFace (linkNodes[ i1++ ], newElems.push_back( aMesh->AddFace (linkNodes[ i1++ ],
linkNodes[ i2++ ], linkNodes[ i2++ ],
nodes[ iSplit < iBestQuad ? i4 : i3 ]); nodes[ iSplit < iBestQuad ? i4 : i3 ]));
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
} }
// change nodes of theFace
const SMDS_MeshNode* newNodes[ 4 ]; const SMDS_MeshNode* newNodes[ 4 ];
newNodes[ 0 ] = linkNodes[ i1 ]; newNodes[ 0 ] = linkNodes[ i1 ];
newNodes[ 1 ] = linkNodes[ i2 ]; newNodes[ 1 ] = linkNodes[ i2 ];
newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ]; newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
newNodes[ 3 ] = nodes[ i4 ]; newNodes[ 3 ] = nodes[ i4 ];
//aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
const SMDS_MeshElement* newElem = 0;
if (iSplit == iBestQuad) if (iSplit == iBestQuad)
newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] ); newElems.push_back( aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] ));
else else
newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] ); newElems.push_back( aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] ));
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem ) } // end if(!theFace->IsQuadratic())
aMesh->SetMeshElementOnShape( newElem, aShapeId );
} // end if(!theFace->IsQuadratic())
else { // theFace is quadratic else { // theFace is quadratic
// we have to split theFace on simple triangles and one simple quadrangle // we have to split theFace on simple triangles and one simple quadrangle
int tmp = il1/2; int tmp = il1/2;
@ -8966,66 +9041,38 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace,
// n4 n6 n5 n4 // n4 n6 n5 n4
// create new elements // create new elements
int aShapeId = FindShape( theFace );
int n1,n2,n3; int n1,n2,n3;
if(nbFaceNodes==6) { // quadratic triangle if ( nbFaceNodes == 6 ) { // quadratic triangle
SMDS_MeshElement* newElem = newElems.push_back( aMesh->AddFace( nodes[3], nodes[4], nodes[5] ));
aMesh->AddFace(nodes[3],nodes[4],nodes[5]); if ( theFace->IsMediumNode(nodes[il1]) ) {
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
if(theFace->IsMediumNode(nodes[il1])) {
// create quadrangle // create quadrangle
newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[5]); newElems.push_back( aMesh->AddFace( nodes[0], nodes[1], nodes[3], nodes[5] ));
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
n1 = 1; n1 = 1;
n2 = 2; n2 = 2;
n3 = 3; n3 = 3;
} }
else { else {
// create quadrangle // create quadrangle
newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[5]); newElems.push_back( aMesh->AddFace( nodes[1], nodes[2], nodes[3], nodes[5] ));
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
n1 = 0; n1 = 0;
n2 = 1; n2 = 1;
n3 = 5; n3 = 5;
} }
} }
else { // nbFaceNodes==8 - quadratic quadrangle else { // nbFaceNodes==8 - quadratic quadrangle
SMDS_MeshElement* newElem = newElems.push_back( aMesh->AddFace( nodes[3], nodes[4], nodes[5] ));
aMesh->AddFace(nodes[3],nodes[4],nodes[5]); newElems.push_back( aMesh->AddFace( nodes[5], nodes[6], nodes[7] ));
myLastCreatedElems.Append(newElem); newElems.push_back( aMesh->AddFace( nodes[5], nodes[7], nodes[3] ));
if ( aShapeId && newElem ) if ( theFace->IsMediumNode( nodes[ il1 ])) {
aMesh->SetMeshElementOnShape( newElem, aShapeId );
newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]);
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]);
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
if(theFace->IsMediumNode(nodes[il1])) {
// create quadrangle // create quadrangle
newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[7]); newElems.push_back( aMesh->AddFace( nodes[0], nodes[1], nodes[3], nodes[7] ));
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
n1 = 1; n1 = 1;
n2 = 2; n2 = 2;
n3 = 3; n3 = 3;
} }
else { else {
// create quadrangle // create quadrangle
newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[7]); newElems.push_back( aMesh->AddFace( nodes[1], nodes[2], nodes[3], nodes[7] ));
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
n1 = 0; n1 = 0;
n2 = 1; n2 = 1;
n3 = 7; n3 = 7;
@ -9033,30 +9080,34 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace,
} }
// create needed triangles using n1,n2,n3 and inserted nodes // create needed triangles using n1,n2,n3 and inserted nodes
int nbn = 2 + aNodesToInsert.size(); int nbn = 2 + aNodesToInsert.size();
//const SMDS_MeshNode* aNodes[nbn];
vector<const SMDS_MeshNode*> aNodes(nbn); vector<const SMDS_MeshNode*> aNodes(nbn);
aNodes[0] = nodes[n1]; aNodes[0 ] = nodes[n1];
aNodes[nbn-1] = nodes[n2]; aNodes[nbn-1] = nodes[n2];
list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin(); list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) { for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
aNodes[iNode++] = *nIt; aNodes[iNode++] = *nIt;
} }
for(i=1; i<nbn; i++) { for ( i = 1; i < nbn; i++ )
SMDS_MeshElement* newElem = newElems.push_back( aMesh->AddFace( aNodes[i-1], aNodes[i], nodes[n3] ));
aMesh->AddFace(aNodes[i-1],aNodes[i],nodes[n3]);
myLastCreatedElems.Append(newElem);
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
}
} }
// remove old face
// remove the old face
for ( size_t i = 0; i < newElems.size(); ++i )
if ( newElems[i] )
{
aMesh->SetMeshElementOnShape( newElems[i], theFace->getshapeId() );
myLastCreatedElems.Append( newElems[i] );
}
ReplaceElemInGroups( theFace, newElems, aMesh );
aMesh->RemoveElement(theFace); aMesh->RemoveElement(theFace);
}
} // InsertNodesIntoLink()
//======================================================================= //=======================================================================
//function : UpdateVolumes //function : UpdateVolumes
//purpose : //purpose :
//======================================================================= //=======================================================================
void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode1, void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode1,
const SMDS_MeshNode* theBetweenNode2, const SMDS_MeshNode* theBetweenNode2,
list<const SMDS_MeshNode*>& theNodesToInsert) list<const SMDS_MeshNode*>& theNodesToInsert)
@ -9118,24 +9169,16 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode
quantities[iface] = nbFaceNodes + nbInserted; quantities[iface] = nbFaceNodes + nbInserted;
} }
// Replace or update the volume // Replace the volume
SMESHDS_Mesh *aMesh = GetMeshDS(); SMESHDS_Mesh *aMesh = GetMeshDS();
if (elem->IsPoly()) { if ( SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities ))
aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); {
aMesh->SetMeshElementOnShape( newElem, elem->getshapeId() );
} myLastCreatedElems.Append( newElem );
else { ReplaceElemInGroups( elem, newElem, aMesh );
int aShapeId = FindShape( elem );
SMDS_MeshElement* newElem =
aMesh->AddPolyhedralVolume(poly_nodes, quantities);
myLastCreatedElems.Append(newElem);
if (aShapeId && newElem)
aMesh->SetMeshElementOnShape(newElem, aShapeId);
aMesh->RemoveElement(elem);
} }
aMesh->RemoveElement( elem );
} }
} }

View File

@ -965,7 +965,7 @@ void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
if ( elt->getshapeId() > 0 ) if ( elt->getshapeId() > 0 )
subMesh = MeshElements( elt->getshapeId() ); subMesh = MeshElements( elt->getshapeId() );
RemoveFreeElement( elt, subMesh, true); RemoveFreeElement( elt, subMesh, true );
return; return;
} }
@ -974,7 +974,7 @@ void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
list<const SMDS_MeshElement *> removedElems; list<const SMDS_MeshElement *> removedElems;
list<const SMDS_MeshElement *> removedNodes; list<const SMDS_MeshElement *> removedNodes;
SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes, false); SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes, false );
removeFromContainers( this, myGroups, removedElems, false ); removeFromContainers( this, myGroups, removedElems, false );
} }
@ -1000,7 +1000,7 @@ void SMESHDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elt,
myScript->RemoveElement(elt->GetID()); myScript->RemoveElement(elt->GetID());
// Rm from group // Rm from group
// Node can belong to several groups // Element can belong to several groups
if ( fromGroups && !myGroups.empty() ) { if ( fromGroups && !myGroups.empty() ) {
set<SMESHDS_GroupBase*>::iterator GrIt = myGroups.begin(); set<SMESHDS_GroupBase*>::iterator GrIt = myGroups.begin();
for (; GrIt != myGroups.end(); GrIt++) { for (; GrIt != myGroups.end(); GrIt++) {
@ -1012,10 +1012,12 @@ void SMESHDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elt,
// Rm from sub-mesh // Rm from sub-mesh
// Element should belong to only one sub-mesh // Element should belong to only one sub-mesh
if( subMesh ) if ( !subMesh && elt->getshapeId() > 0 )
subMesh->RemoveElement(elt, /*deleted=*/false); subMesh = MeshElements( elt->getshapeId() );
if ( subMesh )
subMesh->RemoveElement( elt, /*deleted=*/false );
SMDS_Mesh::RemoveFreeElement(elt); SMDS_Mesh::RemoveFreeElement( elt );
} }
//================================================================================ //================================================================================

View File

@ -2571,7 +2571,7 @@ void SMESHGUI_GroupDlg::setDefaultGroupColor()
// function : SetAppropriateActor() // function : SetAppropriateActor()
// purpose : Find more appropriate of visible actors, set it to myActor, allow picking // purpose : Find more appropriate of visible actors, set it to myActor, allow picking
// NPAL19389: create a group with a selection in another group. // NPAL19389: create a group with a selection in another group.
// if mesh actor is not visible - find any first visible group or submesh // if mesh actor is not visible - find any first visible group or sub-mesh
//================================================================================= //=================================================================================
bool SMESHGUI_GroupDlg::SetAppropriateActor() bool SMESHGUI_GroupDlg::SetAppropriateActor()
{ {
@ -2582,21 +2582,23 @@ bool SMESHGUI_GroupDlg::SetAppropriateActor()
SVTK_ViewWindow* aViewWindow = SMESH::GetCurrentVtkView(); SVTK_ViewWindow* aViewWindow = SMESH::GetCurrentVtkView();
if (myGeomGroupBtn->isChecked()) { // try current group on geometry actor if (myGrpTypeGroup->checkedId() > 0) { // try current group on geometry actor
if (!isActor) { SMESH_Actor* anActor = 0;
if (!myGroupOnGeom->_is_nil()) { if (!myGroupOnGeom->_is_nil())
SMESH_Actor* anActor = SMESH::FindActorByObject(myGroupOnGeom); anActor = SMESH::FindActorByObject(myGroupOnGeom);
if (anActor && anActor->hasIO()) if (!myGroupOnFilter->_is_nil())
{ anActor = SMESH::FindActorByObject(myGroupOnFilter);
isActor = true; if (anActor && anActor->hasIO())
if (aViewWindow && !aViewWindow->isVisible(anActor->getIO())) {
isActor = false; isActor = true;
else if (aViewWindow && !aViewWindow->isVisible(anActor->getIO()))
myActorsList.append(anActor); isActor = false;
} else
} myActorsList.append(anActor);
} }
} else { return anActor;
}
else {
// try mesh actor // try mesh actor
SMESH_Actor* anActor = SMESH::FindActorByObject(myMesh); SMESH_Actor* anActor = SMESH::FindActorByObject(myMesh);
if (anActor && anActor->hasIO()) { if (anActor && anActor->hasIO()) {
@ -2606,42 +2608,50 @@ bool SMESHGUI_GroupDlg::SetAppropriateActor()
else else
myActorsList.append(anActor); myActorsList.append(anActor);
} }
// try group actor // try group actor
SMESH_Actor* aGroupActor = 0;
if (!isActor && !myGroup->_is_nil()) { if (!isActor && !myGroup->_is_nil()) {
SMESH_Actor* anActor = SMESH::FindActorByObject(myGroup); aGroupActor = SMESH::FindActorByObject(myGroup);
if (anActor && anActor->hasIO()) if (aGroupActor && aGroupActor->hasIO())
myActorsList.append(anActor); myActorsList.append(aGroupActor);
} }
// try any visible actor of group or submesh of current mesh // try any visible actor of group or sub-mesh of current mesh
if (aViewWindow) { if (aViewWindow) {
// mesh entry // mesh entry
_PTR(SObject) aSObject = SMESH::FindSObject(myMesh); _PTR(SObject) aSObject = SMESH::FindSObject(myMesh);
if (aSObject) { if (aSObject) {
CORBA::String_var meshEntry = aSObject->GetID().c_str(); CORBA::String_var meshEntry = aSObject->GetID().c_str();
int len = strlen(meshEntry); int len = strlen(meshEntry);
// iterate on all actors in current view window, search for // iterate on all actors in current view window, search for
// any visible actor, that belongs to group or submesh of current mesh // any visible actor, that belongs to group or submesh of current mesh
VTK::ActorCollectionCopy aCopy(aViewWindow->getRenderer()->GetActors()); VTK::ActorCollectionCopy aCopy(aViewWindow->getRenderer()->GetActors());
vtkActorCollection *aCollection = aCopy.GetActors(); vtkActorCollection *aCollection = aCopy.GetActors();
int nbItems = aCollection->GetNumberOfItems(); int nbItems = aCollection->GetNumberOfItems();
for (int i=0; i<nbItems && !isActor; i++) for (int i=0; i<nbItems && !isActor; i++)
{ {
SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(aCollection->GetItemAsObject(i)); SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(aCollection->GetItemAsObject(i));
if (anActor && anActor->hasIO()) { if (anActor && anActor->hasIO()) {
Handle(SALOME_InteractiveObject) anIO = anActor->getIO(); Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
if (aViewWindow->isVisible(anIO)) { if (aViewWindow->isVisible(anIO)) {
if (anIO->hasEntry() && strncmp(anIO->getEntry(), meshEntry, len) == 0 && !myActorsList.contains(anActor) ) if (anIO->hasEntry() && strncmp(anIO->getEntry(), meshEntry, len) == 0 && !myActorsList.contains(anActor) )
myActorsList.append(anActor); myActorsList.append(anActor);
}
} }
} }
}
} }
} }
// Show a standalone group if nothing else is visible (IPAL52227)
if ( myActorsList.count() == 1 &&
myActorsList[0] == aGroupActor &&
aViewWindow && !aViewWindow->isVisible(aGroupActor->getIO()))
SMESH::UpdateView( aViewWindow, SMESH::eDisplay, aGroupActor->getIO()->getEntry() );
} }
if (myActorsList.count() > 0) { if (myActorsList.count() > 0) {
QListIterator<SMESH_Actor*> it( myActorsList ); QListIterator<SMESH_Actor*> it( myActorsList );
while ( it.hasNext() ) { while ( it.hasNext() ) {
@ -2650,10 +2660,10 @@ bool SMESHGUI_GroupDlg::SetAppropriateActor()
anActor->SetPickable(true); anActor->SetPickable(true);
} }
} }
return ( isActor || (myActorsList.count() > 0) ); return ( isActor || (myActorsList.count() > 0) );
} }
//======================================================================= //=======================================================================
//function : setShowEntityMode //function : setShowEntityMode
//purpose : make shown only entity corresponding to my type //purpose : make shown only entity corresponding to my type

View File

@ -236,6 +236,10 @@ void SMESHGUI_RemoveElementsDlg::ClickOnApply()
try { try {
SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
aResult = aMeshEditor->RemoveElements(anArrayOfIdeces.in()); aResult = aMeshEditor->RemoveElements(anArrayOfIdeces.in());
if ( myActor && myMesh->NbElements() == 0 )
myActor->SetRepresentation(SMESH_Actor::ePoint);
} catch (const SALOME::SALOME_Exception& S_ex) { } catch (const SALOME::SALOME_Exception& S_ex) {
SalomeApp_Tools::QtCatchCorbaException(S_ex); SalomeApp_Tools::QtCatchCorbaException(S_ex);
myEditCurrentArgument->clear(); myEditCurrentArgument->clear();

View File

@ -235,7 +235,7 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
elif status == HYP_BAD_SUBSHAPE : elif status == HYP_BAD_SUBSHAPE :
reason = "the shape is neither the main one, nor its sub-shape, nor a valid group" reason = "the shape is neither the main one, nor its sub-shape, nor a valid group"
elif status == HYP_BAD_GEOMETRY: elif status == HYP_BAD_GEOMETRY:
reason = "geometry mismatches the expectation of the algorithm" reason = "the algorithm is not applicable to this geometry"
elif status == HYP_HIDDEN_ALGO: elif status == HYP_HIDDEN_ALGO:
reason = "it is hidden by an algorithm of an upper dimension, which generates elements of all dimensions" reason = "it is hidden by an algorithm of an upper dimension, which generates elements of all dimensions"
elif status == HYP_HIDING_ALGO: elif status == HYP_HIDING_ALGO:
@ -929,7 +929,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
## Creates a numerical functor by its type ## Creates a numerical functor by its type
# @param theCriterion functor type - an item of SMESH.FunctorType enumeration. # @param theCriterion functor type - an item of SMESH.FunctorType enumeration.
# Type SMESH.FunctorType._items in the Python Console to see all items. # Type SMESH.FunctorType._items in the Python Console to see all items.
# Note that not all items corresponds to numerical functors. # Note that not all items correspond to numerical functors.
# @return SMESH_NumericalFunctor # @return SMESH_NumericalFunctor
# @ingroup l1_controls # @ingroup l1_controls
def GetFunctor(self,theCriterion): def GetFunctor(self,theCriterion):
@ -3172,9 +3172,9 @@ class Mesh:
## Fuses the neighbouring triangles into quadrangles. ## Fuses the neighbouring triangles into quadrangles.
# @param IDsOfElements The triangles to be fused. # @param IDsOfElements The triangles to be fused.
# @param theCriterion a numerical functor, in terms of enum SMESH.FunctorType, used to # @param theCriterion a numerical functor, in terms of enum SMESH.FunctorType, used to
# choose a neighbour to fuse with. # applied to possible quadrangles to choose a neighbour to fuse with.
# Type SMESH.FunctorType._items in the Python Console to see all items. # Type SMESH.FunctorType._items in the Python Console to see all items.
# Note that not all items corresponds to numerical functors. # Note that not all items correspond to numerical functors.
# @param MaxAngle is the maximum angle between element normals at which the fusion # @param MaxAngle is the maximum angle between element normals at which the fusion
# is still performed; theMaxAngle is mesured in radians. # is still performed; theMaxAngle is mesured in radians.
# Also it could be a name of variable which defines angle in degrees. # Also it could be a name of variable which defines angle in degrees.
@ -3190,10 +3190,10 @@ class Mesh:
## Fuses the neighbouring triangles of the object into quadrangles ## Fuses the neighbouring triangles of the object into quadrangles
# @param theObject is mesh, submesh or group # @param theObject is mesh, submesh or group
# @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to # @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType,
# choose a neighbour to fuse with. # applied to possible quadrangles to choose a neighbour to fuse with.
# Type SMESH.FunctorType._items in the Python Console to see all items. # Type SMESH.FunctorType._items in the Python Console to see all items.
# Note that not all items corresponds to numerical functors. # Note that not all items correspond to numerical functors.
# @param MaxAngle a max angle between element normals at which the fusion # @param MaxAngle a max angle between element normals at which the fusion
# is still performed; theMaxAngle is mesured in radians. # is still performed; theMaxAngle is mesured in radians.
# @return TRUE in case of success, FALSE otherwise. # @return TRUE in case of success, FALSE otherwise.
@ -3208,11 +3208,11 @@ class Mesh:
## Splits quadrangles into triangles. ## Splits quadrangles into triangles.
# @param IDsOfElements the faces to be splitted. # @param IDsOfElements the faces to be splitted.
# @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to # @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
# choose a diagonal for splitting. If @a theCriterion is None, which is a default # choose a diagonal for splitting. If @a theCriterion is None, which is a default
# value, then quadrangles will be split by the smallest diagonal. # value, then quadrangles will be split by the smallest diagonal.
# Type SMESH.FunctorType._items in the Python Console to see all items. # Type SMESH.FunctorType._items in the Python Console to see all items.
# Note that not all items corresponds to numerical functors. # Note that not all items correspond to numerical functors.
# @return TRUE in case of success, FALSE otherwise. # @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_cutquadr # @ingroup l2_modif_cutquadr
def QuadToTri (self, IDsOfElements, theCriterion = None): def QuadToTri (self, IDsOfElements, theCriterion = None):
@ -3230,7 +3230,7 @@ class Mesh:
# choose a diagonal for splitting. If @a theCriterion is None, which is a default # choose a diagonal for splitting. If @a theCriterion is None, which is a default
# value, then quadrangles will be split by the smallest diagonal. # value, then quadrangles will be split by the smallest diagonal.
# Type SMESH.FunctorType._items in the Python Console to see all items. # Type SMESH.FunctorType._items in the Python Console to see all items.
# Note that not all items corresponds to numerical functors. # Note that not all items correspond to numerical functors.
# @return TRUE in case of success, FALSE otherwise. # @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_cutquadr # @ingroup l2_modif_cutquadr
def QuadToTriObject (self, theObject, theCriterion = None): def QuadToTriObject (self, theObject, theCriterion = None):
@ -3283,7 +3283,7 @@ class Mesh:
# @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to # @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
# choose a diagonal for splitting. # choose a diagonal for splitting.
# Type SMESH.FunctorType._items in the Python Console to see all items. # Type SMESH.FunctorType._items in the Python Console to see all items.
# Note that not all items corresponds to numerical functors. # Note that not all items correspond to numerical functors.
# @return 1 if 1-3 diagonal is better, 2 if 2-4 # @return 1 if 1-3 diagonal is better, 2 if 2-4
# diagonal is better, 0 if error occurs. # diagonal is better, 0 if error occurs.
# @ingroup l2_modif_cutquadr # @ingroup l2_modif_cutquadr

View File

@ -75,10 +75,12 @@ StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int hypId,
_compatibleHypothesis.push_back("LayerDistribution2D"); _compatibleHypothesis.push_back("LayerDistribution2D");
_compatibleHypothesis.push_back("NumberOfLayers2D"); _compatibleHypothesis.push_back("NumberOfLayers2D");
myNbLayerHypo = 0;
myDistributionHypo = 0;
_requireDiscreteBoundary = false; _requireDiscreteBoundary = false;
_supportSubmeshes = true; _supportSubmeshes = true;
_neededLowerHyps[ 1 ] = true; // suppress warning on hiding a global 1D algo
myNbLayerHypo = 0;
myDistributionHypo = 0;
} }
@ -278,6 +280,38 @@ namespace
} }
return nbe; return nbe;
} }
//================================================================================
/*!
* \brief Checks if the common vertex between LinEdge's lies inside the circle
* and not outside
* \param [in] CircEdge -
* \param [in] LinEdge1 -
* \param [in] LinEdge2 -
* \return bool - false if there are 3 EDGEs and the corner is outside
*/
//================================================================================
bool isCornerInsideCircle(const TopoDS_Edge& CircEdge,
const TopoDS_Edge& LinEdge1,
const TopoDS_Edge& LinEdge2)
{
if ( !CircEdge.IsNull() &&
!LinEdge1.IsNull() &&
!LinEdge2.IsNull() )
{
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
TopoDS_Vertex aCommonV;
if ( !aCirc.IsNull() &&
TopExp::CommonVertex( LinEdge1, LinEdge2, aCommonV ))
{
gp_Pnt aCommonP = BRep_Tool::Pnt( aCommonV );
gp_Pnt aCenter = aCirc->Location();
double dist = aCenter.Distance( aCommonP );
return dist < 0.1 * aCirc->Radius();
}
}
return true;
}
//================================================================================ //================================================================================
//================================================================================ //================================================================================
@ -669,15 +703,17 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh,
// segments of line // segments of line
double fp, lp; double fp, lp;
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge )); Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 )); Handle(Geom_Line) aLine1 = Handle(Geom_Line )::DownCast( getCurve( LinEdge1 ));
Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 )); Handle(Geom_Line) aLine2 = Handle(Geom_Line )::DownCast( getCurve( LinEdge2 ));
if( aCirc.IsNull() || aLine1.IsNull() || aLine2.IsNull() ) if ( aCirc.IsNull() || aLine1.IsNull() || aLine2.IsNull() )
return error(COMPERR_BAD_SHAPE);
if ( !isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ))
return error(COMPERR_BAD_SHAPE); return error(COMPERR_BAD_SHAPE);
if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge )) if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
return error( algo1d->GetComputeError() ); return error( algo1d->GetComputeError() );
map< double, const SMDS_MeshNode* > theNodes; map< double, const SMDS_MeshNode* > theNodes;
if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes)) if ( !GetSortedNodesOnEdge( aMesh.GetMeshDS(), CircEdge, true, theNodes ))
return error("Circular edge is incorrectly meshed"); return error("Circular edge is incorrectly meshed");
myHelper->IsQuadraticSubMesh( aShape ); myHelper->IsQuadraticSubMesh( aShape );
@ -1290,18 +1326,20 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
//================================================================================ //================================================================================
/*! /*!
* \brief Return true if applied compute mesh on this shape * \brief Return true if the algorithm can compute mesh on this shape
*/ */
//================================================================================ //================================================================================
bool StdMeshers_RadialQuadrangle_1D2D::IsApplicable( const TopoDS_Shape & aShape, bool toCheckAll ) bool StdMeshers_RadialQuadrangle_1D2D::IsApplicable( const TopoDS_Shape & aShape, bool toCheckAll )
{ {
int nbFoundFaces = 0; int nbFoundFaces = 0;
for (TopExp_Explorer exp( aShape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFoundFaces ){ for (TopExp_Explorer exp( aShape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFoundFaces )
{
TopoDS_Edge CircEdge, LinEdge1, LinEdge2; TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
int nbe = analyseFace( exp.Current(), CircEdge, LinEdge1, LinEdge2 ); int nbe = analyseFace( exp.Current(), CircEdge, LinEdge1, LinEdge2 );
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge )); Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
bool ok = ( nbe <= 3 && nbe >= 1 && !aCirc.IsNull() ); bool ok = ( nbe <= 3 && nbe >= 1 && !aCirc.IsNull() &&
isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ));
if( toCheckAll && !ok ) return false; if( toCheckAll && !ok ) return false;
if( !toCheckAll && ok ) return true; if( !toCheckAll && ok ) return true;
} }

View File

@ -288,7 +288,9 @@ void StdMeshersGUI_SubShapeSelectorWdg::selectionIntoArgument()
} }
} }
} }
} else if ( aGeomObj->GetType() == 28 /*GEOM_SUBSHAPE*/ ) { } else if ( aGeomObj->GetType() == 28 /*GEOM_SUBSHAPE*/ ||
myEntry == IO->getEntry() )
{
GEOMBase::GetShape(aGeomObj, shape); GEOMBase::GetShape(aGeomObj, shape);
if ( !shape.IsNull() && shape.ShapeType() == mySubShType ) { if ( !shape.IsNull() && shape.ShapeType() == mySubShType ) {
int index = myPreviewActor->GetIndexByShape( shape ); int index = myPreviewActor->GetIndexByShape( shape );
@ -530,9 +532,6 @@ SMESH::long_array_var StdMeshersGUI_SubShapeSelectorWdg::GetListOfIDs()
{ {
SMESH::long_array_var anArray = new SMESH::long_array; SMESH::long_array_var anArray = new SMESH::long_array;
// if ( myMainEntry != "" && myIsNotCorrected )
// myListOfIDs = GetCorrectedListOfIDs( true );
int size = myListOfIDs.size(); int size = myListOfIDs.size();
anArray->length( size ); anArray->length( size );
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
@ -575,17 +574,6 @@ bool StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theI
return isOk; return isOk;
} }
//=================================================================================
// function : SetMainShapeEntry
// purpose : Called to set the Entry of main shape of the mesh
//=================================================================================
// void StdMeshersGUI_SubShapeSelectorWdg::SetMainShapeEntry( const QString& theEntry )
// {
// myMainEntry = theEntry;
// myMainShape = GetTopoDSByEntry( theEntry );
// myIsNotCorrected = true;
// }
//================================================================================= //=================================================================================
// function : GetMainShapeEntry // function : GetMainShapeEntry
// purpose : Called to get the Main Object Entry // purpose : Called to get the Main Object Entry
@ -596,82 +584,6 @@ const char* StdMeshersGUI_SubShapeSelectorWdg::GetMainShapeEntry()
return myMainEntry.c_str(); return myMainEntry.c_str();
} }
//=================================================================================
// function : GetCorrectedListOfIds
// purpose : Called to convert the list of IDs from sub-shape IDs to main shape IDs
//=================================================================================
// QList<int>
// StdMeshersGUI_SubShapeSelectorWdg::GetCorrectedListOfIDs( bool fromSubshapeToMainshape,
// bool* isOK )
// {
// if (( myMainShape.IsNull() || myGeomShape.IsNull() ) && fromSubshapeToMainshape )
// return myListOfIDs;
// else if (( myMainShape.IsNull() /*||*/&& myGeomShape.IsNull() ) && !fromSubshapeToMainshape )
// return mySelectedIDs;
// if ( !fromSubshapeToMainshape ) // called from SetListOfIDs
// {
// if ( myMainShape.IsNull() )
// std::swap( myMainShape, myGeomShape );
// }
// QList<int> aList;
// TopTools_IndexedMapOfShape aGeomMap, aMainMap;
// TopExp::MapShapes(myMainShape, aMainMap);
// if ( !myGeomShape.IsNull() )
// TopExp::MapShapes(myGeomShape, aGeomMap);
// bool ok = true;
// if ( fromSubshapeToMainshape ) // convert indexes from sub-shape to mainshape
// {
// int size = myListOfIDs.size();
// for (int i = 0; i < size; i++) {
// int index = myListOfIDs.at(i);
// if ( aGeomMap.Extent() < index )
// {
// ok = false;
// }
// else
// {
// TopoDS_Shape aSubShape = aGeomMap.FindKey( index );
// if ( mySubShType != aSubShape.ShapeType() )
// ok = false;
// if ( !aMainMap.Contains( aSubShape ))
// ok = false;
// else
// index = aMainMap.FindIndex( aSubShape );
// }
// aList.append( index );
// }
// myIsNotCorrected = false;
// }
// else // convert indexes from main shape to sub-shape, or just check indices
// {
// int size = mySelectedIDs.size();
// for (int i = 0; i < size; i++) {
// int index = mySelectedIDs.at(i);
// if ( aMainMap.Extent() < index )
// {
// ok = false;
// }
// else
// {
// TopoDS_Shape aSubShape = aMainMap.FindKey( index );
// if ( mySubShType != aSubShape.ShapeType() )
// ok = false;
// if ( !aGeomMap.Contains( aSubShape ) && !aGeomMap.IsEmpty() )
// ok = false;
// else
// index = aGeomMap.FindIndex( aSubShape );
// }
// aList.append( index );
// }
// }
// if ( isOK ) *isOK = ok;
// return aList;
// }
void StdMeshersGUI_SubShapeSelectorWdg::updateButtons() void StdMeshersGUI_SubShapeSelectorWdg::updateButtons()
{ {
if ( myPreviewActor ) { if ( myPreviewActor ) {