X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FControls%2FSMESH_Controls.cxx;h=1adabb5c6f0dba5560eacd473848fa413d1affaf;hp=fce25f698618e8c45cd0dd472e5a40a4f7aae876;hb=f016bdf914220827ec8f9a7048bc78fc3fb8c299;hpb=54580d9a2a716c32a6d7772a3545811d9538cb96 diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index fce25f698..1adabb5c6 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2021 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 @@ -34,6 +34,7 @@ #include "SMESHDS_Mesh.hxx" #include "SMESH_MeshAlgos.hxx" #include "SMESH_OctreeNode.hxx" +#include "SMESH_Comment.hxx" #include #include @@ -127,7 +128,7 @@ namespace { return aDist; } - int getNbMultiConnection( const SMDS_Mesh* theMesh, const int theId ) + int getNbMultiConnection( const SMDS_Mesh* theMesh, const smIdType theId ) { if ( theMesh == 0 ) return 0; @@ -225,7 +226,7 @@ void NumericalFunctor::SetMesh( const SMDS_Mesh* theMesh ) myMesh = theMesh; } -bool NumericalFunctor::GetPoints(const int theId, +bool NumericalFunctor::GetPoints(const smIdType theId, TSequenceOfXYZ& theRes ) const { theRes.clear(); @@ -322,12 +323,12 @@ bool NumericalFunctor::IsApplicable( long theElementId ) const */ //================================================================================ -void NumericalFunctor::GetHistogram(int nbIntervals, - std::vector& nbEvents, - std::vector& funValues, - const std::vector& elements, - const double* minmax, - const bool isLogarithmic) +void NumericalFunctor::GetHistogram(int nbIntervals, + std::vector& nbEvents, + std::vector& funValues, + const std::vector& elements, + const double* minmax, + const bool isLogarithmic) { if ( nbIntervals < 1 || !myMesh || @@ -346,7 +347,7 @@ void NumericalFunctor::GetHistogram(int nbIntervals, } else { - std::vector::const_iterator id = elements.begin(); + std::vector::const_iterator id = elements.begin(); for ( ; id != elements.end(); ++id ) values.insert( GetValue( *id )); } @@ -997,6 +998,102 @@ namespace{ return aHeight; } + //================================================================================ + /*! + * \brief Standard quality of a tetrahedron but not normalized + */ + //================================================================================ + + double tetQualityByHomardMethod( const gp_XYZ & p1, + const gp_XYZ & p2, + const gp_XYZ & p3, + const gp_XYZ & p4 ) + { + gp_XYZ edgeVec[6]; + edgeVec[0] = ( p1 - p2 ); + edgeVec[1] = ( p2 - p3 ); + edgeVec[2] = ( p3 - p1 ); + edgeVec[3] = ( p4 - p1 ); + edgeVec[4] = ( p4 - p2 ); + edgeVec[5] = ( p4 - p3 ); + + double maxEdgeLen2 = edgeVec[0].SquareModulus(); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[1].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[2].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[3].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[4].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[5].SquareModulus() ); + double maxEdgeLen = Sqrt( maxEdgeLen2 ); + + gp_XYZ cross01 = edgeVec[0] ^ edgeVec[1]; + double sumArea = ( cross01 ).Modulus(); // actually double area + sumArea += ( edgeVec[0] ^ edgeVec[3] ).Modulus(); + sumArea += ( edgeVec[1] ^ edgeVec[4] ).Modulus(); + sumArea += ( edgeVec[2] ^ edgeVec[5] ).Modulus(); + + double sixVolume = Abs( cross01 * edgeVec[4] ); // 6 * volume + double quality = maxEdgeLen * sumArea / sixVolume; // not normalized!!! + return quality; + } + + //================================================================================ + /*! + * \brief HOMARD method of hexahedron quality + * 1. Decompose the hexa into 24 tetra: each face is splitted into 4 triangles by + * adding the diagonals and every triangle is connected to the center of the hexa. + * 2. Compute the quality of every tetra with the same formula as for the standard quality, + * except that the factor for the normalization is not the same because the final goal + * is to have a quality equal to 1 for a perfect cube. So the formula is: + * qual = max(lengthes of 6 edges) * (sum of surfaces of 4 faces) / (7.6569*6*volume) + * 3. The quality of the hexa is the highest value of the qualities of the 24 tetra + */ + //================================================================================ + + double hexQualityByHomardMethod( const TSequenceOfXYZ& P ) + { + gp_XYZ quadCenter[6]; + quadCenter[0] = ( P(1) + P(2) + P(3) + P(4) ) / 4.; + quadCenter[1] = ( P(5) + P(6) + P(7) + P(8) ) / 4.; + quadCenter[2] = ( P(1) + P(2) + P(6) + P(5) ) / 4.; + quadCenter[3] = ( P(2) + P(3) + P(7) + P(6) ) / 4.; + quadCenter[4] = ( P(3) + P(4) + P(8) + P(7) ) / 4.; + quadCenter[5] = ( P(1) + P(4) + P(8) + P(5) ) / 4.; + + gp_XYZ hexCenter = ( P(1) + P(2) + P(3) + P(4) + P(5) + P(6) + P(7) + P(8) ) / 8.; + + // quad 1 ( 1 2 3 4 ) + double quality = tetQualityByHomardMethod( P(1), P(2), quadCenter[0], hexCenter ); + quality = Max( quality, tetQualityByHomardMethod( P(2), P(3), quadCenter[0], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(3), P(4), quadCenter[0], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(4), P(1), quadCenter[0], hexCenter )); + // quad 2 ( 5 6 7 8 ) + quality = Max( quality, tetQualityByHomardMethod( P(5), P(6), quadCenter[1], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(6), P(7), quadCenter[1], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(7), P(8), quadCenter[1], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(8), P(5), quadCenter[1], hexCenter )); + // quad 3 ( 1 2 6 5 ) + quality = Max( quality, tetQualityByHomardMethod( P(1), P(2), quadCenter[2], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(2), P(6), quadCenter[2], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(6), P(5), quadCenter[2], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(5), P(1), quadCenter[2], hexCenter )); + // quad 4 ( 2 3 7 6 ) + quality = Max( quality, tetQualityByHomardMethod( P(2), P(3), quadCenter[3], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(3), P(7), quadCenter[3], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(7), P(6), quadCenter[3], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(6), P(2), quadCenter[3], hexCenter )); + // quad 5 ( 3 4 8 7 ) + quality = Max( quality, tetQualityByHomardMethod( P(3), P(4), quadCenter[4], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(4), P(8), quadCenter[4], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(8), P(7), quadCenter[4], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(7), P(3), quadCenter[4], hexCenter )); + // quad 6 ( 1 4 8 5 ) + quality = Max( quality, tetQualityByHomardMethod( P(1), P(4), quadCenter[5], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(4), P(8), quadCenter[5], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(8), P(5), quadCenter[5], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(5), P(1), quadCenter[5], hexCenter )); + + return quality / 7.65685424949; + } } double AspectRatio3D::GetValue( long theId ) @@ -1126,6 +1223,10 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P ) break; } case 8:{ + + return hexQualityByHomardMethod( P ); // bos #23982 + + { gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 3 )}; aQuality = GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])); @@ -1871,7 +1972,7 @@ void Length2D::GetValues(TValues& theValues) { // use special nodes iterator SMDS_NodeIteratorPtr anIter = anElem->interlacedNodesIterator(); - long aNodeId[4] = { 0,0,0,0 }; + smIdType aNodeId[4] = { 0,0,0,0 }; gp_Pnt P[4]; double aLength = 0; @@ -1908,7 +2009,7 @@ void Length2D::GetValues(TValues& theValues) } else { SMDS_NodeIteratorPtr aNodesIter = anElem->nodeIterator(); - long aNodeId[2] = {0,0}; + smIdType aNodeId[2] = {0,0}; gp_Pnt P[3]; double aLength; @@ -1923,7 +2024,7 @@ void Length2D::GetValues(TValues& theValues) for( ; aNodesIter->more(); ) { aNode = aNodesIter->next(); - long anId = aNode->GetID(); + smIdType anId = aNode->GetID(); P[2] = SMESH_NodeXYZ( aNode ); @@ -2045,7 +2146,7 @@ double Deflection2D::GetBadRate( double Value, int /*nbNodes*/ ) const */ //================================================================================ -double MultiConnection::GetValue( const TSequenceOfXYZ& P ) +double MultiConnection::GetValue( const TSequenceOfXYZ& /*P*/ ) { return 0; } @@ -2072,7 +2173,7 @@ SMDSAbs_ElementType MultiConnection::GetType() const */ //================================================================================ -double MultiConnection2D::GetValue( const TSequenceOfXYZ& P ) +double MultiConnection2D::GetValue( const TSequenceOfXYZ& /*P*/ ) { return 0; } @@ -2092,7 +2193,7 @@ double MultiConnection2D::GetValue( long theElementId ) if (!anIter) break; const SMDS_MeshNode *aNode, *aNode0 = 0; - TColStd_MapOfInteger aMap, aMapPrev; + NCollection_Map< smIdType, smIdHasher > aMap, aMapPrev; for (i = 0; i <= len; i++) { aMapPrev = aMap; @@ -2114,7 +2215,7 @@ double MultiConnection2D::GetValue( long theElementId ) while (anElemIter->more()) { const SMDS_MeshElement* anElem = anElemIter->next(); if (anElem != 0 && anElem->GetType() == SMDSAbs_Face) { - int anId = anElem->GetID(); + smIdType anId = anElem->GetID(); aMap.Add(anId); if (aMapPrev.Contains(anId)) { @@ -2575,14 +2676,14 @@ void FreeEdges::SetMesh( const SMDS_Mesh* theMesh ) myMesh = theMesh; } -bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const int theFaceId ) +bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const smIdType theFaceId ) { SMDS_ElemIteratorPtr anElemIter = theNodes[ 0 ]->GetInverseElementIterator(SMDSAbs_Face); while( anElemIter->more() ) { if ( const SMDS_MeshElement* anElem = anElemIter->next()) { - const int anId = anElem->GetID(); + const smIdType anId = anElem->GetID(); if ( anId != theFaceId && anElem->GetNodeIndex( theNodes[1] ) >= 0 ) return false; } @@ -2867,8 +2968,8 @@ void GroupColor::SetMesh( const SMDS_Mesh* theMesh ) SMDSAbs_ElementType aGrpElType = (SMDSAbs_ElementType)aGrp->GetType(); if ( myType == aGrpElType || (myType == SMDSAbs_All && aGrpElType != SMDSAbs_Node) ) { // add elements IDS into control - int aSize = aGrp->Extent(); - for (int i = 0; i < aSize; i++) + smIdType aSize = aGrp->Extent(); + for (smIdType i = 0; i < aSize; i++) myIDs.insert( aGrp->GetID(i+1) ); } } @@ -3019,7 +3120,7 @@ ConnectedElements::ConnectedElements(): SMDSAbs_ElementType ConnectedElements::GetType() const { return myType; } -int ConnectedElements::GetNode() const +smIdType ConnectedElements::GetNode() const { return myXYZ.empty() ? myNodeID : 0; } // myNodeID can be found by myXYZ std::vector ConnectedElements::GetPoint() const @@ -3046,7 +3147,7 @@ void ConnectedElements::SetMesh( const SMDS_Mesh* theMesh ) } } -void ConnectedElements::SetNode( int nodeID ) +void ConnectedElements::SetNode( smIdType nodeID ) { myNodeID = nodeID; myXYZ.clear(); @@ -3106,7 +3207,7 @@ bool ConnectedElements::IsSatisfy( long theElementId ) return false; std::list< const SMDS_MeshNode* > nodeQueue( 1, node0 ); - std::set< int > checkedNodeIDs; + std::set< smIdType > checkedNodeIDs; // algo: // foreach node in nodeQueue: // foreach element sharing a node: @@ -3131,7 +3232,7 @@ bool ConnectedElements::IsSatisfy( long theElementId ) while ( nIt->more() ) { const SMDS_MeshNode* n = static_cast< const SMDS_MeshNode* >( nIt->next() ); - if ( checkedNodeIDs.insert( n->GetID() ).second ) + if ( checkedNodeIDs.insert( n->GetID()).second ) nodeQueue.push_back( n ); } } @@ -3278,56 +3379,56 @@ void RangeOfIds::GetRangeStr( TCollection_AsciiString& theResStr ) { theResStr.Clear(); - TColStd_SequenceOfInteger anIntSeq; - TColStd_SequenceOfAsciiString aStrSeq; + TIDsSeq anIntSeq; + NCollection_Sequence< std::string > aStrSeq; - TColStd_MapIteratorOfMapOfInteger anIter( myIds ); + TIDsMap::Iterator anIter( myIds ); for ( ; anIter.More(); anIter.Next() ) { - int anId = anIter.Key(); - TCollection_AsciiString aStr( anId ); + smIdType anId = anIter.Key(); + SMESH_Comment aStr( anId ); anIntSeq.Append( anId ); aStrSeq.Append( aStr ); } - for ( int i = 1, n = myMin.Length(); i <= n; i++ ) + for ( smIdType i = 1, n = myMin.size(); i <= n; i++ ) { - int aMinId = myMin( i ); - int aMaxId = myMax( i ); + smIdType aMinId = myMin[i]; + smIdType aMaxId = myMax[i]; - TCollection_AsciiString aStr; + SMESH_Comment aStr; if ( aMinId != IntegerFirst() ) - aStr += aMinId; + aStr << aMinId; - aStr += "-"; + aStr << "-"; - if ( aMaxId != IntegerLast() ) - aStr += aMaxId; + if ( aMaxId != std::numeric_limits::max() ) + aStr << aMaxId; // find position of the string in result sequence and insert string in it if ( anIntSeq.Length() == 0 ) { anIntSeq.Append( aMinId ); - aStrSeq.Append( aStr ); + aStrSeq.Append( (const char*)aStr ); } else { if ( aMinId < anIntSeq.First() ) { anIntSeq.Prepend( aMinId ); - aStrSeq.Prepend( aStr ); + aStrSeq.Prepend( (const char*)aStr ); } else if ( aMinId > anIntSeq.Last() ) { anIntSeq.Append( aMinId ); - aStrSeq.Append( aStr ); + aStrSeq.Append( (const char*)aStr ); } else for ( int j = 1, k = anIntSeq.Length(); j <= k; j++ ) if ( aMinId < anIntSeq( j ) ) { anIntSeq.InsertBefore( j, aMinId ); - aStrSeq.InsertBefore( j, aStr ); + aStrSeq.InsertBefore( j, (const char*)aStr ); break; } } @@ -3335,13 +3436,14 @@ void RangeOfIds::GetRangeStr( TCollection_AsciiString& theResStr ) if ( aStrSeq.Length() == 0 ) return; - - theResStr = aStrSeq( 1 ); + std::string aResStr; + aResStr = aStrSeq( 1 ); for ( int j = 2, k = aStrSeq.Length(); j <= k; j++ ) { - theResStr += ","; - theResStr += aStrSeq( j ); + aResStr += ","; + aResStr += aStrSeq( j ); } + theResStr = aResStr.c_str(); } //======================================================================= @@ -3351,8 +3453,8 @@ void RangeOfIds::GetRangeStr( TCollection_AsciiString& theResStr ) //======================================================================= bool RangeOfIds::SetRangeStr( const TCollection_AsciiString& theStr ) { - myMin.Clear(); - myMax.Clear(); + myMin.clear(); + myMax.clear(); myIds.Clear(); TCollection_AsciiString aStr = theStr; @@ -3390,8 +3492,8 @@ bool RangeOfIds::SetRangeStr( const TCollection_AsciiString& theStr ) (!aMaxStr.IsEmpty() && !aMaxStr.IsIntegerValue()) ) return false; - myMin.Append( aMinStr.IsEmpty() ? IntegerFirst() : aMinStr.IntegerValue() ); - myMax.Append( aMaxStr.IsEmpty() ? IntegerLast() : aMaxStr.IntegerValue() ); + myMin.push_back( aMinStr.IsEmpty() ? IntegerFirst() : aMinStr.IntegerValue() ); + myMax.push_back( aMaxStr.IsEmpty() ? IntegerLast() : aMaxStr.IntegerValue() ); } } @@ -3440,8 +3542,8 @@ bool RangeOfIds::IsSatisfy( long theId ) if ( myIds.Contains( theId ) ) return true; - for ( int i = 1, n = myMin.Length(); i <= n; i++ ) - if ( theId >= myMin( i ) && theId <= myMax( i ) ) + for ( size_t i = 0; i < myMin.size(); i++ ) + if ( theId >= myMin[i] && theId <= myMax[i] ) return true; return false; @@ -3817,7 +3919,7 @@ bool ManifoldPart::process() // the map of non manifold links and bad geometry TMapOfLink aMapOfNonManifold; - TColStd_MapOfInteger aMapOfTreated; + TIDsMap aMapOfTreated; // begin cycle on faces from start index and run on vector till the end // and from begin to start index to cover whole vector @@ -3830,18 +3932,18 @@ bool ManifoldPart::process() // as result next time when fi will be equal to aStartIndx SMDS_MeshFace* aFacePtr = myAllFacePtr[ fi ]; - if ( aMapOfTreated.Contains( aFacePtr->GetID() ) ) + if ( aMapOfTreated.Contains( aFacePtr->GetID()) ) continue; aMapOfTreated.Add( aFacePtr->GetID() ); - TColStd_MapOfInteger aResFaces; + TIDsMap aResFaces; if ( !findConnected( myAllFacePtrIntDMap, aFacePtr, aMapOfNonManifold, aResFaces ) ) continue; - TColStd_MapIteratorOfMapOfInteger anItr( aResFaces ); + TIDsMap::Iterator anItr( aResFaces ); for ( ; anItr.More(); anItr.Next() ) { - int aFaceId = anItr.Key(); + smIdType aFaceId = anItr.Key(); aMapOfTreated.Add( aFaceId ); myMapIds.Add( aFaceId ); } @@ -3877,7 +3979,7 @@ bool ManifoldPart::findConnected ( const ManifoldPart::TDataMapFacePtrInt& theAllFacePtrInt, SMDS_MeshFace* theStartFace, ManifoldPart::TMapOfLink& theNonManifold, - TColStd_MapOfInteger& theResFaces ) + TIDsMap& theResFaces ) { theResFaces.Clear(); if ( !theAllFacePtrInt.size() ) @@ -3945,7 +4047,7 @@ bool ManifoldPart::findConnected SMDS_MeshFace* aNextFace = *pFace; if ( aPrevFace == aNextFace ) continue; - int anNextFaceID = aNextFace->GetID(); + smIdType anNextFaceID = aNextFace->GetID(); if ( myIsOnlyManifold && theResFaces.Contains( anNextFaceID ) ) // should not be with non manifold restriction. probably bad topology continue; @@ -4176,7 +4278,9 @@ void ElementsOnSurface::process() if ( !myMeshModifTracer.GetMesh() ) return; - myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType )); + int nbElems = FromSmIdType( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType )); + if ( nbElems > 0 ) + myIds.ReSize( nbElems ); SMDS_ElemIteratorPtr anIter = myMeshModifTracer.GetMesh()->elementsIterator( myType ); for(; anIter->more(); ) @@ -4263,7 +4367,7 @@ private: bool isOutOfFace (const gp_Pnt& p); bool isOutOfEdge (const gp_Pnt& p); bool isOutOfVertex(const gp_Pnt& p); - bool isOutOfNone (const gp_Pnt& p) { return true; } + bool isOutOfNone (const gp_Pnt& /*p*/) { return true; } bool isBox (const TopoDS_Shape& s); TopoDS_Shape prepareSolid( const TopoDS_Shape& theSolid );