mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2025-01-28 08:40:32 +05:00
52568: Quadrangle (Mapping) differently meshes equal L-shaped faces.
Take into account number of segments when selecting corners among multiple vertices
This commit is contained in:
parent
e9c9effdfa
commit
36f660ae42
@ -4280,16 +4280,17 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
|
|||||||
vMap.Add( (*a2v).second );
|
vMap.Add( (*a2v).second );
|
||||||
|
|
||||||
// check if there are possible variations in choosing corners
|
// check if there are possible variations in choosing corners
|
||||||
bool isThereVariants = false;
|
bool haveVariants = false;
|
||||||
if ( vertexByAngle.size() > nbCorners )
|
if ( vertexByAngle.size() > nbCorners )
|
||||||
{
|
{
|
||||||
double lostAngle = a2v->first;
|
double lostAngle = a2v->first;
|
||||||
double lastAngle = ( --a2v, a2v->first );
|
double lastAngle = ( --a2v, a2v->first );
|
||||||
isThereVariants = ( lostAngle * 1.1 >= lastAngle );
|
haveVariants = ( lostAngle * 1.1 >= lastAngle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const double angleTol = 5.* M_PI/180;
|
||||||
myCheckOri = ( vertexByAngle.size() > nbCorners ||
|
myCheckOri = ( vertexByAngle.size() > nbCorners ||
|
||||||
vertexByAngle.begin()->first < 5.* M_PI/180 );
|
vertexByAngle.begin()->first < angleTol );
|
||||||
|
|
||||||
// make theWire begin from a corner vertex or triaVertex
|
// make theWire begin from a corner vertex or triaVertex
|
||||||
if ( nbCorners == 3 )
|
if ( nbCorners == 3 )
|
||||||
@ -4306,9 +4307,10 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
|
|||||||
vector< double > angles;
|
vector< double > angles;
|
||||||
vector< TopoDS_Edge > edgeVec;
|
vector< TopoDS_Edge > edgeVec;
|
||||||
vector< int > cornerInd, nbSeg;
|
vector< int > cornerInd, nbSeg;
|
||||||
angles.reserve( vertexByAngle.size() );
|
int nbSegTot = 0;
|
||||||
|
angles .reserve( vertexByAngle.size() );
|
||||||
edgeVec.reserve( vertexByAngle.size() );
|
edgeVec.reserve( vertexByAngle.size() );
|
||||||
nbSeg.reserve( vertexByAngle.size() );
|
nbSeg .reserve( vertexByAngle.size() );
|
||||||
cornerInd.reserve( nbCorners );
|
cornerInd.reserve( nbCorners );
|
||||||
for ( edge = theWire.begin(); edge != theWire.end(); ++edge )
|
for ( edge = theWire.begin(); edge != theWire.end(); ++edge )
|
||||||
{
|
{
|
||||||
@ -4321,105 +4323,219 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
|
|||||||
theVertices.push_back( v );
|
theVertices.push_back( v );
|
||||||
cornerInd.push_back( angles.size() );
|
cornerInd.push_back( angles.size() );
|
||||||
}
|
}
|
||||||
angles.push_back( angleByVertex.IsBound( v ) ? angleByVertex( v ) : -M_PI );
|
angles .push_back( angleByVertex.IsBound( v ) ? angleByVertex( v ) : -M_PI );
|
||||||
edgeVec.push_back( *edge );
|
edgeVec.push_back( *edge );
|
||||||
if ( theConsiderMesh && isThereVariants )
|
if ( theConsiderMesh && haveVariants )
|
||||||
{
|
{
|
||||||
if ( SMESHDS_SubMesh* sm = helper.GetMeshDS()->MeshElements( *edge ))
|
if ( SMESHDS_SubMesh* sm = helper.GetMeshDS()->MeshElements( *edge ))
|
||||||
nbSeg.push_back( sm->NbNodes() + 1 );
|
nbSeg.push_back( sm->NbNodes() + 1 );
|
||||||
else
|
else
|
||||||
nbSeg.push_back( 0 );
|
nbSeg.push_back( 0 );
|
||||||
|
nbSegTot += nbSeg.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// refine the result vector - make sides elual by length if
|
// refine the result vector - make sides equal by length if
|
||||||
// there are several equal angles
|
// there are several equal angles
|
||||||
if ( isThereVariants )
|
if ( haveVariants )
|
||||||
{
|
{
|
||||||
if ( nbCorners == 3 )
|
if ( nbCorners == 3 )
|
||||||
angles[0] = 2 * M_PI; // not to move the base triangle VERTEX
|
angles[0] = 2 * M_PI; // not to move the base triangle VERTEX
|
||||||
|
|
||||||
set< int > refinedCorners;
|
// here we refer to VERTEX'es and EDGEs by indices in angles and edgeVec vectors
|
||||||
|
typedef int TGeoIndex;
|
||||||
|
|
||||||
|
// for each vertex find a vertex till which there are nbSegHalf segments
|
||||||
|
const int nbSegHalf = ( nbSegTot % 2 || nbCorners == 3 ) ? 0 : nbSegTot / 2;
|
||||||
|
vector< TGeoIndex > halfDivider( angles.size(), -1 );
|
||||||
|
int nbHalfDividers = 0;
|
||||||
|
if ( nbSegHalf )
|
||||||
|
{
|
||||||
|
// get min angle of corners
|
||||||
|
double minAngle = 10.;
|
||||||
|
for ( size_t iC = 0; iC < cornerInd.size(); ++iC )
|
||||||
|
minAngle = Min( minAngle, angles[ cornerInd[ iC ]]);
|
||||||
|
|
||||||
|
// find halfDivider's
|
||||||
|
for ( TGeoIndex iV1 = 0; iV1 < TGeoIndex( angles.size() ); ++iV1 )
|
||||||
|
{
|
||||||
|
int nbSegs = 0;
|
||||||
|
TGeoIndex iV2 = iV1;
|
||||||
|
do {
|
||||||
|
nbSegs += nbSeg[ iV2 ];
|
||||||
|
iV2 = helper.WrapIndex( iV2 + 1, nbSeg.size() );
|
||||||
|
} while ( nbSegs < nbSegHalf );
|
||||||
|
|
||||||
|
if ( nbSegs == nbSegHalf &&
|
||||||
|
angles[ iV1 ] + angleTol >= minAngle &&
|
||||||
|
angles[ iV2 ] + angleTol >= minAngle )
|
||||||
|
{
|
||||||
|
halfDivider[ iV1 ] = iV2;
|
||||||
|
++nbHalfDividers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set< TGeoIndex > refinedCorners, treatedCorners;
|
||||||
for ( size_t iC = 0; iC < cornerInd.size(); ++iC )
|
for ( size_t iC = 0; iC < cornerInd.size(); ++iC )
|
||||||
{
|
{
|
||||||
int iV = cornerInd[iC];
|
TGeoIndex iV = cornerInd[iC];
|
||||||
if ( !refinedCorners.insert( iV ).second )
|
if ( !treatedCorners.insert( iV ).second )
|
||||||
continue;
|
continue;
|
||||||
list< int > equalVertices;
|
list< TGeoIndex > equVerts; // inds of vertices that can become corners
|
||||||
equalVertices.push_back( iV );
|
equVerts.push_back( iV );
|
||||||
int nbC[2] = { 0, 0 };
|
int nbC[2] = { 0, 0 };
|
||||||
// find equal angles backward and forward from the iV-th corner vertex
|
// find equal angles backward and forward from the iV-th corner vertex
|
||||||
for ( int isFwd = 0; isFwd < 2; ++isFwd )
|
for ( int isFwd = 0; isFwd < 2; ++isFwd )
|
||||||
{
|
{
|
||||||
int dV = isFwd ? +1 : -1;
|
int dV = isFwd ? +1 : -1;
|
||||||
int iCNext = helper.WrapIndex( iC + dV, cornerInd.size() );
|
int iCNext = helper.WrapIndex( iC + dV, cornerInd.size() );
|
||||||
int iVNext = helper.WrapIndex( iV + dV, angles.size() );
|
TGeoIndex iVNext = helper.WrapIndex( iV + dV, angles.size() );
|
||||||
while ( iVNext != iV )
|
while ( iVNext != iV )
|
||||||
{
|
{
|
||||||
bool equal = Abs( angles[iV] - angles[iVNext] ) < 0.1 * angles[iV];
|
bool equal = Abs( angles[iV] - angles[iVNext] ) < angleTol;
|
||||||
if ( equal )
|
if ( equal )
|
||||||
equalVertices.insert( isFwd ? equalVertices.end() : equalVertices.begin(), iVNext );
|
equVerts.insert( isFwd ? equVerts.end() : equVerts.begin(), iVNext );
|
||||||
if ( iVNext == cornerInd[ iCNext ])
|
if ( iVNext == cornerInd[ iCNext ])
|
||||||
{
|
{
|
||||||
if ( !equal )
|
if ( !equal )
|
||||||
|
{
|
||||||
|
if ( angles[iV] < angles[iVNext] )
|
||||||
|
refinedCorners.insert( iVNext );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
nbC[ isFwd ]++;
|
nbC[ isFwd ]++;
|
||||||
refinedCorners.insert( cornerInd[ iCNext ] );
|
treatedCorners.insert( cornerInd[ iCNext ] );
|
||||||
iCNext = helper.WrapIndex( iCNext + dV, cornerInd.size() );
|
iCNext = helper.WrapIndex( iCNext + dV, cornerInd.size() );
|
||||||
}
|
}
|
||||||
iVNext = helper.WrapIndex( iVNext + dV, angles.size() );
|
iVNext = helper.WrapIndex( iVNext + dV, angles.size() );
|
||||||
}
|
}
|
||||||
|
if ( iVNext == iV )
|
||||||
|
break; // all angles equal
|
||||||
}
|
}
|
||||||
// move corners to make sides equal by length
|
|
||||||
int nbEqualV = equalVertices.size();
|
const bool allCornersSame = ( nbC[0] == 3 );
|
||||||
int nbExcessV = nbEqualV - ( 1 + nbC[0] + nbC[1] );
|
if ( allCornersSame && nbHalfDividers > 0 )
|
||||||
if ( nbExcessV > 0 )
|
|
||||||
{
|
{
|
||||||
// calculate normalized length of each side enclosed between neighbor equalVertices
|
// select two halfDivider's as corners
|
||||||
vector< double > curLengths;
|
TGeoIndex hd1, hd2 = -1;
|
||||||
double totalLen = 0;
|
int iC2;
|
||||||
vector< int > evVec( equalVertices.begin(), equalVertices.end() );
|
for ( iC2 = 0; iC2 < cornerInd.size() && hd2 < 0; ++iC2 )
|
||||||
int iEV = 0;
|
|
||||||
int iE = cornerInd[ helper.WrapIndex( iC - nbC[0] - 1, cornerInd.size() )];
|
|
||||||
int iEEnd = cornerInd[ helper.WrapIndex( iC + nbC[1] + 1, cornerInd.size() )];
|
|
||||||
while ( curLengths.size() < nbEqualV + 1 )
|
|
||||||
{
|
{
|
||||||
curLengths.push_back( totalLen );
|
hd1 = cornerInd[ iC2 ];
|
||||||
do {
|
hd2 = halfDivider[ hd1 ];
|
||||||
curLengths.back() += SMESH_Algo::EdgeLength( edgeVec[ iE ]);
|
if ( std::find( equVerts.begin(), equVerts.end(), hd2 ) == equVerts.end() )
|
||||||
iE = helper.WrapIndex( iE + 1, edgeVec.size());
|
hd2 = -1; // hd2-th vertex can't become a corner
|
||||||
if ( iEV < evVec.size() && iE == evVec[ iEV++ ] )
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while( iE != iEEnd );
|
if ( hd2 >= 0 )
|
||||||
totalLen = curLengths.back();
|
{
|
||||||
}
|
angles[ hd1 ] = 2 * M_PI; // make hd1-th vertex no more "equal"
|
||||||
curLengths.resize( equalVertices.size() );
|
angles[ hd2 ] = 2 * M_PI;
|
||||||
for ( size_t iS = 0; iS < curLengths.size(); ++iS )
|
refinedCorners.insert( hd1 );
|
||||||
curLengths[ iS ] /= totalLen;
|
refinedCorners.insert( hd2 );
|
||||||
|
treatedCorners = refinedCorners;
|
||||||
|
// update cornerInd
|
||||||
|
equVerts.push_front( equVerts.back() );
|
||||||
|
equVerts.push_back( equVerts.front() );
|
||||||
|
list< TGeoIndex >::iterator hdPos =
|
||||||
|
std::find( equVerts.begin(), equVerts.end(), hd2 );
|
||||||
|
if ( hdPos == equVerts.end() ) break;
|
||||||
|
cornerInd[ helper.WrapIndex( iC2 + 0, cornerInd.size()) ] = hd1;
|
||||||
|
cornerInd[ helper.WrapIndex( iC2 + 1, cornerInd.size()) ] = *( --hdPos );
|
||||||
|
cornerInd[ helper.WrapIndex( iC2 + 2, cornerInd.size()) ] = hd2;
|
||||||
|
cornerInd[ helper.WrapIndex( iC2 + 3, cornerInd.size()) ] = *( ++hdPos, ++hdPos );
|
||||||
|
|
||||||
// find equalVertices most close to the ideal sub-division of all sides
|
theVertices[ 0 ] = helper.IthVertex( 0, edgeVec[ cornerInd[0] ]);
|
||||||
|
theVertices[ 1 ] = helper.IthVertex( 0, edgeVec[ cornerInd[1] ]);
|
||||||
|
theVertices[ 2 ] = helper.IthVertex( 0, edgeVec[ cornerInd[2] ]);
|
||||||
|
theVertices[ 3 ] = helper.IthVertex( 0, edgeVec[ cornerInd[3] ]);
|
||||||
|
iC = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move corners to make sides equal by length
|
||||||
|
int nbEqualV = equVerts.size();
|
||||||
|
int nbExcessV = nbEqualV - ( 1 + nbC[0] + nbC[1] );
|
||||||
|
if ( nbExcessV > 0 ) // there is nbExcessV vertices that can become corners
|
||||||
|
{
|
||||||
|
// calculate normalized length of each "side" enclosed between neighbor equVerts
|
||||||
|
vector< double > accuLength;
|
||||||
|
double totalLen = 0;
|
||||||
|
vector< TGeoIndex > evVec( equVerts.begin(), equVerts.end() );
|
||||||
|
int iEV = 0;
|
||||||
|
TGeoIndex iE = cornerInd[ helper.WrapIndex( iC - nbC[0] - 1, cornerInd.size() )];
|
||||||
|
TGeoIndex iEEnd = cornerInd[ helper.WrapIndex( iC + nbC[1] + 1, cornerInd.size() )];
|
||||||
|
while ( accuLength.size() < nbEqualV + int( !allCornersSame ) )
|
||||||
|
{
|
||||||
|
// accumulate length of edges before iEV-th equal vertex
|
||||||
|
accuLength.push_back( totalLen );
|
||||||
|
do {
|
||||||
|
accuLength.back() += SMESH_Algo::EdgeLength( edgeVec[ iE ]);
|
||||||
|
iE = helper.WrapIndex( iE + 1, edgeVec.size());
|
||||||
|
if ( iEV < evVec.size() && iE == evVec[ iEV ] ) {
|
||||||
|
iEV++;
|
||||||
|
break; // equal vertex reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while( iE != iEEnd );
|
||||||
|
totalLen = accuLength.back();
|
||||||
|
}
|
||||||
|
accuLength.resize( equVerts.size() );
|
||||||
|
for ( size_t iS = 0; iS < accuLength.size(); ++iS )
|
||||||
|
accuLength[ iS ] /= totalLen;
|
||||||
|
|
||||||
|
// find equVerts most close to the ideal sub-division of all sides
|
||||||
int iBestEV = 0;
|
int iBestEV = 0;
|
||||||
int iCorner = helper.WrapIndex( iC - nbC[0], cornerInd.size() );
|
int iCorner = helper.WrapIndex( iC - nbC[0], cornerInd.size() );
|
||||||
int nbSides = 2 + nbC[0] + nbC[1];
|
int nbSides = Min( nbCorners, 2 + nbC[0] + nbC[1] );
|
||||||
for ( int iS = 1; iS < nbSides; ++iS, ++iBestEV )
|
for ( int iS = 1; iS < nbSides; ++iS, ++iBestEV )
|
||||||
{
|
{
|
||||||
double idealLen = iS / double( nbSides );
|
double idealLen = iS / double( nbSides );
|
||||||
double d, bestDist = 1.;
|
double d, bestDist = 2.;
|
||||||
for ( iEV = iBestEV; iEV < curLengths.size(); ++iEV )
|
for ( iEV = iBestEV; iEV < accuLength.size(); ++iEV )
|
||||||
if (( d = Abs( idealLen - curLengths[ iEV ])) < bestDist )
|
{
|
||||||
|
d = Abs( idealLen - accuLength[ iEV ]);
|
||||||
|
|
||||||
|
// take into account presence of a coresponding halfDivider
|
||||||
|
const double cornerWgt = 0.5 / nbSides;
|
||||||
|
const double vertexWgt = 0.25 / nbSides;
|
||||||
|
TGeoIndex hd = halfDivider[ evVec[ iEV ]];
|
||||||
|
if ( hd < 0 )
|
||||||
|
d += vertexWgt;
|
||||||
|
else if( refinedCorners.count( hd ))
|
||||||
|
d -= cornerWgt;
|
||||||
|
else
|
||||||
|
d -= vertexWgt;
|
||||||
|
|
||||||
|
// choose vertex with the best d
|
||||||
|
if ( d < bestDist )
|
||||||
{
|
{
|
||||||
bestDist = d;
|
bestDist = d;
|
||||||
iBestEV = iEV;
|
iBestEV = iEV;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ( iBestEV > iS-1 + nbExcessV )
|
if ( iBestEV > iS-1 + nbExcessV )
|
||||||
iBestEV = iS-1 + nbExcessV;
|
iBestEV = iS-1 + nbExcessV;
|
||||||
theVertices[ iCorner ] = helper.IthVertex( 0, edgeVec[ evVec[ iBestEV ]]);
|
theVertices[ iCorner ] = helper.IthVertex( 0, edgeVec[ evVec[ iBestEV ]]);
|
||||||
|
refinedCorners.insert( evVec[ iBestEV ]);
|
||||||
iCorner = helper.WrapIndex( iCorner + 1, cornerInd.size() );
|
iCorner = helper.WrapIndex( iCorner + 1, cornerInd.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // if ( nbExcessV > 0 )
|
||||||
|
else
|
||||||
|
{
|
||||||
|
refinedCorners.insert( cornerInd[ iC ]);
|
||||||
}
|
}
|
||||||
}
|
} // loop on cornerInd
|
||||||
}
|
|
||||||
|
// make theWire begin from the cornerInd[0]-th EDGE
|
||||||
|
while ( !theWire.front().IsSame( edgeVec[ cornerInd[0] ]))
|
||||||
|
theWire.splice( theWire.begin(), theWire, --theWire.end() );
|
||||||
|
|
||||||
|
} // if ( haveVariants )
|
||||||
|
|
||||||
return nbCorners;
|
return nbCorners;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user