00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "SMESH_ControlsDef.hxx"
00024
00025 #include <set>
00026 #include <limits>
00027
00028 #include <BRepAdaptor_Surface.hxx>
00029 #include <BRepClass_FaceClassifier.hxx>
00030 #include <BRep_Tool.hxx>
00031
00032 #include <TopAbs.hxx>
00033 #include <TopoDS.hxx>
00034 #include <TopoDS_Edge.hxx>
00035 #include <TopoDS_Face.hxx>
00036 #include <TopoDS_Shape.hxx>
00037 #include <TopoDS_Vertex.hxx>
00038 #include <TopoDS_Iterator.hxx>
00039
00040 #include <Geom_CylindricalSurface.hxx>
00041 #include <Geom_Plane.hxx>
00042 #include <Geom_Surface.hxx>
00043
00044 #include <Precision.hxx>
00045 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
00046 #include <TColStd_MapOfInteger.hxx>
00047 #include <TColStd_SequenceOfAsciiString.hxx>
00048 #include <TColgp_Array1OfXYZ.hxx>
00049
00050 #include <gp_Ax3.hxx>
00051 #include <gp_Cylinder.hxx>
00052 #include <gp_Dir.hxx>
00053 #include <gp_Pln.hxx>
00054 #include <gp_Pnt.hxx>
00055 #include <gp_Vec.hxx>
00056 #include <gp_XYZ.hxx>
00057
00058 #include "SMDS_Mesh.hxx"
00059 #include "SMDS_Iterator.hxx"
00060 #include "SMDS_MeshElement.hxx"
00061 #include "SMDS_MeshNode.hxx"
00062 #include "SMDS_VolumeTool.hxx"
00063 #include "SMDS_QuadraticFaceOfNodes.hxx"
00064 #include "SMDS_QuadraticEdge.hxx"
00065
00066 #include "SMESHDS_Mesh.hxx"
00067 #include "SMESHDS_GroupBase.hxx"
00068
00069 #include <vtkMeshQuality.h>
00070
00071
00072
00073
00074
00075 namespace{
00076
00077 inline gp_XYZ gpXYZ(const SMDS_MeshNode* aNode )
00078 {
00079 return gp_XYZ(aNode->X(), aNode->Y(), aNode->Z() );
00080 }
00081
00082 inline double getAngle( const gp_XYZ& P1, const gp_XYZ& P2, const gp_XYZ& P3 )
00083 {
00084 gp_Vec v1( P1 - P2 ), v2( P3 - P2 );
00085
00086 return v1.Magnitude() < gp::Resolution() ||
00087 v2.Magnitude() < gp::Resolution() ? 0 : v1.Angle( v2 );
00088 }
00089
00090 inline double getArea( const gp_XYZ& P1, const gp_XYZ& P2, const gp_XYZ& P3 )
00091 {
00092 gp_Vec aVec1( P2 - P1 );
00093 gp_Vec aVec2( P3 - P1 );
00094 return ( aVec1 ^ aVec2 ).Magnitude() * 0.5;
00095 }
00096
00097 inline double getArea( const gp_Pnt& P1, const gp_Pnt& P2, const gp_Pnt& P3 )
00098 {
00099 return getArea( P1.XYZ(), P2.XYZ(), P3.XYZ() );
00100 }
00101
00102
00103
00104 inline double getDistance( const gp_XYZ& P1, const gp_XYZ& P2 )
00105 {
00106 double aDist = gp_Pnt( P1 ).Distance( gp_Pnt( P2 ) );
00107 return aDist;
00108 }
00109
00110 int getNbMultiConnection( const SMDS_Mesh* theMesh, const int theId )
00111 {
00112 if ( theMesh == 0 )
00113 return 0;
00114
00115 const SMDS_MeshElement* anEdge = theMesh->FindElement( theId );
00116 if ( anEdge == 0 || anEdge->GetType() != SMDSAbs_Edge)
00117 return 0;
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 int aResult0 = 0, aResult1 = 0;
00132
00133 const SMDS_MeshNode* aLastNode = anEdge->GetNode( anEdge->NbNodes() - 1 );
00134 const SMDS_MeshNode* aNode0 = anEdge->GetNode( 0 );
00135 const SMDS_MeshNode* aNode1 = anEdge->GetNode( 1 );
00136 if ( aNode1 == aLastNode ) aNode1 = 0;
00137
00138 SMDS_ElemIteratorPtr anElemIter = aLastNode->GetInverseElementIterator();
00139 while( anElemIter->more() ) {
00140 const SMDS_MeshElement* anElem = anElemIter->next();
00141 if ( anElem != 0 && anElem->GetType() != SMDSAbs_Edge ) {
00142 SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
00143 while ( anIter->more() ) {
00144 if ( const SMDS_MeshElement* anElemNode = anIter->next() ) {
00145 if ( anElemNode == aNode0 ) {
00146 aResult0++;
00147 if ( !aNode1 ) break;
00148 }
00149 else if ( anElemNode == aNode1 )
00150 aResult1++;
00151 }
00152 }
00153 }
00154 }
00155 int aResult = std::max ( aResult0, aResult1 );
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 return aResult;
00181 }
00182
00183 gp_XYZ getNormale( const SMDS_MeshFace* theFace, bool* ok=0 )
00184 {
00185 int aNbNode = theFace->NbNodes();
00186
00187 gp_XYZ q1 = gpXYZ( theFace->GetNode(1)) - gpXYZ( theFace->GetNode(0));
00188 gp_XYZ q2 = gpXYZ( theFace->GetNode(2)) - gpXYZ( theFace->GetNode(0));
00189 gp_XYZ n = q1 ^ q2;
00190 if ( aNbNode > 3 ) {
00191 gp_XYZ q3 = gpXYZ( theFace->GetNode(3)) - gpXYZ( theFace->GetNode(0));
00192 n += q2 ^ q3;
00193 }
00194 double len = n.Modulus();
00195 bool zeroLen = ( len <= numeric_limits<double>::min());
00196 if ( !zeroLen )
00197 n /= len;
00198
00199 if (ok) *ok = !zeroLen;
00200
00201 return n;
00202 }
00203 }
00204
00205
00206
00207 using namespace SMESH::Controls;
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 NumericalFunctor::NumericalFunctor():
00218 myMesh(NULL)
00219 {
00220 myPrecision = -1;
00221 }
00222
00223 void NumericalFunctor::SetMesh( const SMDS_Mesh* theMesh )
00224 {
00225 myMesh = theMesh;
00226 }
00227
00228 bool NumericalFunctor::GetPoints(const int theId,
00229 TSequenceOfXYZ& theRes ) const
00230 {
00231 theRes.clear();
00232
00233 if ( myMesh == 0 )
00234 return false;
00235
00236 return GetPoints( myMesh->FindElement( theId ), theRes );
00237 }
00238
00239 bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem,
00240 TSequenceOfXYZ& theRes )
00241 {
00242 theRes.clear();
00243
00244 if ( anElem == 0)
00245 return false;
00246
00247 theRes.reserve( anElem->NbNodes() );
00248
00249
00250 SMDS_ElemIteratorPtr anIter;
00251
00252 if ( anElem->IsQuadratic() ) {
00253 switch ( anElem->GetType() ) {
00254 case SMDSAbs_Edge:
00255 anIter = dynamic_cast<const SMDS_VtkEdge*>
00256 (anElem)->interlacedNodesElemIterator();
00257 break;
00258 case SMDSAbs_Face:
00259 anIter = dynamic_cast<const SMDS_VtkFace*>
00260 (anElem)->interlacedNodesElemIterator();
00261 break;
00262 default:
00263 anIter = anElem->nodesIterator();
00264
00265 }
00266 }
00267 else {
00268 anIter = anElem->nodesIterator();
00269 }
00270
00271 if ( anIter ) {
00272 while( anIter->more() ) {
00273 if ( const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>( anIter->next() ))
00274 theRes.push_back( gp_XYZ( aNode->X(), aNode->Y(), aNode->Z() ) );
00275 }
00276 }
00277
00278 return true;
00279 }
00280
00281 long NumericalFunctor::GetPrecision() const
00282 {
00283 return myPrecision;
00284 }
00285
00286 void NumericalFunctor::SetPrecision( const long thePrecision )
00287 {
00288 myPrecision = thePrecision;
00289 myPrecisionValue = pow( 10., (double)( myPrecision ) );
00290 }
00291
00292 double NumericalFunctor::GetValue( long theId )
00293 {
00294 double aVal = 0;
00295
00296 myCurrElement = myMesh->FindElement( theId );
00297
00298 TSequenceOfXYZ P;
00299 if ( GetPoints( theId, P ))
00300 aVal = Round( GetValue( P ));
00301
00302 return aVal;
00303 }
00304
00305 double NumericalFunctor::Round( const double & aVal )
00306 {
00307 return ( myPrecision >= 0 ) ? floor( aVal * myPrecisionValue + 0.5 ) / myPrecisionValue : aVal;
00308 }
00309
00310
00319
00320
00321 void NumericalFunctor::GetHistogram(int nbIntervals,
00322 std::vector<int>& nbEvents,
00323 std::vector<double>& funValues,
00324 const vector<int>& elements,
00325 const double* minmax)
00326 {
00327 if ( nbIntervals < 1 ||
00328 !myMesh ||
00329 !myMesh->GetMeshInfo().NbElements( GetType() ))
00330 return;
00331 nbEvents.resize( nbIntervals, 0 );
00332 funValues.resize( nbIntervals+1 );
00333
00334
00335 std::multiset< double > values;
00336 if ( elements.empty() )
00337 {
00338 SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType());
00339 while ( elemIt->more() )
00340 values.insert( GetValue( elemIt->next()->GetID() ));
00341 }
00342 else
00343 {
00344 vector<int>::const_iterator id = elements.begin();
00345 for ( ; id != elements.end(); ++id )
00346 values.insert( GetValue( *id ));
00347 }
00348
00349 if ( minmax )
00350 {
00351 funValues[0] = minmax[0];
00352 funValues[nbIntervals] = minmax[1];
00353 }
00354 else
00355 {
00356 funValues[0] = *values.begin();
00357 funValues[nbIntervals] = *values.rbegin();
00358 }
00359
00360 if ( nbIntervals == 1 )
00361 {
00362 nbEvents[0] = values.size();
00363 return;
00364 }
00365
00366 if (funValues.front() == funValues.back())
00367 {
00368 nbEvents.resize( 1 );
00369 nbEvents[0] = values.size();
00370 funValues[1] = funValues.back();
00371 funValues.resize( 2 );
00372 }
00373
00374 std::multiset< double >::iterator min = values.begin(), max;
00375 for ( int i = 0; i < nbIntervals; ++i )
00376 {
00377
00378 double r = (i+1) / double( nbIntervals );
00379 funValues[i+1] = funValues.front() * (1-r) + funValues.back() * r;
00380
00381
00382 if ( min != values.end() && *min <= funValues[i+1] )
00383 {
00384
00385 max = values.upper_bound( funValues[i+1] );
00386 nbEvents[i] = std::distance( min, max );
00387 min = max;
00388 }
00389 }
00390
00391 nbEvents.back() += std::distance( min, values.end() );
00392 }
00393
00394
00395
00396
00397
00398
00399 double Volume::GetValue( long theElementId )
00400 {
00401 if ( theElementId && myMesh ) {
00402 SMDS_VolumeTool aVolumeTool;
00403 if ( aVolumeTool.Set( myMesh->FindElement( theElementId )))
00404 return aVolumeTool.GetSize();
00405 }
00406 return 0;
00407 }
00408
00409
00410
00411
00412
00413
00414 double Volume::GetBadRate( double Value, int ) const
00415 {
00416 return Value;
00417 }
00418
00419
00420
00421
00422
00423
00424 SMDSAbs_ElementType Volume::GetType() const
00425 {
00426 return SMDSAbs_Volume;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435 double MaxElementLength2D::GetValue( long theElementId )
00436 {
00437 TSequenceOfXYZ P;
00438 if( GetPoints( theElementId, P ) ) {
00439 double aVal = 0;
00440 const SMDS_MeshElement* aElem = myMesh->FindElement( theElementId );
00441 SMDSAbs_ElementType aType = aElem->GetType();
00442 int len = P.size();
00443 switch( aType ) {
00444 case SMDSAbs_Face:
00445 if( len == 3 ) {
00446 double L1 = getDistance(P( 1 ),P( 2 ));
00447 double L2 = getDistance(P( 2 ),P( 3 ));
00448 double L3 = getDistance(P( 3 ),P( 1 ));
00449 aVal = Max(L1,Max(L2,L3));
00450 break;
00451 }
00452 else if( len == 4 ) {
00453 double L1 = getDistance(P( 1 ),P( 2 ));
00454 double L2 = getDistance(P( 2 ),P( 3 ));
00455 double L3 = getDistance(P( 3 ),P( 4 ));
00456 double L4 = getDistance(P( 4 ),P( 1 ));
00457 double D1 = getDistance(P( 1 ),P( 3 ));
00458 double D2 = getDistance(P( 2 ),P( 4 ));
00459 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
00460 break;
00461 }
00462 else if( len == 6 ) {
00463 double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
00464 double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
00465 double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
00466 aVal = Max(L1,Max(L2,L3));
00467 break;
00468 }
00469 else if( len == 8 ) {
00470 double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
00471 double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
00472 double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
00473 double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
00474 double D1 = getDistance(P( 1 ),P( 5 ));
00475 double D2 = getDistance(P( 3 ),P( 7 ));
00476 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
00477 break;
00478 }
00479 }
00480
00481 if( myPrecision >= 0 )
00482 {
00483 double prec = pow( 10., (double)myPrecision );
00484 aVal = floor( aVal * prec + 0.5 ) / prec;
00485 }
00486 return aVal;
00487 }
00488 return 0.;
00489 }
00490
00491 double MaxElementLength2D::GetBadRate( double Value, int ) const
00492 {
00493 return Value;
00494 }
00495
00496 SMDSAbs_ElementType MaxElementLength2D::GetType() const
00497 {
00498 return SMDSAbs_Face;
00499 }
00500
00501
00502
00503
00504
00505
00506 double MaxElementLength3D::GetValue( long theElementId )
00507 {
00508 TSequenceOfXYZ P;
00509 if( GetPoints( theElementId, P ) ) {
00510 double aVal = 0;
00511 const SMDS_MeshElement* aElem = myMesh->FindElement( theElementId );
00512 SMDSAbs_ElementType aType = aElem->GetType();
00513 int len = P.size();
00514 switch( aType ) {
00515 case SMDSAbs_Volume:
00516 if( len == 4 ) {
00517 double L1 = getDistance(P( 1 ),P( 2 ));
00518 double L2 = getDistance(P( 2 ),P( 3 ));
00519 double L3 = getDistance(P( 3 ),P( 1 ));
00520 double L4 = getDistance(P( 1 ),P( 4 ));
00521 double L5 = getDistance(P( 2 ),P( 4 ));
00522 double L6 = getDistance(P( 3 ),P( 4 ));
00523 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00524 break;
00525 }
00526 else if( len == 5 ) {
00527 double L1 = getDistance(P( 1 ),P( 2 ));
00528 double L2 = getDistance(P( 2 ),P( 3 ));
00529 double L3 = getDistance(P( 3 ),P( 4 ));
00530 double L4 = getDistance(P( 4 ),P( 1 ));
00531 double L5 = getDistance(P( 1 ),P( 5 ));
00532 double L6 = getDistance(P( 2 ),P( 5 ));
00533 double L7 = getDistance(P( 3 ),P( 5 ));
00534 double L8 = getDistance(P( 4 ),P( 5 ));
00535 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00536 aVal = Max(aVal,Max(L7,L8));
00537 break;
00538 }
00539 else if( len == 6 ) {
00540 double L1 = getDistance(P( 1 ),P( 2 ));
00541 double L2 = getDistance(P( 2 ),P( 3 ));
00542 double L3 = getDistance(P( 3 ),P( 1 ));
00543 double L4 = getDistance(P( 4 ),P( 5 ));
00544 double L5 = getDistance(P( 5 ),P( 6 ));
00545 double L6 = getDistance(P( 6 ),P( 4 ));
00546 double L7 = getDistance(P( 1 ),P( 4 ));
00547 double L8 = getDistance(P( 2 ),P( 5 ));
00548 double L9 = getDistance(P( 3 ),P( 6 ));
00549 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00550 aVal = Max(aVal,Max(Max(L7,L8),L9));
00551 break;
00552 }
00553 else if( len == 8 ) {
00554 double L1 = getDistance(P( 1 ),P( 2 ));
00555 double L2 = getDistance(P( 2 ),P( 3 ));
00556 double L3 = getDistance(P( 3 ),P( 4 ));
00557 double L4 = getDistance(P( 4 ),P( 1 ));
00558 double L5 = getDistance(P( 5 ),P( 6 ));
00559 double L6 = getDistance(P( 6 ),P( 7 ));
00560 double L7 = getDistance(P( 7 ),P( 8 ));
00561 double L8 = getDistance(P( 8 ),P( 5 ));
00562 double L9 = getDistance(P( 1 ),P( 5 ));
00563 double L10= getDistance(P( 2 ),P( 6 ));
00564 double L11= getDistance(P( 3 ),P( 7 ));
00565 double L12= getDistance(P( 4 ),P( 8 ));
00566 double D1 = getDistance(P( 1 ),P( 7 ));
00567 double D2 = getDistance(P( 2 ),P( 8 ));
00568 double D3 = getDistance(P( 3 ),P( 5 ));
00569 double D4 = getDistance(P( 4 ),P( 6 ));
00570 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00571 aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
00572 aVal = Max(aVal,Max(L11,L12));
00573 aVal = Max(aVal,Max(Max(D1,D2),Max(D3,D4)));
00574 break;
00575 }
00576 else if( len == 10 ) {
00577 double L1 = getDistance(P( 1 ),P( 5 )) + getDistance(P( 5 ),P( 2 ));
00578 double L2 = getDistance(P( 2 ),P( 6 )) + getDistance(P( 6 ),P( 3 ));
00579 double L3 = getDistance(P( 3 ),P( 7 )) + getDistance(P( 7 ),P( 1 ));
00580 double L4 = getDistance(P( 1 ),P( 8 )) + getDistance(P( 8 ),P( 4 ));
00581 double L5 = getDistance(P( 2 ),P( 9 )) + getDistance(P( 9 ),P( 4 ));
00582 double L6 = getDistance(P( 3 ),P( 10 )) + getDistance(P( 10 ),P( 4 ));
00583 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00584 break;
00585 }
00586 else if( len == 13 ) {
00587 double L1 = getDistance(P( 1 ),P( 6 )) + getDistance(P( 6 ),P( 2 ));
00588 double L2 = getDistance(P( 2 ),P( 7 )) + getDistance(P( 7 ),P( 3 ));
00589 double L3 = getDistance(P( 3 ),P( 8 )) + getDistance(P( 8 ),P( 4 ));
00590 double L4 = getDistance(P( 4 ),P( 9 )) + getDistance(P( 9 ),P( 1 ));
00591 double L5 = getDistance(P( 1 ),P( 10 )) + getDistance(P( 10 ),P( 5 ));
00592 double L6 = getDistance(P( 2 ),P( 11 )) + getDistance(P( 11 ),P( 5 ));
00593 double L7 = getDistance(P( 3 ),P( 12 )) + getDistance(P( 12 ),P( 5 ));
00594 double L8 = getDistance(P( 4 ),P( 13 )) + getDistance(P( 13 ),P( 5 ));
00595 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00596 aVal = Max(aVal,Max(L7,L8));
00597 break;
00598 }
00599 else if( len == 15 ) {
00600 double L1 = getDistance(P( 1 ),P( 7 )) + getDistance(P( 7 ),P( 2 ));
00601 double L2 = getDistance(P( 2 ),P( 8 )) + getDistance(P( 8 ),P( 3 ));
00602 double L3 = getDistance(P( 3 ),P( 9 )) + getDistance(P( 9 ),P( 1 ));
00603 double L4 = getDistance(P( 4 ),P( 10 )) + getDistance(P( 10 ),P( 5 ));
00604 double L5 = getDistance(P( 5 ),P( 11 )) + getDistance(P( 11 ),P( 6 ));
00605 double L6 = getDistance(P( 6 ),P( 12 )) + getDistance(P( 12 ),P( 4 ));
00606 double L7 = getDistance(P( 1 ),P( 13 )) + getDistance(P( 13 ),P( 4 ));
00607 double L8 = getDistance(P( 2 ),P( 14 )) + getDistance(P( 14 ),P( 5 ));
00608 double L9 = getDistance(P( 3 ),P( 15 )) + getDistance(P( 15 ),P( 6 ));
00609 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00610 aVal = Max(aVal,Max(Max(L7,L8),L9));
00611 break;
00612 }
00613 else if( len == 20 ) {
00614 double L1 = getDistance(P( 1 ),P( 9 )) + getDistance(P( 9 ),P( 2 ));
00615 double L2 = getDistance(P( 2 ),P( 10 )) + getDistance(P( 10 ),P( 3 ));
00616 double L3 = getDistance(P( 3 ),P( 11 )) + getDistance(P( 11 ),P( 4 ));
00617 double L4 = getDistance(P( 4 ),P( 12 )) + getDistance(P( 12 ),P( 1 ));
00618 double L5 = getDistance(P( 5 ),P( 13 )) + getDistance(P( 13 ),P( 6 ));
00619 double L6 = getDistance(P( 6 ),P( 14 )) + getDistance(P( 14 ),P( 7 ));
00620 double L7 = getDistance(P( 7 ),P( 15 )) + getDistance(P( 15 ),P( 8 ));
00621 double L8 = getDistance(P( 8 ),P( 16 )) + getDistance(P( 16 ),P( 5 ));
00622 double L9 = getDistance(P( 1 ),P( 17 )) + getDistance(P( 17 ),P( 5 ));
00623 double L10= getDistance(P( 2 ),P( 18 )) + getDistance(P( 18 ),P( 6 ));
00624 double L11= getDistance(P( 3 ),P( 19 )) + getDistance(P( 19 ),P( 7 ));
00625 double L12= getDistance(P( 4 ),P( 20 )) + getDistance(P( 20 ),P( 8 ));
00626 double D1 = getDistance(P( 1 ),P( 7 ));
00627 double D2 = getDistance(P( 2 ),P( 8 ));
00628 double D3 = getDistance(P( 3 ),P( 5 ));
00629 double D4 = getDistance(P( 4 ),P( 6 ));
00630 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
00631 aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
00632 aVal = Max(aVal,Max(L11,L12));
00633 aVal = Max(aVal,Max(Max(D1,D2),Max(D3,D4)));
00634 break;
00635 }
00636 else if( len > 1 && aElem->IsPoly() ) {
00637
00638 for( int i = 1; i <= len; i++ ) {
00639 for( int j = 1; j <= len; j++ ) {
00640 if( j > i ) {
00641 double D = getDistance( P(i), P(j) );
00642 aVal = Max( aVal, D );
00643 }
00644 }
00645 }
00646 }
00647 }
00648
00649 if( myPrecision >= 0 )
00650 {
00651 double prec = pow( 10., (double)myPrecision );
00652 aVal = floor( aVal * prec + 0.5 ) / prec;
00653 }
00654 return aVal;
00655 }
00656 return 0.;
00657 }
00658
00659 double MaxElementLength3D::GetBadRate( double Value, int ) const
00660 {
00661 return Value;
00662 }
00663
00664 SMDSAbs_ElementType MaxElementLength3D::GetType() const
00665 {
00666 return SMDSAbs_Volume;
00667 }
00668
00669
00670
00671
00672
00673
00674
00675 double MinimumAngle::GetValue( const TSequenceOfXYZ& P )
00676 {
00677 double aMin;
00678
00679 if (P.size() <3)
00680 return 0.;
00681
00682 aMin = getAngle(P( P.size() ), P( 1 ), P( 2 ));
00683 aMin = Min(aMin,getAngle(P( P.size()-1 ), P( P.size() ), P( 1 )));
00684
00685 for (int i=2; i<P.size();i++){
00686 double A0 = getAngle( P( i-1 ), P( i ), P( i+1 ) );
00687 aMin = Min(aMin,A0);
00688 }
00689
00690 return aMin * 180.0 / PI;
00691 }
00692
00693 double MinimumAngle::GetBadRate( double Value, int nbNodes ) const
00694 {
00695
00696 const double aBestAngle = 180.0 - ( 360.0 / double(nbNodes) );
00697 return ( fabs( aBestAngle - Value ));
00698 }
00699
00700 SMDSAbs_ElementType MinimumAngle::GetType() const
00701 {
00702 return SMDSAbs_Face;
00703 }
00704
00705
00706
00707
00708
00709
00710 double AspectRatio::GetValue( const TSequenceOfXYZ& P )
00711 {
00712
00713
00714
00715
00716
00717 int nbNodes = P.size();
00718
00719 if ( nbNodes < 3 )
00720 return 0;
00721
00722
00723
00724 if ( nbNodes == 3 ) {
00725
00726 std::vector< double > aLen (nbNodes);
00727 for ( int i = 0; i < nbNodes - 1; i++ )
00728 aLen[ i ] = getDistance( P( i + 1 ), P( i + 2 ) );
00729 aLen[ nbNodes - 1 ] = getDistance( P( 1 ), P( nbNodes ) );
00730
00731
00732
00733
00734
00735
00736 const double alfa = sqrt( 3. ) / 6.;
00737 double maxLen = Max( aLen[ 0 ], Max( aLen[ 1 ], aLen[ 2 ] ) );
00738 double half_perimeter = ( aLen[0] + aLen[1] + aLen[2] ) / 2.;
00739 double anArea = getArea( P( 1 ), P( 2 ), P( 3 ) );
00740 if ( anArea <= Precision::Confusion() )
00741 return 0.;
00742 return alfa * maxLen * half_perimeter / anArea;
00743 }
00744 else if ( nbNodes == 6 ) {
00745
00746 std::vector< double > aLen (3);
00747 aLen[0] = getDistance( P(1), P(3) );
00748 aLen[1] = getDistance( P(3), P(5) );
00749 aLen[2] = getDistance( P(5), P(1) );
00750
00751
00752
00753
00754
00755
00756 const double alfa = sqrt( 3. ) / 6.;
00757 double maxLen = Max( aLen[ 0 ], Max( aLen[ 1 ], aLen[ 2 ] ) );
00758 double half_perimeter = ( aLen[0] + aLen[1] + aLen[2] ) / 2.;
00759 double anArea = getArea( P(1), P(3), P(5) );
00760 if ( anArea <= Precision::Confusion() )
00761 return 0.;
00762 return alfa * maxLen * half_perimeter / anArea;
00763 }
00764 else if( nbNodes == 4 ) {
00765
00766 std::vector< double > aLen (4);
00767 aLen[0] = getDistance( P(1), P(2) );
00768 aLen[1] = getDistance( P(2), P(3) );
00769 aLen[2] = getDistance( P(3), P(4) );
00770 aLen[3] = getDistance( P(4), P(1) );
00771
00772 std::vector< double > aDia (2);
00773 aDia[0] = getDistance( P(1), P(3) );
00774 aDia[1] = getDistance( P(2), P(4) );
00775
00776
00777 std::vector< double > anArea (4);
00778 anArea[0] = getArea( P(1), P(2), P(3) );
00779 anArea[1] = getArea( P(1), P(2), P(4) );
00780 anArea[2] = getArea( P(1), P(3), P(4) );
00781 anArea[3] = getArea( P(2), P(3), P(4) );
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 const double alpha = sqrt( 1 / 32. );
00792 double L = Max( aLen[ 0 ],
00793 Max( aLen[ 1 ],
00794 Max( aLen[ 2 ],
00795 Max( aLen[ 3 ],
00796 Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) );
00797 double C1 = sqrt( ( aLen[0] * aLen[0] +
00798 aLen[1] * aLen[1] +
00799 aLen[2] * aLen[2] +
00800 aLen[3] * aLen[3] ) / 4. );
00801 double C2 = Min( anArea[ 0 ],
00802 Min( anArea[ 1 ],
00803 Min( anArea[ 2 ], anArea[ 3 ] ) ) );
00804 if ( C2 <= Precision::Confusion() )
00805 return 0.;
00806 return alpha * L * C1 / C2;
00807 }
00808 else if( nbNodes == 8 ){
00809
00810 std::vector< double > aLen (4);
00811 aLen[0] = getDistance( P(1), P(3) );
00812 aLen[1] = getDistance( P(3), P(5) );
00813 aLen[2] = getDistance( P(5), P(7) );
00814 aLen[3] = getDistance( P(7), P(1) );
00815
00816 std::vector< double > aDia (2);
00817 aDia[0] = getDistance( P(1), P(5) );
00818 aDia[1] = getDistance( P(3), P(7) );
00819
00820
00821 std::vector< double > anArea (4);
00822 anArea[0] = getArea( P(1), P(3), P(5) );
00823 anArea[1] = getArea( P(1), P(3), P(7) );
00824 anArea[2] = getArea( P(1), P(5), P(7) );
00825 anArea[3] = getArea( P(3), P(5), P(7) );
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 const double alpha = sqrt( 1 / 32. );
00836 double L = Max( aLen[ 0 ],
00837 Max( aLen[ 1 ],
00838 Max( aLen[ 2 ],
00839 Max( aLen[ 3 ],
00840 Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) );
00841 double C1 = sqrt( ( aLen[0] * aLen[0] +
00842 aLen[1] * aLen[1] +
00843 aLen[2] * aLen[2] +
00844 aLen[3] * aLen[3] ) / 4. );
00845 double C2 = Min( anArea[ 0 ],
00846 Min( anArea[ 1 ],
00847 Min( anArea[ 2 ], anArea[ 3 ] ) ) );
00848 if ( C2 <= Precision::Confusion() )
00849 return 0.;
00850 return alpha * L * C1 / C2;
00851 }
00852 return 0;
00853 }
00854
00855 double AspectRatio::GetBadRate( double Value, int ) const
00856 {
00857
00858
00859
00860 return Value / 1000.;
00861 }
00862
00863 SMDSAbs_ElementType AspectRatio::GetType() const
00864 {
00865 return SMDSAbs_Face;
00866 }
00867
00868
00869
00870
00871
00872
00873 namespace{
00874
00875 inline double getHalfPerimeter(double theTria[3]){
00876 return (theTria[0] + theTria[1] + theTria[2])/2.0;
00877 }
00878
00879 inline double getArea(double theHalfPerim, double theTria[3]){
00880 return sqrt(theHalfPerim*
00881 (theHalfPerim-theTria[0])*
00882 (theHalfPerim-theTria[1])*
00883 (theHalfPerim-theTria[2]));
00884 }
00885
00886 inline double getVolume(double theLen[6]){
00887 double a2 = theLen[0]*theLen[0];
00888 double b2 = theLen[1]*theLen[1];
00889 double c2 = theLen[2]*theLen[2];
00890 double d2 = theLen[3]*theLen[3];
00891 double e2 = theLen[4]*theLen[4];
00892 double f2 = theLen[5]*theLen[5];
00893 double P = 4.0*a2*b2*d2;
00894 double Q = a2*(b2+d2-e2)-b2*(a2+d2-f2)-d2*(a2+b2-c2);
00895 double R = (b2+d2-e2)*(a2+d2-f2)*(a2+d2-f2);
00896 return sqrt(P-Q+R)/12.0;
00897 }
00898
00899 inline double getVolume2(double theLen[6]){
00900 double a2 = theLen[0]*theLen[0];
00901 double b2 = theLen[1]*theLen[1];
00902 double c2 = theLen[2]*theLen[2];
00903 double d2 = theLen[3]*theLen[3];
00904 double e2 = theLen[4]*theLen[4];
00905 double f2 = theLen[5]*theLen[5];
00906
00907 double P = a2*e2*(b2+c2+d2+f2-a2-e2);
00908 double Q = b2*f2*(a2+c2+d2+e2-b2-f2);
00909 double R = c2*d2*(a2+b2+e2+f2-c2-d2);
00910 double S = a2*b2*d2+b2*c2*e2+a2*c2*f2+d2*e2*f2;
00911
00912 return sqrt(P+Q+R-S)/12.0;
00913 }
00914
00915 inline double getVolume(const TSequenceOfXYZ& P){
00916 gp_Vec aVec1( P( 2 ) - P( 1 ) );
00917 gp_Vec aVec2( P( 3 ) - P( 1 ) );
00918 gp_Vec aVec3( P( 4 ) - P( 1 ) );
00919 gp_Vec anAreaVec( aVec1 ^ aVec2 );
00920 return fabs(aVec3 * anAreaVec) / 6.0;
00921 }
00922
00923 inline double getMaxHeight(double theLen[6])
00924 {
00925 double aHeight = std::max(theLen[0],theLen[1]);
00926 aHeight = std::max(aHeight,theLen[2]);
00927 aHeight = std::max(aHeight,theLen[3]);
00928 aHeight = std::max(aHeight,theLen[4]);
00929 aHeight = std::max(aHeight,theLen[5]);
00930 return aHeight;
00931 }
00932
00933 }
00934
00935 double AspectRatio3D::GetValue( long theId )
00936 {
00937 double aVal = 0;
00938 myCurrElement = myMesh->FindElement( theId );
00939 if ( myCurrElement && myCurrElement->GetVtkType() == VTK_TETRA )
00940 {
00941
00942
00943
00944 vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myCurrElement->getMeshId()]->getGrid();
00945 if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->getVtkId() ))
00946 aVal = Round( vtkMeshQuality::TetAspectRatio( avtkCell ));
00947 }
00948 else
00949 {
00950 TSequenceOfXYZ P;
00951 if ( GetPoints( myCurrElement, P ))
00952 aVal = Round( GetValue( P ));
00953 }
00954 return aVal;
00955 }
00956
00957 double AspectRatio3D::GetValue( const TSequenceOfXYZ& P )
00958 {
00959 double aQuality = 0.0;
00960 if(myCurrElement->IsPoly()) return aQuality;
00961
00962 int nbNodes = P.size();
00963
00964 if(myCurrElement->IsQuadratic()) {
00965 if(nbNodes==10) nbNodes=4;
00966 else if(nbNodes==13) nbNodes=5;
00967 else if(nbNodes==15) nbNodes=6;
00968 else if(nbNodes==20) nbNodes=8;
00969 else return aQuality;
00970 }
00971
00972 switch(nbNodes){
00973 case 4:{
00974 double aLen[6] = {
00975 getDistance(P( 1 ),P( 2 )),
00976 getDistance(P( 2 ),P( 3 )),
00977 getDistance(P( 3 ),P( 1 )),
00978 getDistance(P( 2 ),P( 4 )),
00979 getDistance(P( 3 ),P( 4 )),
00980 getDistance(P( 1 ),P( 4 ))
00981 };
00982 double aTria[4][3] = {
00983 {aLen[0],aLen[1],aLen[2]},
00984 {aLen[0],aLen[3],aLen[5]},
00985 {aLen[1],aLen[3],aLen[4]},
00986 {aLen[2],aLen[4],aLen[5]}
00987 };
00988 double aSumArea = 0.0;
00989 double aHalfPerimeter = getHalfPerimeter(aTria[0]);
00990 double anArea = getArea(aHalfPerimeter,aTria[0]);
00991 aSumArea += anArea;
00992 aHalfPerimeter = getHalfPerimeter(aTria[1]);
00993 anArea = getArea(aHalfPerimeter,aTria[1]);
00994 aSumArea += anArea;
00995 aHalfPerimeter = getHalfPerimeter(aTria[2]);
00996 anArea = getArea(aHalfPerimeter,aTria[2]);
00997 aSumArea += anArea;
00998 aHalfPerimeter = getHalfPerimeter(aTria[3]);
00999 anArea = getArea(aHalfPerimeter,aTria[3]);
01000 aSumArea += anArea;
01001 double aVolume = getVolume(P);
01002
01003 double aHeight = getMaxHeight(aLen);
01004 static double aCoeff = sqrt(2.0)/12.0;
01005 if ( aVolume > DBL_MIN )
01006 aQuality = aCoeff*aHeight*aSumArea/aVolume;
01007 break;
01008 }
01009 case 5:{
01010 {
01011 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 3 ),P( 5 )};
01012 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01013 }
01014 {
01015 gp_XYZ aXYZ[4] = {P( 1 ),P( 3 ),P( 4 ),P( 5 )};
01016 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01017 }
01018 {
01019 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 4 ),P( 5 )};
01020 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01021 }
01022 {
01023 gp_XYZ aXYZ[4] = {P( 2 ),P( 3 ),P( 4 ),P( 5 )};
01024 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01025 }
01026 break;
01027 }
01028 case 6:{
01029 {
01030 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 4 ),P( 6 )};
01031 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01032 }
01033 {
01034 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 4 ),P( 3 )};
01035 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01036 }
01037 {
01038 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 6 )};
01039 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01040 }
01041 {
01042 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 3 )};
01043 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01044 }
01045 {
01046 gp_XYZ aXYZ[4] = {P( 2 ),P( 5 ),P( 4 ),P( 6 )};
01047 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01048 }
01049 {
01050 gp_XYZ aXYZ[4] = {P( 2 ),P( 5 ),P( 4 ),P( 3 )};
01051 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01052 }
01053 break;
01054 }
01055 case 8:{
01056 {
01057 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 3 )};
01058 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01059 }
01060 {
01061 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 4 )};
01062 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01063 }
01064 {
01065 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 7 )};
01066 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01067 }
01068 {
01069 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 8 )};
01070 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01071 }
01072 {
01073 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 6 ),P( 3 )};
01074 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01075 }
01076 {
01077 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 6 ),P( 4 )};
01078 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01079 }
01080 {
01081 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 6 ),P( 7 )};
01082 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01083 }
01084 {
01085 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 6 ),P( 8 )};
01086 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01087 }
01088 {
01089 gp_XYZ aXYZ[4] = {P( 2 ),P( 6 ),P( 5 ),P( 3 )};
01090 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01091 }
01092 {
01093 gp_XYZ aXYZ[4] = {P( 2 ),P( 6 ),P( 5 ),P( 4 )};
01094 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01095 }
01096 {
01097 gp_XYZ aXYZ[4] = {P( 2 ),P( 6 ),P( 5 ),P( 7 )};
01098 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01099 }
01100 {
01101 gp_XYZ aXYZ[4] = {P( 2 ),P( 6 ),P( 5 ),P( 8 )};
01102 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01103 }
01104 {
01105 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 8 ),P( 1 )};
01106 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01107 }
01108 {
01109 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 8 ),P( 2 )};
01110 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01111 }
01112 {
01113 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 8 ),P( 5 )};
01114 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01115 }
01116 {
01117 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 8 ),P( 6 )};
01118 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01119 }
01120 {
01121 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 7 ),P( 1 )};
01122 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01123 }
01124 {
01125 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 7 ),P( 2 )};
01126 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01127 }
01128 {
01129 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 7 ),P( 5 )};
01130 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01131 }
01132 {
01133 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 7 ),P( 6 )};
01134 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01135 }
01136 {
01137 gp_XYZ aXYZ[4] = {P( 4 ),P( 8 ),P( 7 ),P( 1 )};
01138 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01139 }
01140 {
01141 gp_XYZ aXYZ[4] = {P( 4 ),P( 8 ),P( 7 ),P( 2 )};
01142 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01143 }
01144 {
01145 gp_XYZ aXYZ[4] = {P( 4 ),P( 8 ),P( 7 ),P( 5 )};
01146 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01147 }
01148 {
01149 gp_XYZ aXYZ[4] = {P( 4 ),P( 8 ),P( 7 ),P( 6 )};
01150 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01151 }
01152 {
01153 gp_XYZ aXYZ[4] = {P( 4 ),P( 8 ),P( 7 ),P( 2 )};
01154 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01155 }
01156 {
01157 gp_XYZ aXYZ[4] = {P( 4 ),P( 5 ),P( 8 ),P( 2 )};
01158 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01159 }
01160 {
01161 gp_XYZ aXYZ[4] = {P( 1 ),P( 4 ),P( 5 ),P( 3 )};
01162 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01163 }
01164 {
01165 gp_XYZ aXYZ[4] = {P( 3 ),P( 6 ),P( 7 ),P( 1 )};
01166 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01167 }
01168 {
01169 gp_XYZ aXYZ[4] = {P( 2 ),P( 3 ),P( 6 ),P( 4 )};
01170 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01171 }
01172 {
01173 gp_XYZ aXYZ[4] = {P( 5 ),P( 6 ),P( 8 ),P( 3 )};
01174 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01175 }
01176 {
01177 gp_XYZ aXYZ[4] = {P( 7 ),P( 8 ),P( 6 ),P( 1 )};
01178 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01179 }
01180 {
01181 gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 4 ),P( 7 )};
01182 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01183 }
01184 {
01185 gp_XYZ aXYZ[4] = {P( 3 ),P( 4 ),P( 2 ),P( 5 )};
01186 aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality);
01187 }
01188 break;
01189 }
01190 }
01191 if ( nbNodes > 4 ) {
01192
01193 AspectRatio aspect2D;
01194 SMDS_VolumeTool::VolumeType type = SMDS_VolumeTool::GetType( nbNodes );
01195 int nbFaces = SMDS_VolumeTool::NbFaces( type );
01196 TSequenceOfXYZ points(4);
01197 for ( int i = 0; i < nbFaces; ++i ) {
01198 if ( SMDS_VolumeTool::NbFaceNodes( type, i ) != 4 )
01199 continue;
01200 const int* pInd = SMDS_VolumeTool::GetFaceNodesIndices( type, i, true );
01201 for ( int p = 0; p < 4; ++p )
01202 points( p + 1 ) = P( pInd[ p ] + 1 );
01203 aQuality = std::max( aQuality, aspect2D.GetValue( points ));
01204 }
01205 }
01206 return aQuality;
01207 }
01208
01209 double AspectRatio3D::GetBadRate( double Value, int ) const
01210 {
01211
01212
01213
01214 return Value / 1000.;
01215 }
01216
01217 SMDSAbs_ElementType AspectRatio3D::GetType() const
01218 {
01219 return SMDSAbs_Volume;
01220 }
01221
01222
01223
01224
01225
01226
01227 double Warping::GetValue( const TSequenceOfXYZ& P )
01228 {
01229 if ( P.size() != 4 )
01230 return 0;
01231
01232 gp_XYZ G = ( P( 1 ) + P( 2 ) + P( 3 ) + P( 4 ) ) / 4.;
01233
01234 double A1 = ComputeA( P( 1 ), P( 2 ), P( 3 ), G );
01235 double A2 = ComputeA( P( 2 ), P( 3 ), P( 4 ), G );
01236 double A3 = ComputeA( P( 3 ), P( 4 ), P( 1 ), G );
01237 double A4 = ComputeA( P( 4 ), P( 1 ), P( 2 ), G );
01238
01239 return Max( Max( A1, A2 ), Max( A3, A4 ) );
01240 }
01241
01242 double Warping::ComputeA( const gp_XYZ& thePnt1,
01243 const gp_XYZ& thePnt2,
01244 const gp_XYZ& thePnt3,
01245 const gp_XYZ& theG ) const
01246 {
01247 double aLen1 = gp_Pnt( thePnt1 ).Distance( gp_Pnt( thePnt2 ) );
01248 double aLen2 = gp_Pnt( thePnt2 ).Distance( gp_Pnt( thePnt3 ) );
01249 double L = Min( aLen1, aLen2 ) * 0.5;
01250 if ( L < Precision::Confusion())
01251 return 0.;
01252
01253 gp_XYZ GI = ( thePnt2 + thePnt1 ) / 2. - theG;
01254 gp_XYZ GJ = ( thePnt3 + thePnt2 ) / 2. - theG;
01255 gp_XYZ N = GI.Crossed( GJ );
01256
01257 if ( N.Modulus() < gp::Resolution() )
01258 return PI / 2;
01259
01260 N.Normalize();
01261
01262 double H = ( thePnt2 - theG ).Dot( N );
01263 return asin( fabs( H / L ) ) * 180. / PI;
01264 }
01265
01266 double Warping::GetBadRate( double Value, int ) const
01267 {
01268
01269
01270
01271 return Value;
01272 }
01273
01274 SMDSAbs_ElementType Warping::GetType() const
01275 {
01276 return SMDSAbs_Face;
01277 }
01278
01279
01280
01281
01282
01283
01284 double Taper::GetValue( const TSequenceOfXYZ& P )
01285 {
01286 if ( P.size() != 4 )
01287 return 0.;
01288
01289
01290 double J1 = getArea( P( 4 ), P( 1 ), P( 2 ) ) / 2.;
01291 double J2 = getArea( P( 3 ), P( 1 ), P( 2 ) ) / 2.;
01292 double J3 = getArea( P( 2 ), P( 3 ), P( 4 ) ) / 2.;
01293 double J4 = getArea( P( 3 ), P( 4 ), P( 1 ) ) / 2.;
01294
01295 double JA = 0.25 * ( J1 + J2 + J3 + J4 );
01296 if ( JA <= Precision::Confusion() )
01297 return 0.;
01298
01299 double T1 = fabs( ( J1 - JA ) / JA );
01300 double T2 = fabs( ( J2 - JA ) / JA );
01301 double T3 = fabs( ( J3 - JA ) / JA );
01302 double T4 = fabs( ( J4 - JA ) / JA );
01303
01304 return Max( Max( T1, T2 ), Max( T3, T4 ) );
01305 }
01306
01307 double Taper::GetBadRate( double Value, int ) const
01308 {
01309
01310
01311
01312 return Value;
01313 }
01314
01315 SMDSAbs_ElementType Taper::GetType() const
01316 {
01317 return SMDSAbs_Face;
01318 }
01319
01320
01321
01322
01323
01324
01325 static inline double skewAngle( const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3 )
01326 {
01327 gp_XYZ p12 = ( p2 + p1 ) / 2.;
01328 gp_XYZ p23 = ( p3 + p2 ) / 2.;
01329 gp_XYZ p31 = ( p3 + p1 ) / 2.;
01330
01331 gp_Vec v1( p31 - p2 ), v2( p12 - p23 );
01332
01333 return v1.Magnitude() < gp::Resolution() || v2.Magnitude() < gp::Resolution() ? 0. : v1.Angle( v2 );
01334 }
01335
01336 double Skew::GetValue( const TSequenceOfXYZ& P )
01337 {
01338 if ( P.size() != 3 && P.size() != 4 )
01339 return 0.;
01340
01341
01342 static double PI2 = PI / 2.;
01343 if ( P.size() == 3 )
01344 {
01345 double A0 = fabs( PI2 - skewAngle( P( 3 ), P( 1 ), P( 2 ) ) );
01346 double A1 = fabs( PI2 - skewAngle( P( 1 ), P( 2 ), P( 3 ) ) );
01347 double A2 = fabs( PI2 - skewAngle( P( 2 ), P( 3 ), P( 1 ) ) );
01348
01349 return Max( A0, Max( A1, A2 ) ) * 180. / PI;
01350 }
01351 else
01352 {
01353 gp_XYZ p12 = ( P( 1 ) + P( 2 ) ) / 2.;
01354 gp_XYZ p23 = ( P( 2 ) + P( 3 ) ) / 2.;
01355 gp_XYZ p34 = ( P( 3 ) + P( 4 ) ) / 2.;
01356 gp_XYZ p41 = ( P( 4 ) + P( 1 ) ) / 2.;
01357
01358 gp_Vec v1( p34 - p12 ), v2( p23 - p41 );
01359 double A = v1.Magnitude() <= gp::Resolution() || v2.Magnitude() <= gp::Resolution()
01360 ? 0. : fabs( PI2 - v1.Angle( v2 ) );
01361
01362
01363 if ( A < Precision::Angular() )
01364 return 0.;
01365
01366 return A * 180. / PI;
01367 }
01368 }
01369
01370 double Skew::GetBadRate( double Value, int ) const
01371 {
01372
01373
01374
01375 return Value;
01376 }
01377
01378 SMDSAbs_ElementType Skew::GetType() const
01379 {
01380 return SMDSAbs_Face;
01381 }
01382
01383
01384
01385
01386
01387
01388 double Area::GetValue( const TSequenceOfXYZ& P )
01389 {
01390 double val = 0.0;
01391 if ( P.size() > 2 ) {
01392 gp_Vec aVec1( P(2) - P(1) );
01393 gp_Vec aVec2( P(3) - P(1) );
01394 gp_Vec SumVec = aVec1 ^ aVec2;
01395 for (int i=4; i<=P.size(); i++) {
01396 gp_Vec aVec1( P(i-1) - P(1) );
01397 gp_Vec aVec2( P(i) - P(1) );
01398 gp_Vec tmp = aVec1 ^ aVec2;
01399 SumVec.Add(tmp);
01400 }
01401 val = SumVec.Magnitude() * 0.5;
01402 }
01403 return val;
01404 }
01405
01406 double Area::GetBadRate( double Value, int ) const
01407 {
01408
01409 return Value;
01410 }
01411
01412 SMDSAbs_ElementType Area::GetType() const
01413 {
01414 return SMDSAbs_Face;
01415 }
01416
01417
01418
01419
01420
01421
01422 double Length::GetValue( const TSequenceOfXYZ& P )
01423 {
01424 switch ( P.size() ) {
01425 case 2: return getDistance( P( 1 ), P( 2 ) );
01426 case 3: return getDistance( P( 1 ), P( 2 ) ) + getDistance( P( 2 ), P( 3 ) );
01427 default: return 0.;
01428 }
01429 }
01430
01431 double Length::GetBadRate( double Value, int ) const
01432 {
01433
01434 return Value;
01435 }
01436
01437 SMDSAbs_ElementType Length::GetType() const
01438 {
01439 return SMDSAbs_Edge;
01440 }
01441
01442
01443
01444
01445
01446
01447 double Length2D::GetValue( long theElementId)
01448 {
01449 TSequenceOfXYZ P;
01450
01451
01452 if (GetPoints(theElementId,P)){
01453
01454
01455
01456 double aVal;
01457 const SMDS_MeshElement* aElem = myMesh->FindElement( theElementId );
01458 SMDSAbs_ElementType aType = aElem->GetType();
01459
01460 int len = P.size();
01461
01462 switch (aType){
01463 case SMDSAbs_All:
01464 case SMDSAbs_Node:
01465 case SMDSAbs_Edge:
01466 if (len == 2){
01467 aVal = getDistance( P( 1 ), P( 2 ) );
01468 break;
01469 }
01470 else if (len == 3){
01471 aVal = getDistance(P( 1 ),P( 3 )) + getDistance(P( 3 ),P( 2 ));
01472 break;
01473 }
01474 case SMDSAbs_Face:
01475 if (len == 3){
01476 double L1 = getDistance(P( 1 ),P( 2 ));
01477 double L2 = getDistance(P( 2 ),P( 3 ));
01478 double L3 = getDistance(P( 3 ),P( 1 ));
01479 aVal = Max(L1,Max(L2,L3));
01480 break;
01481 }
01482 else if (len == 4){
01483 double L1 = getDistance(P( 1 ),P( 2 ));
01484 double L2 = getDistance(P( 2 ),P( 3 ));
01485 double L3 = getDistance(P( 3 ),P( 4 ));
01486 double L4 = getDistance(P( 4 ),P( 1 ));
01487 aVal = Max(Max(L1,L2),Max(L3,L4));
01488 break;
01489 }
01490 if (len == 6){
01491 double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
01492 double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
01493 double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
01494 aVal = Max(L1,Max(L2,L3));
01495
01496 break;
01497 }
01498 else if (len == 8){
01499 double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
01500 double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
01501 double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
01502 double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
01503 aVal = Max(Max(L1,L2),Max(L3,L4));
01504 break;
01505 }
01506 case SMDSAbs_Volume:
01507 if (len == 4){
01508 double L1 = getDistance(P( 1 ),P( 2 ));
01509 double L2 = getDistance(P( 2 ),P( 3 ));
01510 double L3 = getDistance(P( 3 ),P( 1 ));
01511 double L4 = getDistance(P( 1 ),P( 4 ));
01512 double L5 = getDistance(P( 2 ),P( 4 ));
01513 double L6 = getDistance(P( 3 ),P( 4 ));
01514 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01515 break;
01516 }
01517 else if (len == 5){
01518 double L1 = getDistance(P( 1 ),P( 2 ));
01519 double L2 = getDistance(P( 2 ),P( 3 ));
01520 double L3 = getDistance(P( 3 ),P( 4 ));
01521 double L4 = getDistance(P( 4 ),P( 1 ));
01522 double L5 = getDistance(P( 1 ),P( 5 ));
01523 double L6 = getDistance(P( 2 ),P( 5 ));
01524 double L7 = getDistance(P( 3 ),P( 5 ));
01525 double L8 = getDistance(P( 4 ),P( 5 ));
01526
01527 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01528 aVal = Max(aVal,Max(L7,L8));
01529 break;
01530 }
01531 else if (len == 6){
01532 double L1 = getDistance(P( 1 ),P( 2 ));
01533 double L2 = getDistance(P( 2 ),P( 3 ));
01534 double L3 = getDistance(P( 3 ),P( 1 ));
01535 double L4 = getDistance(P( 4 ),P( 5 ));
01536 double L5 = getDistance(P( 5 ),P( 6 ));
01537 double L6 = getDistance(P( 6 ),P( 4 ));
01538 double L7 = getDistance(P( 1 ),P( 4 ));
01539 double L8 = getDistance(P( 2 ),P( 5 ));
01540 double L9 = getDistance(P( 3 ),P( 6 ));
01541
01542 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01543 aVal = Max(aVal,Max(Max(L7,L8),L9));
01544 break;
01545 }
01546 else if (len == 8){
01547 double L1 = getDistance(P( 1 ),P( 2 ));
01548 double L2 = getDistance(P( 2 ),P( 3 ));
01549 double L3 = getDistance(P( 3 ),P( 4 ));
01550 double L4 = getDistance(P( 4 ),P( 1 ));
01551 double L5 = getDistance(P( 5 ),P( 6 ));
01552 double L6 = getDistance(P( 6 ),P( 7 ));
01553 double L7 = getDistance(P( 7 ),P( 8 ));
01554 double L8 = getDistance(P( 8 ),P( 5 ));
01555 double L9 = getDistance(P( 1 ),P( 5 ));
01556 double L10= getDistance(P( 2 ),P( 6 ));
01557 double L11= getDistance(P( 3 ),P( 7 ));
01558 double L12= getDistance(P( 4 ),P( 8 ));
01559
01560 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01561 aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
01562 aVal = Max(aVal,Max(L11,L12));
01563 break;
01564
01565 }
01566
01567 if (len == 10){
01568 double L1 = getDistance(P( 1 ),P( 5 )) + getDistance(P( 5 ),P( 2 ));
01569 double L2 = getDistance(P( 2 ),P( 6 )) + getDistance(P( 6 ),P( 3 ));
01570 double L3 = getDistance(P( 3 ),P( 7 )) + getDistance(P( 7 ),P( 1 ));
01571 double L4 = getDistance(P( 1 ),P( 8 )) + getDistance(P( 8 ),P( 4 ));
01572 double L5 = getDistance(P( 2 ),P( 9 )) + getDistance(P( 9 ),P( 4 ));
01573 double L6 = getDistance(P( 3 ),P( 10 )) + getDistance(P( 10 ),P( 4 ));
01574 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01575 break;
01576 }
01577 else if (len == 13){
01578 double L1 = getDistance(P( 1 ),P( 6 )) + getDistance(P( 6 ),P( 2 ));
01579 double L2 = getDistance(P( 2 ),P( 7 )) + getDistance(P( 7 ),P( 3 ));
01580 double L3 = getDistance(P( 3 ),P( 8 )) + getDistance(P( 8 ),P( 4 ));
01581 double L4 = getDistance(P( 4 ),P( 9 )) + getDistance(P( 9 ),P( 1 ));
01582 double L5 = getDistance(P( 1 ),P( 10 )) + getDistance(P( 10 ),P( 5 ));
01583 double L6 = getDistance(P( 2 ),P( 11 )) + getDistance(P( 11 ),P( 5 ));
01584 double L7 = getDistance(P( 3 ),P( 12 )) + getDistance(P( 12 ),P( 5 ));
01585 double L8 = getDistance(P( 4 ),P( 13 )) + getDistance(P( 13 ),P( 5 ));
01586 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01587 aVal = Max(aVal,Max(L7,L8));
01588 break;
01589 }
01590 else if (len == 15){
01591 double L1 = getDistance(P( 1 ),P( 7 )) + getDistance(P( 7 ),P( 2 ));
01592 double L2 = getDistance(P( 2 ),P( 8 )) + getDistance(P( 8 ),P( 3 ));
01593 double L3 = getDistance(P( 3 ),P( 9 )) + getDistance(P( 9 ),P( 1 ));
01594 double L4 = getDistance(P( 4 ),P( 10 )) + getDistance(P( 10 ),P( 5 ));
01595 double L5 = getDistance(P( 5 ),P( 11 )) + getDistance(P( 11 ),P( 6 ));
01596 double L6 = getDistance(P( 6 ),P( 12 )) + getDistance(P( 12 ),P( 4 ));
01597 double L7 = getDistance(P( 1 ),P( 13 )) + getDistance(P( 13 ),P( 4 ));
01598 double L8 = getDistance(P( 2 ),P( 14 )) + getDistance(P( 14 ),P( 5 ));
01599 double L9 = getDistance(P( 3 ),P( 15 )) + getDistance(P( 15 ),P( 6 ));
01600 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01601 aVal = Max(aVal,Max(Max(L7,L8),L9));
01602 break;
01603 }
01604 else if (len == 20){
01605 double L1 = getDistance(P( 1 ),P( 9 )) + getDistance(P( 9 ),P( 2 ));
01606 double L2 = getDistance(P( 2 ),P( 10 )) + getDistance(P( 10 ),P( 3 ));
01607 double L3 = getDistance(P( 3 ),P( 11 )) + getDistance(P( 11 ),P( 4 ));
01608 double L4 = getDistance(P( 4 ),P( 12 )) + getDistance(P( 12 ),P( 1 ));
01609 double L5 = getDistance(P( 5 ),P( 13 )) + getDistance(P( 13 ),P( 6 ));
01610 double L6 = getDistance(P( 6 ),P( 14 )) + getDistance(P( 14 ),P( 7 ));
01611 double L7 = getDistance(P( 7 ),P( 15 )) + getDistance(P( 15 ),P( 8 ));
01612 double L8 = getDistance(P( 8 ),P( 16 )) + getDistance(P( 16 ),P( 5 ));
01613 double L9 = getDistance(P( 1 ),P( 17 )) + getDistance(P( 17 ),P( 5 ));
01614 double L10= getDistance(P( 2 ),P( 18 )) + getDistance(P( 18 ),P( 6 ));
01615 double L11= getDistance(P( 3 ),P( 19 )) + getDistance(P( 19 ),P( 7 ));
01616 double L12= getDistance(P( 4 ),P( 20 )) + getDistance(P( 20 ),P( 8 ));
01617 aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(L5,L6));
01618 aVal = Max(aVal,Max(Max(L7,L8),Max(L9,L10)));
01619 aVal = Max(aVal,Max(L11,L12));
01620 break;
01621
01622 }
01623
01624 default: aVal=-1;
01625 }
01626
01627 if (aVal <0){
01628 return 0.;
01629 }
01630
01631 if ( myPrecision >= 0 )
01632 {
01633 double prec = pow( 10., (double)( myPrecision ) );
01634 aVal = floor( aVal * prec + 0.5 ) / prec;
01635 }
01636
01637 return aVal;
01638
01639 }
01640 return 0.;
01641 }
01642
01643 double Length2D::GetBadRate( double Value, int ) const
01644 {
01645
01646 return Value;
01647 }
01648
01649 SMDSAbs_ElementType Length2D::GetType() const
01650 {
01651 return SMDSAbs_Face;
01652 }
01653
01654 Length2D::Value::Value(double theLength,long thePntId1, long thePntId2):
01655 myLength(theLength)
01656 {
01657 myPntId[0] = thePntId1; myPntId[1] = thePntId2;
01658 if(thePntId1 > thePntId2){
01659 myPntId[1] = thePntId1; myPntId[0] = thePntId2;
01660 }
01661 }
01662
01663 bool Length2D::Value::operator<(const Length2D::Value& x) const{
01664 if(myPntId[0] < x.myPntId[0]) return true;
01665 if(myPntId[0] == x.myPntId[0])
01666 if(myPntId[1] < x.myPntId[1]) return true;
01667 return false;
01668 }
01669
01670 void Length2D::GetValues(TValues& theValues){
01671 TValues aValues;
01672 SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
01673 for(; anIter->more(); ){
01674 const SMDS_MeshFace* anElem = anIter->next();
01675
01676 if(anElem->IsQuadratic()) {
01677 const SMDS_VtkFace* F =
01678 dynamic_cast<const SMDS_VtkFace*>(anElem);
01679
01680 SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
01681 long aNodeId[4];
01682 gp_Pnt P[4];
01683
01684 double aLength;
01685 const SMDS_MeshElement* aNode;
01686 if(anIter->more()){
01687 aNode = anIter->next();
01688 const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode;
01689 P[0] = P[1] = gp_Pnt(aNodes->X(),aNodes->Y(),aNodes->Z());
01690 aNodeId[0] = aNodeId[1] = aNode->GetID();
01691 aLength = 0;
01692 }
01693 for(; anIter->more(); ){
01694 const SMDS_MeshNode* N1 = static_cast<const SMDS_MeshNode*> (anIter->next());
01695 P[2] = gp_Pnt(N1->X(),N1->Y(),N1->Z());
01696 aNodeId[2] = N1->GetID();
01697 aLength = P[1].Distance(P[2]);
01698 if(!anIter->more()) break;
01699 const SMDS_MeshNode* N2 = static_cast<const SMDS_MeshNode*> (anIter->next());
01700 P[3] = gp_Pnt(N2->X(),N2->Y(),N2->Z());
01701 aNodeId[3] = N2->GetID();
01702 aLength += P[2].Distance(P[3]);
01703 Value aValue1(aLength,aNodeId[1],aNodeId[2]);
01704 Value aValue2(aLength,aNodeId[2],aNodeId[3]);
01705 P[1] = P[3];
01706 aNodeId[1] = aNodeId[3];
01707 theValues.insert(aValue1);
01708 theValues.insert(aValue2);
01709 }
01710 aLength += P[2].Distance(P[0]);
01711 Value aValue1(aLength,aNodeId[1],aNodeId[2]);
01712 Value aValue2(aLength,aNodeId[2],aNodeId[0]);
01713 theValues.insert(aValue1);
01714 theValues.insert(aValue2);
01715 }
01716 else {
01717 SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
01718 long aNodeId[2];
01719 gp_Pnt P[3];
01720
01721 double aLength;
01722 const SMDS_MeshElement* aNode;
01723 if(aNodesIter->more()){
01724 aNode = aNodesIter->next();
01725 const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode;
01726 P[0] = P[1] = gp_Pnt(aNodes->X(),aNodes->Y(),aNodes->Z());
01727 aNodeId[0] = aNodeId[1] = aNode->GetID();
01728 aLength = 0;
01729 }
01730 for(; aNodesIter->more(); ){
01731 aNode = aNodesIter->next();
01732 const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode;
01733 long anId = aNode->GetID();
01734
01735 P[2] = gp_Pnt(aNodes->X(),aNodes->Y(),aNodes->Z());
01736
01737 aLength = P[1].Distance(P[2]);
01738
01739 Value aValue(aLength,aNodeId[1],anId);
01740 aNodeId[1] = anId;
01741 P[1] = P[2];
01742 theValues.insert(aValue);
01743 }
01744
01745 aLength = P[0].Distance(P[1]);
01746
01747 Value aValue(aLength,aNodeId[0],aNodeId[1]);
01748 theValues.insert(aValue);
01749 }
01750 }
01751 }
01752
01753
01754
01755
01756
01757 double MultiConnection::GetValue( const TSequenceOfXYZ& P )
01758 {
01759 return 0;
01760 }
01761 double MultiConnection::GetValue( long theId )
01762 {
01763 return getNbMultiConnection( myMesh, theId );
01764 }
01765
01766 double MultiConnection::GetBadRate( double Value, int ) const
01767 {
01768
01769 return Value;
01770 }
01771
01772 SMDSAbs_ElementType MultiConnection::GetType() const
01773 {
01774 return SMDSAbs_Edge;
01775 }
01776
01777
01778
01779
01780
01781 double MultiConnection2D::GetValue( const TSequenceOfXYZ& P )
01782 {
01783 return 0;
01784 }
01785
01786 double MultiConnection2D::GetValue( long theElementId )
01787 {
01788 int aResult = 0;
01789
01790 const SMDS_MeshElement* aFaceElem = myMesh->FindElement(theElementId);
01791 SMDSAbs_ElementType aType = aFaceElem->GetType();
01792
01793 switch (aType) {
01794 case SMDSAbs_Face:
01795 {
01796 int i = 0, len = aFaceElem->NbNodes();
01797 SMDS_ElemIteratorPtr anIter = aFaceElem->nodesIterator();
01798 if (!anIter) break;
01799
01800 const SMDS_MeshNode *aNode, *aNode0;
01801 TColStd_MapOfInteger aMap, aMapPrev;
01802
01803 for (i = 0; i <= len; i++) {
01804 aMapPrev = aMap;
01805 aMap.Clear();
01806
01807 int aNb = 0;
01808 if (anIter->more()) {
01809 aNode = (SMDS_MeshNode*)anIter->next();
01810 } else {
01811 if (i == len)
01812 aNode = aNode0;
01813 else
01814 break;
01815 }
01816 if (!aNode) break;
01817 if (i == 0) aNode0 = aNode;
01818
01819 SMDS_ElemIteratorPtr anElemIter = aNode->GetInverseElementIterator();
01820 while (anElemIter->more()) {
01821 const SMDS_MeshElement* anElem = anElemIter->next();
01822 if (anElem != 0 && anElem->GetType() == SMDSAbs_Face) {
01823 int anId = anElem->GetID();
01824
01825 aMap.Add(anId);
01826 if (aMapPrev.Contains(anId)) {
01827 aNb++;
01828 }
01829 }
01830 }
01831 aResult = Max(aResult, aNb);
01832 }
01833 }
01834 break;
01835 default:
01836 aResult = 0;
01837 }
01838
01839 return aResult;
01840 }
01841
01842 double MultiConnection2D::GetBadRate( double Value, int ) const
01843 {
01844
01845 return Value;
01846 }
01847
01848 SMDSAbs_ElementType MultiConnection2D::GetType() const
01849 {
01850 return SMDSAbs_Face;
01851 }
01852
01853 MultiConnection2D::Value::Value(long thePntId1, long thePntId2)
01854 {
01855 myPntId[0] = thePntId1; myPntId[1] = thePntId2;
01856 if(thePntId1 > thePntId2){
01857 myPntId[1] = thePntId1; myPntId[0] = thePntId2;
01858 }
01859 }
01860
01861 bool MultiConnection2D::Value::operator<(const MultiConnection2D::Value& x) const{
01862 if(myPntId[0] < x.myPntId[0]) return true;
01863 if(myPntId[0] == x.myPntId[0])
01864 if(myPntId[1] < x.myPntId[1]) return true;
01865 return false;
01866 }
01867
01868 void MultiConnection2D::GetValues(MValues& theValues){
01869 SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
01870 for(; anIter->more(); ){
01871 const SMDS_MeshFace* anElem = anIter->next();
01872 SMDS_ElemIteratorPtr aNodesIter;
01873 if ( anElem->IsQuadratic() )
01874 aNodesIter = dynamic_cast<const SMDS_VtkFace*>
01875 (anElem)->interlacedNodesElemIterator();
01876 else
01877 aNodesIter = anElem->nodesIterator();
01878 long aNodeId[3];
01879
01880
01881 const SMDS_MeshNode* aNode0;
01882 const SMDS_MeshNode* aNode1;
01883 const SMDS_MeshNode* aNode2;
01884 if(aNodesIter->more()){
01885 aNode0 = (SMDS_MeshNode*) aNodesIter->next();
01886 aNode1 = aNode0;
01887 const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode1;
01888 aNodeId[0] = aNodeId[1] = aNodes->GetID();
01889 }
01890 for(; aNodesIter->more(); ) {
01891 aNode2 = (SMDS_MeshNode*) aNodesIter->next();
01892 long anId = aNode2->GetID();
01893 aNodeId[2] = anId;
01894
01895 Value aValue(aNodeId[1],aNodeId[2]);
01896 MValues::iterator aItr = theValues.find(aValue);
01897 if (aItr != theValues.end()){
01898 aItr->second += 1;
01899
01900 }
01901 else {
01902 theValues[aValue] = 1;
01903
01904 }
01905
01906 aNodeId[1] = aNodeId[2];
01907 aNode1 = aNode2;
01908 }
01909 Value aValue(aNodeId[0],aNodeId[2]);
01910 MValues::iterator aItr = theValues.find(aValue);
01911 if (aItr != theValues.end()) {
01912 aItr->second += 1;
01913
01914 }
01915 else {
01916 theValues[aValue] = 1;
01917
01918 }
01919
01920 }
01921
01922 }
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933 BadOrientedVolume::BadOrientedVolume()
01934 {
01935 myMesh = 0;
01936 }
01937
01938 void BadOrientedVolume::SetMesh( const SMDS_Mesh* theMesh )
01939 {
01940 myMesh = theMesh;
01941 }
01942
01943 bool BadOrientedVolume::IsSatisfy( long theId )
01944 {
01945 if ( myMesh == 0 )
01946 return false;
01947
01948 SMDS_VolumeTool vTool( myMesh->FindElement( theId ));
01949 return !vTool.IsForward();
01950 }
01951
01952 SMDSAbs_ElementType BadOrientedVolume::GetType() const
01953 {
01954 return SMDSAbs_Volume;
01955 }
01956
01957
01958
01959
01960
01961 bool BareBorderVolume::IsSatisfy(long theElementId )
01962 {
01963 SMDS_VolumeTool myTool;
01964 if ( myTool.Set( myMesh->FindElement(theElementId)))
01965 {
01966 for ( int iF = 0; iF < myTool.NbFaces(); ++iF )
01967 if ( myTool.IsFreeFace( iF ))
01968 {
01969 const SMDS_MeshNode** n = myTool.GetFaceNodes(iF);
01970 vector< const SMDS_MeshNode*> nodes( n, n+myTool.NbFaceNodes(iF));
01971 if ( !myMesh->FindElement( nodes, SMDSAbs_Face, false))
01972 return true;
01973 }
01974 }
01975 return false;
01976 }
01977
01978
01979
01980
01981
01982 bool BareBorderFace::IsSatisfy(long theElementId )
01983 {
01984 bool ok = false;
01985 if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId))
01986 {
01987 if ( face->GetType() == SMDSAbs_Face )
01988 {
01989 int nbN = face->NbCornerNodes();
01990 for ( int i = 0; i < nbN && !ok; ++i )
01991 {
01992
01993 const SMDS_MeshNode* n1 = face->GetNode( i );
01994 const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN );
01995 SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face );
01996 bool isShared = false;
01997 while ( !isShared && fIt->more() )
01998 {
01999 const SMDS_MeshElement* f = fIt->next();
02000 isShared = ( f != face && f->GetNodeIndex(n2) != -1 );
02001 }
02002 if ( !isShared )
02003 {
02004 myLinkNodes.resize( 2 + face->IsQuadratic());
02005 myLinkNodes[0] = n1;
02006 myLinkNodes[1] = n2;
02007 if ( face->IsQuadratic() )
02008 myLinkNodes[2] = face->GetNode( i+nbN );
02009 ok = !myMesh->FindElement( myLinkNodes, SMDSAbs_Edge, false);
02010 }
02011 }
02012 }
02013 }
02014 return ok;
02015 }
02016
02017
02018
02019
02020
02021 bool OverConstrainedVolume::IsSatisfy(long theElementId )
02022 {
02023
02024
02025 SMDS_VolumeTool myTool;
02026 if ( myTool.Set( myMesh->FindElement(theElementId)))
02027 {
02028 int nbSharedFaces = 0;
02029 for ( int iF = 0; iF < myTool.NbFaces(); ++iF )
02030 if ( !myTool.IsFreeFace( iF ) && ++nbSharedFaces > 1 )
02031 break;
02032 return ( nbSharedFaces == 1 );
02033 }
02034 return false;
02035 }
02036
02037
02038
02039
02040
02041 bool OverConstrainedFace::IsSatisfy(long theElementId )
02042 {
02043
02044
02045 if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId))
02046 if ( face->GetType() == SMDSAbs_Face )
02047 {
02048 int nbSharedBorders = 0;
02049 int nbN = face->NbCornerNodes();
02050 for ( int i = 0; i < nbN; ++i )
02051 {
02052
02053 const SMDS_MeshNode* n1 = face->GetNode( i );
02054 const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN );
02055 SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face );
02056 bool isShared = false;
02057 while ( !isShared && fIt->more() )
02058 {
02059 const SMDS_MeshElement* f = fIt->next();
02060 isShared = ( f != face && f->GetNodeIndex(n2) != -1 );
02061 }
02062 if ( isShared && ++nbSharedBorders > 1 )
02063 break;
02064 }
02065 return ( nbSharedBorders == 1 );
02066 }
02067 return false;
02068 }
02069
02070
02071
02072
02073
02074
02075 FreeBorders::FreeBorders()
02076 {
02077 myMesh = 0;
02078 }
02079
02080 void FreeBorders::SetMesh( const SMDS_Mesh* theMesh )
02081 {
02082 myMesh = theMesh;
02083 }
02084
02085 bool FreeBorders::IsSatisfy( long theId )
02086 {
02087 return getNbMultiConnection( myMesh, theId ) == 1;
02088 }
02089
02090 SMDSAbs_ElementType FreeBorders::GetType() const
02091 {
02092 return SMDSAbs_Edge;
02093 }
02094
02095
02096
02097
02098
02099
02100 FreeEdges::FreeEdges()
02101 {
02102 myMesh = 0;
02103 }
02104
02105 void FreeEdges::SetMesh( const SMDS_Mesh* theMesh )
02106 {
02107 myMesh = theMesh;
02108 }
02109
02110 bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const int theFaceId )
02111 {
02112 TColStd_MapOfInteger aMap;
02113 for ( int i = 0; i < 2; i++ )
02114 {
02115 SMDS_ElemIteratorPtr anElemIter = theNodes[ i ]->GetInverseElementIterator();
02116 while( anElemIter->more() )
02117 {
02118 const SMDS_MeshElement* anElem = anElemIter->next();
02119 if ( anElem != 0 && anElem->GetType() == SMDSAbs_Face )
02120 {
02121 int anId = anElem->GetID();
02122
02123 if ( i == 0 )
02124 aMap.Add( anId );
02125 else if ( aMap.Contains( anId ) && anId != theFaceId )
02126 return false;
02127 }
02128 }
02129 }
02130 return true;
02131 }
02132
02133 bool FreeEdges::IsSatisfy( long theId )
02134 {
02135 if ( myMesh == 0 )
02136 return false;
02137
02138 const SMDS_MeshElement* aFace = myMesh->FindElement( theId );
02139 if ( aFace == 0 || aFace->GetType() != SMDSAbs_Face || aFace->NbNodes() < 3 )
02140 return false;
02141
02142 SMDS_ElemIteratorPtr anIter;
02143 if ( aFace->IsQuadratic() ) {
02144 anIter = dynamic_cast<const SMDS_VtkFace*>
02145 (aFace)->interlacedNodesElemIterator();
02146 }
02147 else {
02148 anIter = aFace->nodesIterator();
02149 }
02150 if ( anIter == 0 )
02151 return false;
02152
02153 int i = 0, nbNodes = aFace->NbNodes();
02154 std::vector <const SMDS_MeshNode*> aNodes( nbNodes+1 );
02155 while( anIter->more() )
02156 {
02157 const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next();
02158 if ( aNode == 0 )
02159 return false;
02160 aNodes[ i++ ] = aNode;
02161 }
02162 aNodes[ nbNodes ] = aNodes[ 0 ];
02163
02164 for ( i = 0; i < nbNodes; i++ )
02165 if ( IsFreeEdge( &aNodes[ i ], theId ) )
02166 return true;
02167
02168 return false;
02169 }
02170
02171 SMDSAbs_ElementType FreeEdges::GetType() const
02172 {
02173 return SMDSAbs_Face;
02174 }
02175
02176 FreeEdges::Border::Border(long theElemId, long thePntId1, long thePntId2):
02177 myElemId(theElemId)
02178 {
02179 myPntId[0] = thePntId1; myPntId[1] = thePntId2;
02180 if(thePntId1 > thePntId2){
02181 myPntId[1] = thePntId1; myPntId[0] = thePntId2;
02182 }
02183 }
02184
02185 bool FreeEdges::Border::operator<(const FreeEdges::Border& x) const{
02186 if(myPntId[0] < x.myPntId[0]) return true;
02187 if(myPntId[0] == x.myPntId[0])
02188 if(myPntId[1] < x.myPntId[1]) return true;
02189 return false;
02190 }
02191
02192 inline void UpdateBorders(const FreeEdges::Border& theBorder,
02193 FreeEdges::TBorders& theRegistry,
02194 FreeEdges::TBorders& theContainer)
02195 {
02196 if(theRegistry.find(theBorder) == theRegistry.end()){
02197 theRegistry.insert(theBorder);
02198 theContainer.insert(theBorder);
02199 }else{
02200 theContainer.erase(theBorder);
02201 }
02202 }
02203
02204 void FreeEdges::GetBoreders(TBorders& theBorders)
02205 {
02206 TBorders aRegistry;
02207 SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
02208 for(; anIter->more(); ){
02209 const SMDS_MeshFace* anElem = anIter->next();
02210 long anElemId = anElem->GetID();
02211 SMDS_ElemIteratorPtr aNodesIter;
02212 if ( anElem->IsQuadratic() )
02213 aNodesIter = static_cast<const SMDS_VtkFace*>(anElem)->
02214 interlacedNodesElemIterator();
02215 else
02216 aNodesIter = anElem->nodesIterator();
02217 long aNodeId[2];
02218 const SMDS_MeshElement* aNode;
02219 if(aNodesIter->more()){
02220 aNode = aNodesIter->next();
02221 aNodeId[0] = aNodeId[1] = aNode->GetID();
02222 }
02223 for(; aNodesIter->more(); ){
02224 aNode = aNodesIter->next();
02225 long anId = aNode->GetID();
02226 Border aBorder(anElemId,aNodeId[1],anId);
02227 aNodeId[1] = anId;
02228
02229 UpdateBorders(aBorder,aRegistry,theBorders);
02230 }
02231 Border aBorder(anElemId,aNodeId[0],aNodeId[1]);
02232
02233 UpdateBorders(aBorder,aRegistry,theBorders);
02234 }
02235
02236 }
02237
02238
02239
02240
02241
02242
02243
02244 FreeNodes::FreeNodes()
02245 {
02246 myMesh = 0;
02247 }
02248
02249 void FreeNodes::SetMesh( const SMDS_Mesh* theMesh )
02250 {
02251 myMesh = theMesh;
02252 }
02253
02254 bool FreeNodes::IsSatisfy( long theNodeId )
02255 {
02256 const SMDS_MeshNode* aNode = myMesh->FindNode( theNodeId );
02257 if (!aNode)
02258 return false;
02259
02260 return (aNode->NbInverseElements() < 1);
02261 }
02262
02263 SMDSAbs_ElementType FreeNodes::GetType() const
02264 {
02265 return SMDSAbs_Node;
02266 }
02267
02268
02269
02270
02271
02272
02273
02274 FreeFaces::FreeFaces()
02275 {
02276 myMesh = 0;
02277 }
02278
02279 void FreeFaces::SetMesh( const SMDS_Mesh* theMesh )
02280 {
02281 myMesh = theMesh;
02282 }
02283
02284 bool FreeFaces::IsSatisfy( long theId )
02285 {
02286 if (!myMesh) return false;
02287
02288 const SMDS_MeshElement* aFace = myMesh->FindElement( theId );
02289 if ( !aFace || aFace->GetType() != SMDSAbs_Face )
02290 return false;
02291
02292 int nbNode = aFace->NbNodes();
02293
02294
02295 typedef map< SMDS_MeshElement*, int > TMapOfVolume;
02296 typedef map< SMDS_MeshElement*, int >::iterator TItrMapOfVolume;
02297 TMapOfVolume mapOfVol;
02298
02299 SMDS_ElemIteratorPtr nodeItr = aFace->nodesIterator();
02300 while ( nodeItr->more() ) {
02301 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(nodeItr->next());
02302 if ( !aNode ) continue;
02303 SMDS_ElemIteratorPtr volItr = aNode->GetInverseElementIterator(SMDSAbs_Volume);
02304 while ( volItr->more() ) {
02305 SMDS_MeshElement* aVol = (SMDS_MeshElement*)volItr->next();
02306 TItrMapOfVolume itr = mapOfVol.insert(make_pair(aVol, 0)).first;
02307 (*itr).second++;
02308 }
02309 }
02310 int nbVol = 0;
02311 TItrMapOfVolume volItr = mapOfVol.begin();
02312 TItrMapOfVolume volEnd = mapOfVol.end();
02313 for ( ; volItr != volEnd; ++volItr )
02314 if ( (*volItr).second >= nbNode )
02315 nbVol++;
02316
02317 return (nbVol < 2);
02318 }
02319
02320 SMDSAbs_ElementType FreeFaces::GetType() const
02321 {
02322 return SMDSAbs_Face;
02323 }
02324
02325
02326
02327
02328
02329
02330 LinearOrQuadratic::LinearOrQuadratic()
02331 {
02332 myMesh = 0;
02333 }
02334
02335 void LinearOrQuadratic::SetMesh( const SMDS_Mesh* theMesh )
02336 {
02337 myMesh = theMesh;
02338 }
02339
02340 bool LinearOrQuadratic::IsSatisfy( long theId )
02341 {
02342 if (!myMesh) return false;
02343 const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
02344 if ( !anElem || (myType != SMDSAbs_All && anElem->GetType() != myType) )
02345 return false;
02346 return (!anElem->IsQuadratic());
02347 }
02348
02349 void LinearOrQuadratic::SetType( SMDSAbs_ElementType theType )
02350 {
02351 myType = theType;
02352 }
02353
02354 SMDSAbs_ElementType LinearOrQuadratic::GetType() const
02355 {
02356 return myType;
02357 }
02358
02359
02360
02361
02362
02363
02364 GroupColor::GroupColor()
02365 {
02366 }
02367
02368 bool GroupColor::IsSatisfy( long theId )
02369 {
02370 return (myIDs.find( theId ) != myIDs.end());
02371 }
02372
02373 void GroupColor::SetType( SMDSAbs_ElementType theType )
02374 {
02375 myType = theType;
02376 }
02377
02378 SMDSAbs_ElementType GroupColor::GetType() const
02379 {
02380 return myType;
02381 }
02382
02383 static bool isEqual( const Quantity_Color& theColor1,
02384 const Quantity_Color& theColor2 )
02385 {
02386
02387 const double tol = 5*1e-3;
02388 return ( fabs( theColor1.Red() - theColor2.Red() ) < tol &&
02389 fabs( theColor1.Green() - theColor2.Green() ) < tol &&
02390 fabs( theColor1.Blue() - theColor2.Blue() ) < tol );
02391 }
02392
02393
02394 void GroupColor::SetMesh( const SMDS_Mesh* theMesh )
02395 {
02396 myIDs.clear();
02397
02398 const SMESHDS_Mesh* aMesh = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
02399 if ( !aMesh )
02400 return;
02401
02402 int nbGrp = aMesh->GetNbGroups();
02403 if ( !nbGrp )
02404 return;
02405
02406
02407 const std::set<SMESHDS_GroupBase*>& aGroups = aMesh->GetGroups();
02408 set<SMESHDS_GroupBase*>::const_iterator GrIt = aGroups.begin();
02409 for (; GrIt != aGroups.end(); GrIt++) {
02410 SMESHDS_GroupBase* aGrp = (*GrIt);
02411 if ( !aGrp )
02412 continue;
02413
02414 if ( !isEqual( myColor, aGrp->GetColor() ) )
02415 continue;
02416 if ( myType != SMDSAbs_All && myType != (SMDSAbs_ElementType)aGrp->GetType() )
02417 continue;
02418
02419 SMDSAbs_ElementType aGrpElType = (SMDSAbs_ElementType)aGrp->GetType();
02420 if ( myType == aGrpElType || (myType == SMDSAbs_All && aGrpElType != SMDSAbs_Node) ) {
02421
02422 int aSize = aGrp->Extent();
02423 for (int i = 0; i < aSize; i++)
02424 myIDs.insert( aGrp->GetID(i+1) );
02425 }
02426 }
02427 }
02428
02429 void GroupColor::SetColorStr( const TCollection_AsciiString& theStr )
02430 {
02431 TCollection_AsciiString aStr = theStr;
02432 aStr.RemoveAll( ' ' );
02433 aStr.RemoveAll( '\t' );
02434 for ( int aPos = aStr.Search( ";;" ); aPos != -1; aPos = aStr.Search( ";;" ) )
02435 aStr.Remove( aPos, 2 );
02436 Standard_Real clr[3];
02437 clr[0] = clr[1] = clr[2] = 0.;
02438 for ( int i = 0; i < 3; i++ ) {
02439 TCollection_AsciiString tmpStr = aStr.Token( ";", i+1 );
02440 if ( !tmpStr.IsEmpty() && tmpStr.IsRealValue() )
02441 clr[i] = tmpStr.RealValue();
02442 }
02443 myColor = Quantity_Color( clr[0], clr[1], clr[2], Quantity_TOC_RGB );
02444 }
02445
02446
02447
02448
02449
02450
02451 void GroupColor::GetColorStr( TCollection_AsciiString& theResStr ) const
02452 {
02453 theResStr.Clear();
02454 theResStr += TCollection_AsciiString( myColor.Red() );
02455 theResStr += TCollection_AsciiString( ";" ) + TCollection_AsciiString( myColor.Green() );
02456 theResStr += TCollection_AsciiString( ";" ) + TCollection_AsciiString( myColor.Blue() );
02457 }
02458
02459
02460
02461
02462
02463
02464 ElemGeomType::ElemGeomType()
02465 {
02466 myMesh = 0;
02467 myType = SMDSAbs_All;
02468 myGeomType = SMDSGeom_TRIANGLE;
02469 }
02470
02471 void ElemGeomType::SetMesh( const SMDS_Mesh* theMesh )
02472 {
02473 myMesh = theMesh;
02474 }
02475
02476 bool ElemGeomType::IsSatisfy( long theId )
02477 {
02478 if (!myMesh) return false;
02479 const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
02480 if ( !anElem )
02481 return false;
02482 const SMDSAbs_ElementType anElemType = anElem->GetType();
02483 if ( myType != SMDSAbs_All && anElemType != myType )
02484 return false;
02485 const int aNbNode = anElem->NbNodes();
02486 bool isOk = false;
02487 switch( anElemType )
02488 {
02489 case SMDSAbs_Node:
02490 isOk = (myGeomType == SMDSGeom_POINT);
02491 break;
02492
02493 case SMDSAbs_Edge:
02494 isOk = (myGeomType == SMDSGeom_EDGE);
02495 break;
02496
02497 case SMDSAbs_Face:
02498 if ( myGeomType == SMDSGeom_TRIANGLE )
02499 isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 6 : aNbNode == 3));
02500 else if ( myGeomType == SMDSGeom_QUADRANGLE )
02501 isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 8 : aNbNode == 4));
02502 else if ( myGeomType == SMDSGeom_POLYGON )
02503 isOk = anElem->IsPoly();
02504 break;
02505
02506 case SMDSAbs_Volume:
02507 if ( myGeomType == SMDSGeom_TETRA )
02508 isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 10 : aNbNode == 4));
02509 else if ( myGeomType == SMDSGeom_PYRAMID )
02510 isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 13 : aNbNode == 5));
02511 else if ( myGeomType == SMDSGeom_PENTA )
02512 isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 15 : aNbNode == 6));
02513 else if ( myGeomType == SMDSGeom_HEXA )
02514 isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 20 : aNbNode == 8));
02515 else if ( myGeomType == SMDSGeom_POLYHEDRA )
02516 isOk = anElem->IsPoly();
02517 break;
02518 default: break;
02519 }
02520 return isOk;
02521 }
02522
02523 void ElemGeomType::SetType( SMDSAbs_ElementType theType )
02524 {
02525 myType = theType;
02526 }
02527
02528 SMDSAbs_ElementType ElemGeomType::GetType() const
02529 {
02530 return myType;
02531 }
02532
02533 void ElemGeomType::SetGeomType( SMDSAbs_GeometryType theType )
02534 {
02535 myGeomType = theType;
02536 }
02537
02538 SMDSAbs_GeometryType ElemGeomType::GetGeomType() const
02539 {
02540 return myGeomType;
02541 }
02542
02543
02547
02548
02549 CoplanarFaces::CoplanarFaces()
02550 : myMesh(0), myFaceID(0), myToler(0)
02551 {
02552 }
02553 bool CoplanarFaces::IsSatisfy( long theElementId )
02554 {
02555 if ( myCoplanarIDs.empty() )
02556 {
02557
02558
02559 if ( !myMesh || !myFaceID || !myToler )
02560 return false;
02561
02562 const SMDS_MeshElement* face = myMesh->FindElement( myFaceID );
02563 if ( !face || face->GetType() != SMDSAbs_Face )
02564 return false;
02565
02566 bool normOK;
02567 gp_Vec myNorm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
02568 if (!normOK)
02569 return false;
02570
02571 const double radianTol = myToler * PI180;
02572 typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TFaceIt;
02573 std::set<const SMDS_MeshElement*> checkedFaces, checkedNodes;
02574 std::list<const SMDS_MeshElement*> faceQueue( 1, face );
02575 while ( !faceQueue.empty() )
02576 {
02577 face = faceQueue.front();
02578 if ( checkedFaces.insert( face ).second )
02579 {
02580 gp_Vec norm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
02581 if (!normOK || myNorm.Angle( norm ) <= radianTol)
02582 {
02583 myCoplanarIDs.insert( face->GetID() );
02584 std::set<const SMDS_MeshElement*> neighborFaces;
02585 for ( int i = 0; i < face->NbCornerNodes(); ++i )
02586 {
02587 const SMDS_MeshNode* n = face->GetNode( i );
02588 if ( checkedNodes.insert( n ).second )
02589 neighborFaces.insert( TFaceIt( n->GetInverseElementIterator(SMDSAbs_Face)),
02590 TFaceIt());
02591 }
02592 faceQueue.insert( faceQueue.end(), neighborFaces.begin(), neighborFaces.end() );
02593 }
02594 }
02595 faceQueue.pop_front();
02596 }
02597 }
02598 return myCoplanarIDs.count( theElementId );
02599 }
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614 RangeOfIds::RangeOfIds()
02615 {
02616 myMesh = 0;
02617 myType = SMDSAbs_All;
02618 }
02619
02620
02621
02622
02623
02624 void RangeOfIds::SetMesh( const SMDS_Mesh* theMesh )
02625 {
02626 myMesh = theMesh;
02627 }
02628
02629
02630
02631
02632
02633 bool RangeOfIds::AddToRange( long theEntityId )
02634 {
02635 myIds.Add( theEntityId );
02636 return true;
02637 }
02638
02639
02640
02641
02642
02643
02644 void RangeOfIds::GetRangeStr( TCollection_AsciiString& theResStr )
02645 {
02646 theResStr.Clear();
02647
02648 TColStd_SequenceOfInteger anIntSeq;
02649 TColStd_SequenceOfAsciiString aStrSeq;
02650
02651 TColStd_MapIteratorOfMapOfInteger anIter( myIds );
02652 for ( ; anIter.More(); anIter.Next() )
02653 {
02654 int anId = anIter.Key();
02655 TCollection_AsciiString aStr( anId );
02656 anIntSeq.Append( anId );
02657 aStrSeq.Append( aStr );
02658 }
02659
02660 for ( int i = 1, n = myMin.Length(); i <= n; i++ )
02661 {
02662 int aMinId = myMin( i );
02663 int aMaxId = myMax( i );
02664
02665 TCollection_AsciiString aStr;
02666 if ( aMinId != IntegerFirst() )
02667 aStr += aMinId;
02668
02669 aStr += "-";
02670
02671 if ( aMaxId != IntegerLast() )
02672 aStr += aMaxId;
02673
02674
02675 if ( anIntSeq.Length() == 0 )
02676 {
02677 anIntSeq.Append( aMinId );
02678 aStrSeq.Append( aStr );
02679 }
02680 else
02681 {
02682 if ( aMinId < anIntSeq.First() )
02683 {
02684 anIntSeq.Prepend( aMinId );
02685 aStrSeq.Prepend( aStr );
02686 }
02687 else if ( aMinId > anIntSeq.Last() )
02688 {
02689 anIntSeq.Append( aMinId );
02690 aStrSeq.Append( aStr );
02691 }
02692 else
02693 for ( int j = 1, k = anIntSeq.Length(); j <= k; j++ )
02694 if ( aMinId < anIntSeq( j ) )
02695 {
02696 anIntSeq.InsertBefore( j, aMinId );
02697 aStrSeq.InsertBefore( j, aStr );
02698 break;
02699 }
02700 }
02701 }
02702
02703 if ( aStrSeq.Length() == 0 )
02704 return;
02705
02706 theResStr = aStrSeq( 1 );
02707 for ( int j = 2, k = aStrSeq.Length(); j <= k; j++ )
02708 {
02709 theResStr += ",";
02710 theResStr += aStrSeq( j );
02711 }
02712 }
02713
02714
02715
02716
02717
02718
02719 bool RangeOfIds::SetRangeStr( const TCollection_AsciiString& theStr )
02720 {
02721 myMin.Clear();
02722 myMax.Clear();
02723 myIds.Clear();
02724
02725 TCollection_AsciiString aStr = theStr;
02726 aStr.RemoveAll( ' ' );
02727 aStr.RemoveAll( '\t' );
02728
02729 for ( int aPos = aStr.Search( ",," ); aPos != -1; aPos = aStr.Search( ",," ) )
02730 aStr.Remove( aPos, 2 );
02731
02732 TCollection_AsciiString tmpStr = aStr.Token( ",", 1 );
02733 int i = 1;
02734 while ( tmpStr != "" )
02735 {
02736 tmpStr = aStr.Token( ",", i++ );
02737 int aPos = tmpStr.Search( '-' );
02738
02739 if ( aPos == -1 )
02740 {
02741 if ( tmpStr.IsIntegerValue() )
02742 myIds.Add( tmpStr.IntegerValue() );
02743 else
02744 return false;
02745 }
02746 else
02747 {
02748 TCollection_AsciiString aMaxStr = tmpStr.Split( aPos );
02749 TCollection_AsciiString aMinStr = tmpStr;
02750
02751 while ( aMinStr.Search( "-" ) != -1 ) aMinStr.RemoveAll( '-' );
02752 while ( aMaxStr.Search( "-" ) != -1 ) aMaxStr.RemoveAll( '-' );
02753
02754 if ( (!aMinStr.IsEmpty() && !aMinStr.IsIntegerValue()) ||
02755 (!aMaxStr.IsEmpty() && !aMaxStr.IsIntegerValue()) )
02756 return false;
02757
02758 myMin.Append( aMinStr.IsEmpty() ? IntegerFirst() : aMinStr.IntegerValue() );
02759 myMax.Append( aMaxStr.IsEmpty() ? IntegerLast() : aMaxStr.IntegerValue() );
02760 }
02761 }
02762
02763 return true;
02764 }
02765
02766
02767
02768
02769
02770 SMDSAbs_ElementType RangeOfIds::GetType() const
02771 {
02772 return myType;
02773 }
02774
02775
02776
02777
02778
02779 void RangeOfIds::SetType( SMDSAbs_ElementType theType )
02780 {
02781 myType = theType;
02782 }
02783
02784
02785
02786
02787
02788 bool RangeOfIds::IsSatisfy( long theId )
02789 {
02790 if ( !myMesh )
02791 return false;
02792
02793 if ( myType == SMDSAbs_Node )
02794 {
02795 if ( myMesh->FindNode( theId ) == 0 )
02796 return false;
02797 }
02798 else
02799 {
02800 const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
02801 if ( anElem == 0 || (myType != anElem->GetType() && myType != SMDSAbs_All ))
02802 return false;
02803 }
02804
02805 if ( myIds.Contains( theId ) )
02806 return true;
02807
02808 for ( int i = 1, n = myMin.Length(); i <= n; i++ )
02809 if ( theId >= myMin( i ) && theId <= myMax( i ) )
02810 return true;
02811
02812 return false;
02813 }
02814
02815
02816
02817
02818
02819 Comparator::Comparator():
02820 myMargin(0)
02821 {}
02822
02823 Comparator::~Comparator()
02824 {}
02825
02826 void Comparator::SetMesh( const SMDS_Mesh* theMesh )
02827 {
02828 if ( myFunctor )
02829 myFunctor->SetMesh( theMesh );
02830 }
02831
02832 void Comparator::SetMargin( double theValue )
02833 {
02834 myMargin = theValue;
02835 }
02836
02837 void Comparator::SetNumFunctor( NumericalFunctorPtr theFunct )
02838 {
02839 myFunctor = theFunct;
02840 }
02841
02842 SMDSAbs_ElementType Comparator::GetType() const
02843 {
02844 return myFunctor ? myFunctor->GetType() : SMDSAbs_All;
02845 }
02846
02847 double Comparator::GetMargin()
02848 {
02849 return myMargin;
02850 }
02851
02852
02853
02854
02855
02856
02857 bool LessThan::IsSatisfy( long theId )
02858 {
02859 return myFunctor && myFunctor->GetValue( theId ) < myMargin;
02860 }
02861
02862
02863
02864
02865
02866
02867 bool MoreThan::IsSatisfy( long theId )
02868 {
02869 return myFunctor && myFunctor->GetValue( theId ) > myMargin;
02870 }
02871
02872
02873
02874
02875
02876
02877 EqualTo::EqualTo():
02878 myToler(Precision::Confusion())
02879 {}
02880
02881 bool EqualTo::IsSatisfy( long theId )
02882 {
02883 return myFunctor && fabs( myFunctor->GetValue( theId ) - myMargin ) < myToler;
02884 }
02885
02886 void EqualTo::SetTolerance( double theToler )
02887 {
02888 myToler = theToler;
02889 }
02890
02891 double EqualTo::GetTolerance()
02892 {
02893 return myToler;
02894 }
02895
02896
02897
02898
02899
02900 LogicalNOT::LogicalNOT()
02901 {}
02902
02903 LogicalNOT::~LogicalNOT()
02904 {}
02905
02906 bool LogicalNOT::IsSatisfy( long theId )
02907 {
02908 return myPredicate && !myPredicate->IsSatisfy( theId );
02909 }
02910
02911 void LogicalNOT::SetMesh( const SMDS_Mesh* theMesh )
02912 {
02913 if ( myPredicate )
02914 myPredicate->SetMesh( theMesh );
02915 }
02916
02917 void LogicalNOT::SetPredicate( PredicatePtr thePred )
02918 {
02919 myPredicate = thePred;
02920 }
02921
02922 SMDSAbs_ElementType LogicalNOT::GetType() const
02923 {
02924 return myPredicate ? myPredicate->GetType() : SMDSAbs_All;
02925 }
02926
02927
02928
02929
02930
02931
02932 LogicalBinary::LogicalBinary()
02933 {}
02934
02935 LogicalBinary::~LogicalBinary()
02936 {}
02937
02938 void LogicalBinary::SetMesh( const SMDS_Mesh* theMesh )
02939 {
02940 if ( myPredicate1 )
02941 myPredicate1->SetMesh( theMesh );
02942
02943 if ( myPredicate2 )
02944 myPredicate2->SetMesh( theMesh );
02945 }
02946
02947 void LogicalBinary::SetPredicate1( PredicatePtr thePredicate )
02948 {
02949 myPredicate1 = thePredicate;
02950 }
02951
02952 void LogicalBinary::SetPredicate2( PredicatePtr thePredicate )
02953 {
02954 myPredicate2 = thePredicate;
02955 }
02956
02957 SMDSAbs_ElementType LogicalBinary::GetType() const
02958 {
02959 if ( !myPredicate1 || !myPredicate2 )
02960 return SMDSAbs_All;
02961
02962 SMDSAbs_ElementType aType1 = myPredicate1->GetType();
02963 SMDSAbs_ElementType aType2 = myPredicate2->GetType();
02964
02965 return aType1 == aType2 ? aType1 : SMDSAbs_All;
02966 }
02967
02968
02969
02970
02971
02972
02973 bool LogicalAND::IsSatisfy( long theId )
02974 {
02975 return
02976 myPredicate1 &&
02977 myPredicate2 &&
02978 myPredicate1->IsSatisfy( theId ) &&
02979 myPredicate2->IsSatisfy( theId );
02980 }
02981
02982
02983
02984
02985
02986
02987 bool LogicalOR::IsSatisfy( long theId )
02988 {
02989 return
02990 myPredicate1 &&
02991 myPredicate2 &&
02992 (myPredicate1->IsSatisfy( theId ) ||
02993 myPredicate2->IsSatisfy( theId ));
02994 }
02995
02996
02997
02998
02999
03000
03001 Filter::Filter()
03002 {}
03003
03004 Filter::~Filter()
03005 {}
03006
03007 void Filter::SetPredicate( PredicatePtr thePredicate )
03008 {
03009 myPredicate = thePredicate;
03010 }
03011
03012 template<class TElement, class TIterator, class TPredicate>
03013 inline void FillSequence(const TIterator& theIterator,
03014 TPredicate& thePredicate,
03015 Filter::TIdSequence& theSequence)
03016 {
03017 if ( theIterator ) {
03018 while( theIterator->more() ) {
03019 TElement anElem = theIterator->next();
03020 long anId = anElem->GetID();
03021 if ( thePredicate->IsSatisfy( anId ) )
03022 theSequence.push_back( anId );
03023 }
03024 }
03025 }
03026
03027 void
03028 Filter::
03029 GetElementsId( const SMDS_Mesh* theMesh,
03030 PredicatePtr thePredicate,
03031 TIdSequence& theSequence )
03032 {
03033 theSequence.clear();
03034
03035 if ( !theMesh || !thePredicate )
03036 return;
03037
03038 thePredicate->SetMesh( theMesh );
03039
03040 SMDSAbs_ElementType aType = thePredicate->GetType();
03041 switch(aType){
03042 case SMDSAbs_Node:
03043 FillSequence<const SMDS_MeshNode*>(theMesh->nodesIterator(),thePredicate,theSequence);
03044 break;
03045 case SMDSAbs_Edge:
03046 FillSequence<const SMDS_MeshElement*>(theMesh->edgesIterator(),thePredicate,theSequence);
03047 break;
03048 case SMDSAbs_Face:
03049 FillSequence<const SMDS_MeshElement*>(theMesh->facesIterator(),thePredicate,theSequence);
03050 break;
03051 case SMDSAbs_Volume:
03052 FillSequence<const SMDS_MeshElement*>(theMesh->volumesIterator(),thePredicate,theSequence);
03053 break;
03054 case SMDSAbs_All:
03055 FillSequence<const SMDS_MeshElement*>(theMesh->edgesIterator(),thePredicate,theSequence);
03056 FillSequence<const SMDS_MeshElement*>(theMesh->facesIterator(),thePredicate,theSequence);
03057 FillSequence<const SMDS_MeshElement*>(theMesh->volumesIterator(),thePredicate,theSequence);
03058 break;
03059 }
03060 }
03061
03062 void
03063 Filter::GetElementsId( const SMDS_Mesh* theMesh,
03064 Filter::TIdSequence& theSequence )
03065 {
03066 GetElementsId(theMesh,myPredicate,theSequence);
03067 }
03068
03069
03070
03071
03072
03073 typedef std::set<SMDS_MeshFace*> TMapOfFacePtr;
03074
03075
03076
03077
03078
03079 ManifoldPart::Link::Link( SMDS_MeshNode* theNode1,
03080 SMDS_MeshNode* theNode2 )
03081 {
03082 myNode1 = theNode1;
03083 myNode2 = theNode2;
03084 }
03085
03086 ManifoldPart::Link::~Link()
03087 {
03088 myNode1 = 0;
03089 myNode2 = 0;
03090 }
03091
03092 bool ManifoldPart::Link::IsEqual( const ManifoldPart::Link& theLink ) const
03093 {
03094 if ( myNode1 == theLink.myNode1 &&
03095 myNode2 == theLink.myNode2 )
03096 return true;
03097 else if ( myNode1 == theLink.myNode2 &&
03098 myNode2 == theLink.myNode1 )
03099 return true;
03100 else
03101 return false;
03102 }
03103
03104 bool ManifoldPart::Link::operator<( const ManifoldPart::Link& x ) const
03105 {
03106 if(myNode1 < x.myNode1) return true;
03107 if(myNode1 == x.myNode1)
03108 if(myNode2 < x.myNode2) return true;
03109 return false;
03110 }
03111
03112 bool ManifoldPart::IsEqual( const ManifoldPart::Link& theLink1,
03113 const ManifoldPart::Link& theLink2 )
03114 {
03115 return theLink1.IsEqual( theLink2 );
03116 }
03117
03118 ManifoldPart::ManifoldPart()
03119 {
03120 myMesh = 0;
03121 myAngToler = Precision::Angular();
03122 myIsOnlyManifold = true;
03123 }
03124
03125 ManifoldPart::~ManifoldPart()
03126 {
03127 myMesh = 0;
03128 }
03129
03130 void ManifoldPart::SetMesh( const SMDS_Mesh* theMesh )
03131 {
03132 myMesh = theMesh;
03133 process();
03134 }
03135
03136 SMDSAbs_ElementType ManifoldPart::GetType() const
03137 { return SMDSAbs_Face; }
03138
03139 bool ManifoldPart::IsSatisfy( long theElementId )
03140 {
03141 return myMapIds.Contains( theElementId );
03142 }
03143
03144 void ManifoldPart::SetAngleTolerance( const double theAngToler )
03145 { myAngToler = theAngToler; }
03146
03147 double ManifoldPart::GetAngleTolerance() const
03148 { return myAngToler; }
03149
03150 void ManifoldPart::SetIsOnlyManifold( const bool theIsOnly )
03151 { myIsOnlyManifold = theIsOnly; }
03152
03153 void ManifoldPart::SetStartElem( const long theStartId )
03154 { myStartElemId = theStartId; }
03155
03156 bool ManifoldPart::process()
03157 {
03158 myMapIds.Clear();
03159 myMapBadGeomIds.Clear();
03160
03161 myAllFacePtr.clear();
03162 myAllFacePtrIntDMap.clear();
03163 if ( !myMesh )
03164 return false;
03165
03166
03167 SMDS_FaceIteratorPtr anFaceItr = myMesh->facesIterator();
03168 for (; anFaceItr->more(); )
03169 {
03170 SMDS_MeshFace* aFacePtr = (SMDS_MeshFace*)anFaceItr->next();
03171 myAllFacePtr.push_back( aFacePtr );
03172 myAllFacePtrIntDMap[aFacePtr] = myAllFacePtr.size()-1;
03173 }
03174
03175 SMDS_MeshFace* aStartFace = (SMDS_MeshFace*)myMesh->FindElement( myStartElemId );
03176 if ( !aStartFace )
03177 return false;
03178
03179
03180 TMapOfLink aMapOfNonManifold;
03181 TColStd_MapOfInteger aMapOfTreated;
03182
03183
03184
03185 const int aStartIndx = myAllFacePtrIntDMap[aStartFace];
03186 bool isStartTreat = false;
03187 for ( int fi = aStartIndx; !isStartTreat || fi != aStartIndx ; fi++ )
03188 {
03189 if ( fi == aStartIndx )
03190 isStartTreat = true;
03191
03192
03193 SMDS_MeshFace* aFacePtr = myAllFacePtr[ fi ];
03194 if ( aMapOfTreated.Contains( aFacePtr->GetID() ) )
03195 continue;
03196
03197 aMapOfTreated.Add( aFacePtr->GetID() );
03198 TColStd_MapOfInteger aResFaces;
03199 if ( !findConnected( myAllFacePtrIntDMap, aFacePtr,
03200 aMapOfNonManifold, aResFaces ) )
03201 continue;
03202 TColStd_MapIteratorOfMapOfInteger anItr( aResFaces );
03203 for ( ; anItr.More(); anItr.Next() )
03204 {
03205 int aFaceId = anItr.Key();
03206 aMapOfTreated.Add( aFaceId );
03207 myMapIds.Add( aFaceId );
03208 }
03209
03210 if ( fi == ( myAllFacePtr.size() - 1 ) )
03211 fi = 0;
03212 }
03213 return !myMapIds.IsEmpty();
03214 }
03215
03216 static void getLinks( const SMDS_MeshFace* theFace,
03217 ManifoldPart::TVectorOfLink& theLinks )
03218 {
03219 int aNbNode = theFace->NbNodes();
03220 SMDS_ElemIteratorPtr aNodeItr = theFace->nodesIterator();
03221 int i = 1;
03222 SMDS_MeshNode* aNode = 0;
03223 for ( ; aNodeItr->more() && i <= aNbNode; )
03224 {
03225
03226 SMDS_MeshNode* aN1 = (SMDS_MeshNode*)aNodeItr->next();
03227 if ( i == 1 )
03228 aNode = aN1;
03229 i++;
03230 SMDS_MeshNode* aN2 = ( i >= aNbNode ) ? aNode : (SMDS_MeshNode*)aNodeItr->next();
03231 i++;
03232 ManifoldPart::Link aLink( aN1, aN2 );
03233 theLinks.push_back( aLink );
03234 }
03235 }
03236
03237 bool ManifoldPart::findConnected
03238 ( const ManifoldPart::TDataMapFacePtrInt& theAllFacePtrInt,
03239 SMDS_MeshFace* theStartFace,
03240 ManifoldPart::TMapOfLink& theNonManifold,
03241 TColStd_MapOfInteger& theResFaces )
03242 {
03243 theResFaces.Clear();
03244 if ( !theAllFacePtrInt.size() )
03245 return false;
03246
03247 if ( getNormale( theStartFace ).SquareModulus() <= gp::Resolution() )
03248 {
03249 myMapBadGeomIds.Add( theStartFace->GetID() );
03250 return false;
03251 }
03252
03253 ManifoldPart::TMapOfLink aMapOfBoundary, aMapToSkip;
03254 ManifoldPart::TVectorOfLink aSeqOfBoundary;
03255 theResFaces.Add( theStartFace->GetID() );
03256 ManifoldPart::TDataMapOfLinkFacePtr aDMapLinkFace;
03257
03258 expandBoundary( aMapOfBoundary, aSeqOfBoundary,
03259 aDMapLinkFace, theNonManifold, theStartFace );
03260
03261 bool isDone = false;
03262 while ( !isDone && aMapOfBoundary.size() != 0 )
03263 {
03264 bool isToReset = false;
03265 ManifoldPart::TVectorOfLink::iterator pLink = aSeqOfBoundary.begin();
03266 for ( ; !isToReset && pLink != aSeqOfBoundary.end(); ++pLink )
03267 {
03268 ManifoldPart::Link aLink = *pLink;
03269 if ( aMapToSkip.find( aLink ) != aMapToSkip.end() )
03270 continue;
03271
03272 aMapToSkip.insert( aLink );
03273
03274 ManifoldPart::TVectorOfFacePtr aFaces;
03275
03276 if ( myIsOnlyManifold &&
03277 (theNonManifold.find( aLink ) != theNonManifold.end()) )
03278 continue;
03279 else
03280 {
03281 getFacesByLink( aLink, aFaces );
03282
03283 ManifoldPart::TVectorOfFacePtr aFiltered;
03284 ManifoldPart::TVectorOfFacePtr::iterator pFace = aFaces.begin();
03285 for ( ; pFace != aFaces.end(); ++pFace )
03286 {
03287 SMDS_MeshFace* aFace = *pFace;
03288 if ( myAllFacePtrIntDMap.find( aFace ) != myAllFacePtrIntDMap.end() )
03289 aFiltered.push_back( aFace );
03290 }
03291 aFaces = aFiltered;
03292 if ( aFaces.size() < 2 )
03293 continue;
03294 else if ( myIsOnlyManifold && aFaces.size() > 2 )
03295 {
03296 theNonManifold.insert( aLink );
03297 continue;
03298 }
03299 }
03300
03301
03302 SMDS_MeshFace* aPrevFace = aDMapLinkFace[ aLink ];
03303 ManifoldPart::TVectorOfFacePtr::iterator pFace = aFaces.begin();
03304 for ( ; pFace != aFaces.end(); ++pFace )
03305 {
03306 SMDS_MeshFace* aNextFace = *pFace;
03307 if ( aPrevFace == aNextFace )
03308 continue;
03309 int anNextFaceID = aNextFace->GetID();
03310 if ( myIsOnlyManifold && theResFaces.Contains( anNextFaceID ) )
03311
03312 continue;
03313
03314 if ( myMapBadGeomIds.Contains( anNextFaceID ) ||
03315 !isInPlane( aPrevFace, aNextFace ) )
03316 continue;
03317
03318 theResFaces.Add( anNextFaceID );
03319 expandBoundary( aMapOfBoundary, aSeqOfBoundary,
03320 aDMapLinkFace, theNonManifold, aNextFace );
03321 isToReset = true;
03322 }
03323 }
03324 isDone = !isToReset;
03325 }
03326
03327 return !theResFaces.IsEmpty();
03328 }
03329
03330 bool ManifoldPart::isInPlane( const SMDS_MeshFace* theFace1,
03331 const SMDS_MeshFace* theFace2 )
03332 {
03333 gp_Dir aNorm1 = gp_Dir( getNormale( theFace1 ) );
03334 gp_XYZ aNorm2XYZ = getNormale( theFace2 );
03335 if ( aNorm2XYZ.SquareModulus() <= gp::Resolution() )
03336 {
03337 myMapBadGeomIds.Add( theFace2->GetID() );
03338 return false;
03339 }
03340 if ( aNorm1.IsParallel( gp_Dir( aNorm2XYZ ), myAngToler ) )
03341 return true;
03342
03343 return false;
03344 }
03345
03346 void ManifoldPart::expandBoundary
03347 ( ManifoldPart::TMapOfLink& theMapOfBoundary,
03348 ManifoldPart::TVectorOfLink& theSeqOfBoundary,
03349 ManifoldPart::TDataMapOfLinkFacePtr& theDMapLinkFacePtr,
03350 ManifoldPart::TMapOfLink& theNonManifold,
03351 SMDS_MeshFace* theNextFace ) const
03352 {
03353 ManifoldPart::TVectorOfLink aLinks;
03354 getLinks( theNextFace, aLinks );
03355 int aNbLink = (int)aLinks.size();
03356 for ( int i = 0; i < aNbLink; i++ )
03357 {
03358 ManifoldPart::Link aLink = aLinks[ i ];
03359 if ( myIsOnlyManifold && (theNonManifold.find( aLink ) != theNonManifold.end()) )
03360 continue;
03361 if ( theMapOfBoundary.find( aLink ) != theMapOfBoundary.end() )
03362 {
03363 if ( myIsOnlyManifold )
03364 {
03365
03366 theMapOfBoundary.erase( aLink );
03367 ManifoldPart::TVectorOfLink::iterator pLink = theSeqOfBoundary.begin();
03368 for ( ; pLink != theSeqOfBoundary.end(); ++pLink )
03369 {
03370 ManifoldPart::Link aBoundLink = *pLink;
03371 if ( aBoundLink.IsEqual( aLink ) )
03372 {
03373 theSeqOfBoundary.erase( pLink );
03374 break;
03375 }
03376 }
03377 }
03378 }
03379 else
03380 {
03381 theMapOfBoundary.insert( aLink );
03382 theSeqOfBoundary.push_back( aLink );
03383 theDMapLinkFacePtr[ aLink ] = theNextFace;
03384 }
03385 }
03386 }
03387
03388 void ManifoldPart::getFacesByLink( const ManifoldPart::Link& theLink,
03389 ManifoldPart::TVectorOfFacePtr& theFaces ) const
03390 {
03391 std::set<SMDS_MeshCell *> aSetOfFaces;
03392
03393 SMDS_ElemIteratorPtr anItr = theLink.myNode1->facesIterator();
03394 for ( ; anItr->more(); )
03395 {
03396 SMDS_MeshFace* aFace = (SMDS_MeshFace*)anItr->next();
03397 if ( !aFace )
03398 continue;
03399 aSetOfFaces.insert( aFace );
03400 }
03401
03402 anItr = theLink.myNode2->facesIterator();
03403
03404 for ( ; anItr->more(); )
03405 {
03406 SMDS_MeshFace* aFace = (SMDS_MeshFace*)anItr->next();
03407 if ( aSetOfFaces.count( aFace ) )
03408 theFaces.push_back( aFace );
03409 }
03410 }
03411
03412
03413
03414
03415
03416
03417 ElementsOnSurface::ElementsOnSurface()
03418 {
03419 myMesh = 0;
03420 myIds.Clear();
03421 myType = SMDSAbs_All;
03422 mySurf.Nullify();
03423 myToler = Precision::Confusion();
03424 myUseBoundaries = false;
03425 }
03426
03427 ElementsOnSurface::~ElementsOnSurface()
03428 {
03429 myMesh = 0;
03430 }
03431
03432 void ElementsOnSurface::SetMesh( const SMDS_Mesh* theMesh )
03433 {
03434 if ( myMesh == theMesh )
03435 return;
03436 myMesh = theMesh;
03437 process();
03438 }
03439
03440 bool ElementsOnSurface::IsSatisfy( long theElementId )
03441 {
03442 return myIds.Contains( theElementId );
03443 }
03444
03445 SMDSAbs_ElementType ElementsOnSurface::GetType() const
03446 { return myType; }
03447
03448 void ElementsOnSurface::SetTolerance( const double theToler )
03449 {
03450 if ( myToler != theToler )
03451 myIds.Clear();
03452 myToler = theToler;
03453 }
03454
03455 double ElementsOnSurface::GetTolerance() const
03456 { return myToler; }
03457
03458 void ElementsOnSurface::SetUseBoundaries( bool theUse )
03459 {
03460 if ( myUseBoundaries != theUse ) {
03461 myUseBoundaries = theUse;
03462 SetSurface( mySurf, myType );
03463 }
03464 }
03465
03466 void ElementsOnSurface::SetSurface( const TopoDS_Shape& theShape,
03467 const SMDSAbs_ElementType theType )
03468 {
03469 myIds.Clear();
03470 myType = theType;
03471 mySurf.Nullify();
03472 if ( theShape.IsNull() || theShape.ShapeType() != TopAbs_FACE )
03473 return;
03474 mySurf = TopoDS::Face( theShape );
03475 BRepAdaptor_Surface SA( mySurf, myUseBoundaries );
03476 Standard_Real
03477 u1 = SA.FirstUParameter(),
03478 u2 = SA.LastUParameter(),
03479 v1 = SA.FirstVParameter(),
03480 v2 = SA.LastVParameter();
03481 Handle(Geom_Surface) surf = BRep_Tool::Surface( mySurf );
03482 myProjector.Init( surf, u1,u2, v1,v2 );
03483 process();
03484 }
03485
03486 void ElementsOnSurface::process()
03487 {
03488 myIds.Clear();
03489 if ( mySurf.IsNull() )
03490 return;
03491
03492 if ( myMesh == 0 )
03493 return;
03494
03495 if ( myType == SMDSAbs_Face || myType == SMDSAbs_All )
03496 {
03497 myIds.ReSize( myMesh->NbFaces() );
03498 SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
03499 for(; anIter->more(); )
03500 process( anIter->next() );
03501 }
03502
03503 if ( myType == SMDSAbs_Edge || myType == SMDSAbs_All )
03504 {
03505 myIds.ReSize( myIds.Extent() + myMesh->NbEdges() );
03506 SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
03507 for(; anIter->more(); )
03508 process( anIter->next() );
03509 }
03510
03511 if ( myType == SMDSAbs_Node )
03512 {
03513 myIds.ReSize( myMesh->NbNodes() );
03514 SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
03515 for(; anIter->more(); )
03516 process( anIter->next() );
03517 }
03518 }
03519
03520 void ElementsOnSurface::process( const SMDS_MeshElement* theElemPtr )
03521 {
03522 SMDS_ElemIteratorPtr aNodeItr = theElemPtr->nodesIterator();
03523 bool isSatisfy = true;
03524 for ( ; aNodeItr->more(); )
03525 {
03526 SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next();
03527 if ( !isOnSurface( aNode ) )
03528 {
03529 isSatisfy = false;
03530 break;
03531 }
03532 }
03533 if ( isSatisfy )
03534 myIds.Add( theElemPtr->GetID() );
03535 }
03536
03537 bool ElementsOnSurface::isOnSurface( const SMDS_MeshNode* theNode )
03538 {
03539 if ( mySurf.IsNull() )
03540 return false;
03541
03542 gp_Pnt aPnt( theNode->X(), theNode->Y(), theNode->Z() );
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563 myProjector.Perform( aPnt );
03564 bool isOn = ( myProjector.IsDone() && myProjector.LowerDistance() <= myToler );
03565
03566 return isOn;
03567 }
03568
03569
03570
03571
03572
03573
03574 ElementsOnShape::ElementsOnShape()
03575 : myMesh(0),
03576 myType(SMDSAbs_All),
03577 myToler(Precision::Confusion()),
03578 myAllNodesFlag(false)
03579 {
03580 myCurShapeType = TopAbs_SHAPE;
03581 }
03582
03583 ElementsOnShape::~ElementsOnShape()
03584 {
03585 }
03586
03587 void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
03588 {
03589 if (myMesh != theMesh) {
03590 myMesh = theMesh;
03591 SetShape(myShape, myType);
03592 }
03593 }
03594
03595 bool ElementsOnShape::IsSatisfy (long theElementId)
03596 {
03597 return myIds.Contains(theElementId);
03598 }
03599
03600 SMDSAbs_ElementType ElementsOnShape::GetType() const
03601 {
03602 return myType;
03603 }
03604
03605 void ElementsOnShape::SetTolerance (const double theToler)
03606 {
03607 if (myToler != theToler) {
03608 myToler = theToler;
03609 SetShape(myShape, myType);
03610 }
03611 }
03612
03613 double ElementsOnShape::GetTolerance() const
03614 {
03615 return myToler;
03616 }
03617
03618 void ElementsOnShape::SetAllNodes (bool theAllNodes)
03619 {
03620 if (myAllNodesFlag != theAllNodes) {
03621 myAllNodesFlag = theAllNodes;
03622 SetShape(myShape, myType);
03623 }
03624 }
03625
03626 void ElementsOnShape::SetShape (const TopoDS_Shape& theShape,
03627 const SMDSAbs_ElementType theType)
03628 {
03629 myType = theType;
03630 myShape = theShape;
03631 myIds.Clear();
03632
03633 if (myMesh == 0) return;
03634
03635 switch (myType)
03636 {
03637 case SMDSAbs_All:
03638 myIds.ReSize(myMesh->NbEdges() + myMesh->NbFaces() + myMesh->NbVolumes());
03639 break;
03640 case SMDSAbs_Node:
03641 myIds.ReSize(myMesh->NbNodes());
03642 break;
03643 case SMDSAbs_Edge:
03644 myIds.ReSize(myMesh->NbEdges());
03645 break;
03646 case SMDSAbs_Face:
03647 myIds.ReSize(myMesh->NbFaces());
03648 break;
03649 case SMDSAbs_Volume:
03650 myIds.ReSize(myMesh->NbVolumes());
03651 break;
03652 default:
03653 break;
03654 }
03655
03656 myShapesMap.Clear();
03657 addShape(myShape);
03658 }
03659
03660 void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
03661 {
03662 if (theShape.IsNull() || myMesh == 0)
03663 return;
03664
03665 if (!myShapesMap.Add(theShape)) return;
03666
03667 myCurShapeType = theShape.ShapeType();
03668 switch (myCurShapeType)
03669 {
03670 case TopAbs_COMPOUND:
03671 case TopAbs_COMPSOLID:
03672 case TopAbs_SHELL:
03673 case TopAbs_WIRE:
03674 {
03675 TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
03676 for (; anIt.More(); anIt.Next()) addShape(anIt.Value());
03677 }
03678 break;
03679 case TopAbs_SOLID:
03680 {
03681 myCurSC.Load(theShape);
03682 process();
03683 }
03684 break;
03685 case TopAbs_FACE:
03686 {
03687 TopoDS_Face aFace = TopoDS::Face(theShape);
03688 BRepAdaptor_Surface SA (aFace, true);
03689 Standard_Real
03690 u1 = SA.FirstUParameter(),
03691 u2 = SA.LastUParameter(),
03692 v1 = SA.FirstVParameter(),
03693 v2 = SA.LastVParameter();
03694 Handle(Geom_Surface) surf = BRep_Tool::Surface(aFace);
03695 myCurProjFace.Init(surf, u1,u2, v1,v2);
03696 myCurFace = aFace;
03697 process();
03698 }
03699 break;
03700 case TopAbs_EDGE:
03701 {
03702 TopoDS_Edge anEdge = TopoDS::Edge(theShape);
03703 Standard_Real u1, u2;
03704 Handle(Geom_Curve) curve = BRep_Tool::Curve(anEdge, u1, u2);
03705 myCurProjEdge.Init(curve, u1, u2);
03706 process();
03707 }
03708 break;
03709 case TopAbs_VERTEX:
03710 {
03711 TopoDS_Vertex aV = TopoDS::Vertex(theShape);
03712 myCurPnt = BRep_Tool::Pnt(aV);
03713 process();
03714 }
03715 break;
03716 default:
03717 break;
03718 }
03719 }
03720
03721 void ElementsOnShape::process()
03722 {
03723 if (myShape.IsNull() || myMesh == 0)
03724 return;
03725
03726 if (myType == SMDSAbs_Node)
03727 {
03728 SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
03729 while (anIter->more())
03730 process(anIter->next());
03731 }
03732 else
03733 {
03734 if (myType == SMDSAbs_Edge || myType == SMDSAbs_All)
03735 {
03736 SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
03737 while (anIter->more())
03738 process(anIter->next());
03739 }
03740
03741 if (myType == SMDSAbs_Face || myType == SMDSAbs_All)
03742 {
03743 SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
03744 while (anIter->more()) {
03745 process(anIter->next());
03746 }
03747 }
03748
03749 if (myType == SMDSAbs_Volume || myType == SMDSAbs_All)
03750 {
03751 SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
03752 while (anIter->more())
03753 process(anIter->next());
03754 }
03755 }
03756 }
03757
03758 void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr)
03759 {
03760 if (myShape.IsNull())
03761 return;
03762
03763 SMDS_ElemIteratorPtr aNodeItr = theElemPtr->nodesIterator();
03764 bool isSatisfy = myAllNodesFlag;
03765
03766 gp_XYZ centerXYZ (0, 0, 0);
03767
03768 while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
03769 {
03770 SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next();
03771 gp_Pnt aPnt (aNode->X(), aNode->Y(), aNode->Z());
03772 centerXYZ += aPnt.XYZ();
03773
03774 switch (myCurShapeType)
03775 {
03776 case TopAbs_SOLID:
03777 {
03778 myCurSC.Perform(aPnt, myToler);
03779 isSatisfy = (myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON);
03780 }
03781 break;
03782 case TopAbs_FACE:
03783 {
03784 myCurProjFace.Perform(aPnt);
03785 isSatisfy = (myCurProjFace.IsDone() && myCurProjFace.LowerDistance() <= myToler);
03786 if (isSatisfy)
03787 {
03788
03789 Quantity_Parameter u, v;
03790 myCurProjFace.LowerDistanceParameters(u, v);
03791 gp_Pnt2d aProjPnt (u, v);
03792 BRepClass_FaceClassifier aClsf (myCurFace, aProjPnt, myToler);
03793 isSatisfy = (aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON);
03794 }
03795 }
03796 break;
03797 case TopAbs_EDGE:
03798 {
03799 myCurProjEdge.Perform(aPnt);
03800 isSatisfy = (myCurProjEdge.NbPoints() > 0 && myCurProjEdge.LowerDistance() <= myToler);
03801 }
03802 break;
03803 case TopAbs_VERTEX:
03804 {
03805 isSatisfy = (aPnt.Distance(myCurPnt) <= myToler);
03806 }
03807 break;
03808 default:
03809 {
03810 isSatisfy = false;
03811 }
03812 }
03813 }
03814
03815 if (isSatisfy && myCurShapeType == TopAbs_SOLID) {
03816 centerXYZ /= theElemPtr->NbNodes();
03817 gp_Pnt aCenterPnt (centerXYZ);
03818 myCurSC.Perform(aCenterPnt, myToler);
03819 if ( !(myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON))
03820 isSatisfy = false;
03821 }
03822
03823 if (isSatisfy)
03824 myIds.Add(theElemPtr->GetID());
03825 }
03826
03827 TSequenceOfXYZ::TSequenceOfXYZ()
03828 {}
03829
03830 TSequenceOfXYZ::TSequenceOfXYZ(size_type n) : myArray(n)
03831 {}
03832
03833 TSequenceOfXYZ::TSequenceOfXYZ(size_type n, const gp_XYZ& t) : myArray(n,t)
03834 {}
03835
03836 TSequenceOfXYZ::TSequenceOfXYZ(const TSequenceOfXYZ& theSequenceOfXYZ) : myArray(theSequenceOfXYZ.myArray)
03837 {}
03838
03839 template <class InputIterator>
03840 TSequenceOfXYZ::TSequenceOfXYZ(InputIterator theBegin, InputIterator theEnd): myArray(theBegin,theEnd)
03841 {}
03842
03843 TSequenceOfXYZ::~TSequenceOfXYZ()
03844 {}
03845
03846 TSequenceOfXYZ& TSequenceOfXYZ::operator=(const TSequenceOfXYZ& theSequenceOfXYZ)
03847 {
03848 myArray = theSequenceOfXYZ.myArray;
03849 return *this;
03850 }
03851
03852 gp_XYZ& TSequenceOfXYZ::operator()(size_type n)
03853 {
03854 return myArray[n-1];
03855 }
03856
03857 const gp_XYZ& TSequenceOfXYZ::operator()(size_type n) const
03858 {
03859 return myArray[n-1];
03860 }
03861
03862 void TSequenceOfXYZ::clear()
03863 {
03864 myArray.clear();
03865 }
03866
03867 void TSequenceOfXYZ::reserve(size_type n)
03868 {
03869 myArray.reserve(n);
03870 }
03871
03872 void TSequenceOfXYZ::push_back(const gp_XYZ& v)
03873 {
03874 myArray.push_back(v);
03875 }
03876
03877 TSequenceOfXYZ::size_type TSequenceOfXYZ::size() const
03878 {
03879 return myArray.size();
03880 }