Fix for the "0021861: EDF 2226 : Documentation of numeric functor option in split quadrangles is unclear" issue.

This commit is contained in:
ana 2012-11-01 11:39:48 +00:00
parent 7348db21e5
commit f0bf265fc0
8 changed files with 86 additions and 56 deletions

View File

@ -429,59 +429,56 @@ SMDSAbs_ElementType Volume::GetType() const
Class : MaxElementLength2D
Description : Functor calculating maximum length of 2D element
*/
double MaxElementLength2D::GetValue( const TSequenceOfXYZ& P )
{
if(P.size() == 0)
return 0.;
double aVal = 0;
int len = P.size();
if( len == 3 ) { // triangles
double L1 = getDistance(P( 1 ),P( 2 ));
double L2 = getDistance(P( 2 ),P( 3 ));
double L3 = getDistance(P( 3 ),P( 1 ));
aVal = Max(L1,Max(L2,L3));
}
else if( len == 4 ) { // quadrangles
double L1 = getDistance(P( 1 ),P( 2 ));
double L2 = getDistance(P( 2 ),P( 3 ));
double L3 = getDistance(P( 3 ),P( 4 ));
double L4 = getDistance(P( 4 ),P( 1 ));
double D1 = getDistance(P( 1 ),P( 3 ));
double D2 = getDistance(P( 2 ),P( 4 ));
aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
}
else if( len == 6 ) { // quadratic triangles
double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
aVal = Max(L1,Max(L2,L3));
}
else if( len == 8 || len == 9 ) { // quadratic quadrangles
double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
double D1 = getDistance(P( 1 ),P( 5 ));
double D2 = getDistance(P( 3 ),P( 7 ));
aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
}
if( myPrecision >= 0 )
{
double prec = pow( 10., (double)myPrecision );
aVal = floor( aVal * prec + 0.5 ) / prec;
}
return aVal;
}
double MaxElementLength2D::GetValue( long theElementId )
{
TSequenceOfXYZ P;
if( GetPoints( theElementId, P ) ) {
double aVal = 0;
const SMDS_MeshElement* aElem = myMesh->FindElement( theElementId );
SMDSAbs_ElementType aType = aElem->GetType();
int len = P.size();
switch( aType ) {
case SMDSAbs_Face:
if( len == 3 ) { // triangles
double L1 = getDistance(P( 1 ),P( 2 ));
double L2 = getDistance(P( 2 ),P( 3 ));
double L3 = getDistance(P( 3 ),P( 1 ));
aVal = Max(L1,Max(L2,L3));
break;
}
else if( len == 4 ) { // quadrangles
double L1 = getDistance(P( 1 ),P( 2 ));
double L2 = getDistance(P( 2 ),P( 3 ));
double L3 = getDistance(P( 3 ),P( 4 ));
double L4 = getDistance(P( 4 ),P( 1 ));
double D1 = getDistance(P( 1 ),P( 3 ));
double D2 = getDistance(P( 2 ),P( 4 ));
aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
break;
}
else if( len == 6 ) { // quadratic triangles
double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
aVal = Max(L1,Max(L2,L3));
break;
}
else if( len == 8 || len == 9 ) { // quadratic quadrangles
double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
double D1 = getDistance(P( 1 ),P( 5 ));
double D2 = getDistance(P( 3 ),P( 7 ));
aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
break;
}
}
if( myPrecision >= 0 )
{
double prec = pow( 10., (double)myPrecision );
aVal = floor( aVal * prec + 0.5 ) / prec;
}
return aVal;
if( GetPoints( theElementId, P ) && myMesh->FindElement( theElementId )->GetType() == SMDSAbs_Face) {
GetValue(P);
}
return 0.;
}

View File

@ -162,6 +162,7 @@ namespace SMESH{
class SMESHCONTROLS_EXPORT MaxElementLength2D: public virtual NumericalFunctor{
public:
virtual double GetValue( long theElementId );
virtual double GetValue( const TSequenceOfXYZ& P );
virtual double GetBadRate( double Value, int nbNodes ) const;
virtual SMDSAbs_ElementType GetType() const;
};

View File

@ -1267,7 +1267,8 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
if( !elem->IsQuadratic() ) {
// split liner quadrangle
// for MaxElementLength2D functor we return minimum diagonal for splitting,
// because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
if ( aBadRate1 <= aBadRate2 ) {
// tr1 + tr2 is better
newElem1 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
@ -1401,7 +1402,8 @@ int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement* theQuad,
SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
// for MaxElementLength2D functor we return minimum diagonal for splitting,
// because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
return 1; // diagonal 1-3

View File

@ -225,7 +225,7 @@ QWidget* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool
myComboBoxFunctor->addItem(tr("ASPECTRATIO_ELEMENTS"));
myComboBoxFunctor->addItem(tr("MINIMUMANGLE_ELEMENTS"));
myComboBoxFunctor->addItem(tr("SKEW_ELEMENTS"));
myComboBoxFunctor->addItem(tr("AREA_ELEMENTS"));
//myComboBoxFunctor->addItem(tr("AREA_ELEMENTS"));
//myComboBoxFunctor->addItem(tr("LENGTH2D_EDGES")); // for existing elements only
//myComboBoxFunctor->addItem(tr("MULTI2D_BORDERS")); // for existing elements only
myComboBoxFunctor->setCurrentIndex(0);
@ -362,6 +362,8 @@ SMESH::NumericalFunctor_ptr SMESHGUI_MultiEditDlg::getNumericalFunctor()
aNF = aFilterMgr->CreateLength2D();
else if (myComboBoxFunctor->currentText() == tr("MULTI2D_BORDERS"))
aNF = aFilterMgr->CreateMultiConnection2D();
else if (myComboBoxFunctor->currentText() == tr("MIN_DIAG_ELEMENTS"))
aNF = aFilterMgr->CreateMaxElementLength2D();
else;
return aNF._retn();
@ -1154,6 +1156,7 @@ SMESHGUI_UnionOfTrianglesDlg
setWindowTitle(tr("CAPTION"));
myComboBoxFunctor->setEnabled(true);
myComboBoxFunctor->addItem(tr("AREA_ELEMENTS"));
myComboBoxFunctor->addItem(tr("WARP_ELEMENTS")); // for quadrangles only
myComboBoxFunctor->addItem(tr("TAPER_ELEMENTS")); // for quadrangles only
@ -1240,6 +1243,8 @@ SMESHGUI_CuttingOfQuadsDlg
myCriterionGrp->show();
myChoiceWidget->show();
myComboBoxFunctor->insertItem(0, tr("MIN_DIAG_ELEMENTS"));
myComboBoxFunctor->setCurrentIndex(0);
myComboBoxFunctor->setEnabled(false);
connect(myPreviewChk, SIGNAL(stateChanged(int)), this, SLOT(onPreviewChk()));

View File

@ -63,6 +63,10 @@
<source>AREA_ELEMENTS</source>
<translation>Area</translation>
</message>
<message>
<source>MIN_DIAG_ELEMENTS</source>
<translation>Minimum diagonal</translation>
</message>
<message>
<source>ASPECTRATIO_3D_ELEMENTS</source>
<translation>Aspect Ratio 3D</translation>

View File

@ -2125,6 +2125,17 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
theCommand->SetArg( 3, face );
}
if(method == "QuadToTri" || method == "QuadToTriObject")
{
int crit_arg = theCommand->GetNbArgs();
_AString crit = theCommand->GetArg(crit_arg);
if(crit.Search("MaxElementLength2D") != -1)
{
theCommand->SetArg(crit_arg, "");
isPyMeshMethod = true;
}
}
if ( isPyMeshMethod )
{
theCommand->SetObject( myMesh );

View File

@ -1546,7 +1546,7 @@ CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfE
dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
SMESH::Controls::NumericalFunctorPtr aCrit;
if ( !aNumericalFunctor )
aCrit.reset( new SMESH::Controls::AspectRatio() );
aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
else
aCrit = aNumericalFunctor->GetNumericalFunctor();

View File

@ -2682,23 +2682,33 @@ class Mesh:
return self.editor.TriToQuadObject(theObject, self.smeshpyD.GetFunctor(theCriterion), MaxAngle)
## Splits quadrangles into triangles.
#
# If @a theCriterion is None, quadrangles will be split by the smallest diagonal.
#
# @param IDsOfElements the faces to be splitted.
# @param theCriterion FT_...; used to choose a diagonal for splitting.
# @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_cutquadr
def QuadToTri (self, IDsOfElements, theCriterion):
def QuadToTri (self, IDsOfElements, theCriterion = None):
if IDsOfElements == []:
IDsOfElements = self.GetElementsId()
if theCriterion is None:
theCriterion = FT_MaxElementLength2D
return self.editor.QuadToTri(IDsOfElements, self.smeshpyD.GetFunctor(theCriterion))
## Splits quadrangles into triangles.
#
# If @a theCriterion is None, quadrangles will be split by the smallest diagonal.
#
# @param theObject the object from which the list of elements is taken, this is mesh, submesh or group
# @param theCriterion FT_...; used to choose a diagonal for splitting.
# @return TRUE in case of success, FALSE otherwise.
# @ingroup l2_modif_cutquadr
def QuadToTriObject (self, theObject, theCriterion):
def QuadToTriObject (self, theObject, theCriterion = None):
if ( isinstance( theObject, Mesh )):
theObject = theObject.GetMesh()
if theCriterion is None:
theCriterion = FT_MaxElementLength2D
return self.editor.QuadToTriObject(theObject, self.smeshpyD.GetFunctor(theCriterion))
## Splits quadrangles into triangles.