mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2025-02-04 09:40:34 +05:00
IPAL52781: Orientation of a wall face created by revolution is wrong
IPAL52850: ConvertToQuadratic creates invalid triangles Regression of imps_09/K0
This commit is contained in:
parent
0db2de9312
commit
1dd2f82c6d
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.9 KiB |
@ -48,6 +48,11 @@ The following dialog will appear:
|
||||
|
||||
<li>In this dialog:
|
||||
<ul>
|
||||
<li>Use \a Selection button to specify what you are going to
|
||||
select at a given moment, \b Nodes, \b Edges or \b Faces.
|
||||
\image html image120.png
|
||||
<center><em>"Selection" button</em></center>
|
||||
</li>
|
||||
<li>Specify \b Nodes, \b Edges and \b Faces, which will be extruded, by one
|
||||
of following means:
|
||||
<ul>
|
||||
|
@ -68,16 +68,16 @@ The following dialog will appear:
|
||||
<ul>
|
||||
<li> <b>Angle by Step</b> - the elements are revolved by the
|
||||
specified angle at each step (i.e. for Angle=30 and Number of
|
||||
Steps=2, the elements will be extruded by 30 degrees twice for a
|
||||
total of 30*2=60)
|
||||
\image html revolutionsn2.png "Example of Revolution with Angle by Step"
|
||||
Steps=3, the elements will be extruded by 30 degrees twice for a
|
||||
total of 30*3=90)
|
||||
\image html revolutionsn2.png "Example of Revolution with Angle by Step. Angle=30 and Number of Steps=3"
|
||||
</li>
|
||||
<li> <b>Total Angle</b> - the elements are revolved by the
|
||||
specified angle only once and the number of steps defines the
|
||||
number of iterations (i.e. for Angle=30 and Number of Steps=2,
|
||||
the elements will be revolved by 30/2=15 degrees twice for a
|
||||
number of iterations (i.e. for Angle=30 and Number of Steps=3,
|
||||
the elements will be revolved by 30/3=10 degrees twice for a
|
||||
total of 30).
|
||||
\image html revolutionsn1.png "Example of Revolution with Total Angle"
|
||||
\image html revolutionsn1.png "Example of Revolution with Total Angle. Angle=30 and Number of Steps=3"
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include <map>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -410,14 +412,33 @@ inline double XYZ::SquareMagnitude() {
|
||||
|
||||
} // namespace
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Saver/restorer of a SMDS_VolumeTool::myCurFace
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
struct SMDS_VolumeTool::SaveFacet
|
||||
{
|
||||
SMDS_VolumeTool::Facet mySaved;
|
||||
SMDS_VolumeTool::Facet& myToRestore;
|
||||
SaveFacet( SMDS_VolumeTool::Facet& facet ): myToRestore( facet )
|
||||
{
|
||||
mySaved = facet;
|
||||
}
|
||||
~SaveFacet()
|
||||
{
|
||||
if ( myToRestore.myIndex != mySaved.myIndex )
|
||||
myToRestore = mySaved;
|
||||
}
|
||||
};
|
||||
|
||||
//=======================================================================
|
||||
//function : SMDS_VolumeTool
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
SMDS_VolumeTool::SMDS_VolumeTool ()
|
||||
: myVolumeNodes( NULL ),
|
||||
myFaceNodes( NULL )
|
||||
{
|
||||
Set( 0 );
|
||||
}
|
||||
@ -429,8 +450,6 @@ SMDS_VolumeTool::SMDS_VolumeTool ()
|
||||
|
||||
SMDS_VolumeTool::SMDS_VolumeTool (const SMDS_MeshElement* theVolume,
|
||||
const bool ignoreCentralNodes)
|
||||
: myVolumeNodes( NULL ),
|
||||
myFaceNodes( NULL )
|
||||
{
|
||||
Set( theVolume, ignoreCentralNodes );
|
||||
}
|
||||
@ -442,11 +461,7 @@ SMDS_VolumeTool::SMDS_VolumeTool (const SMDS_MeshElement* theVolume,
|
||||
|
||||
SMDS_VolumeTool::~SMDS_VolumeTool()
|
||||
{
|
||||
if ( myVolumeNodes != NULL ) delete [] myVolumeNodes;
|
||||
if ( myFaceNodes != NULL ) delete [] myFaceNodes;
|
||||
|
||||
myFaceNodeIndices = NULL;
|
||||
myVolumeNodes = myFaceNodes = NULL;
|
||||
myCurFace.myNodeIndices = NULL;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -464,42 +479,37 @@ bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume,
|
||||
|
||||
myVolForward = true;
|
||||
myNbFaces = 0;
|
||||
myVolumeNbNodes = 0;
|
||||
if (myVolumeNodes != NULL) {
|
||||
delete [] myVolumeNodes;
|
||||
myVolumeNodes = NULL;
|
||||
}
|
||||
myVolumeNodes.clear();
|
||||
myPolyIndices.clear();
|
||||
myPolyQuantities.clear();
|
||||
myPolyFacetOri.clear();
|
||||
myFwdLinks.clear();
|
||||
|
||||
myExternalFaces = false;
|
||||
|
||||
myAllFacesNodeIndices_F = 0;
|
||||
//myAllFacesNodeIndices_FE = 0;
|
||||
myAllFacesNodeIndices_RE = 0;
|
||||
myAllFacesNbNodes = 0;
|
||||
|
||||
myCurFace = -1;
|
||||
myFaceNbNodes = 0;
|
||||
myFaceNodeIndices = NULL;
|
||||
if (myFaceNodes != NULL) {
|
||||
delete [] myFaceNodes;
|
||||
myFaceNodes = NULL;
|
||||
}
|
||||
myCurFace.myIndex = -1;
|
||||
myCurFace.myNodeIndices = NULL;
|
||||
myCurFace.myNodes.clear();
|
||||
|
||||
// set volume data
|
||||
if ( !theVolume || theVolume->GetType() != SMDSAbs_Volume )
|
||||
return false;
|
||||
|
||||
myVolume = theVolume;
|
||||
if (myVolume->IsPoly())
|
||||
myPolyedre = dynamic_cast<const SMDS_VtkVolume*>( myVolume );
|
||||
|
||||
myNbFaces = theVolume->NbFaces();
|
||||
myVolumeNbNodes = theVolume->NbNodes();
|
||||
if ( myVolume->IsPoly() )
|
||||
{
|
||||
myPolyedre = dynamic_cast<const SMDS_VtkVolume*>( myVolume );
|
||||
myPolyFacetOri.resize( myNbFaces, 0 );
|
||||
}
|
||||
|
||||
// set nodes
|
||||
int iNode = 0;
|
||||
myVolumeNodes = new const SMDS_MeshNode* [myVolumeNbNodes];
|
||||
myVolumeNodes.resize( myVolume->NbNodes() );
|
||||
SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator();
|
||||
while ( nodeIt->more() )
|
||||
myVolumeNodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
|
||||
@ -512,7 +522,8 @@ bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume,
|
||||
{
|
||||
// define volume orientation
|
||||
XYZ botNormal;
|
||||
GetFaceNormal( 0, botNormal.x, botNormal.y, botNormal.z );
|
||||
if ( GetFaceNormal( 0, botNormal.x, botNormal.y, botNormal.z ))
|
||||
{
|
||||
const SMDS_MeshNode* botNode = myVolumeNodes[ 0 ];
|
||||
int topNodeIndex = myVolume->NbCornerNodes() - 1;
|
||||
while ( !IsLinked( 0, topNodeIndex, /*ignoreMediumNodes=*/true )) --topNodeIndex;
|
||||
@ -521,9 +532,9 @@ bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume,
|
||||
topNode->Y() - botNode->Y(),
|
||||
topNode->Z() - botNode->Z() );
|
||||
myVolForward = ( botNormal.Dot( upDir ) < 0 );
|
||||
|
||||
}
|
||||
if ( !myVolForward )
|
||||
myCurFace = -1; // previous setFace(0) didn't take myVolForward into account
|
||||
myCurFace.myIndex = -1; // previous setFace(0) didn't take myVolForward into account
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -549,10 +560,10 @@ void SMDS_VolumeTool::Inverse ()
|
||||
}
|
||||
|
||||
myVolForward = !myVolForward;
|
||||
myCurFace = -1;
|
||||
myCurFace.myIndex = -1;
|
||||
|
||||
// inverse top and bottom faces
|
||||
switch ( myVolumeNbNodes ) {
|
||||
switch ( myVolumeNodes.size() ) {
|
||||
case 4:
|
||||
SWAP_NODES( myVolumeNodes, 1, 2 );
|
||||
break;
|
||||
@ -626,7 +637,7 @@ SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetVolumeType() const
|
||||
if ( myPolyedre )
|
||||
return POLYHEDA;
|
||||
|
||||
switch( myVolumeNbNodes ) {
|
||||
switch( myVolumeNodes.size() ) {
|
||||
case 4: return TETRA;
|
||||
case 5: return PYRAM;
|
||||
case 6: return PENTA;
|
||||
@ -653,28 +664,18 @@ static double getTetraVolume(const SMDS_MeshNode* n1,
|
||||
const SMDS_MeshNode* n3,
|
||||
const SMDS_MeshNode* n4)
|
||||
{
|
||||
double X1 = n1->X();
|
||||
double Y1 = n1->Y();
|
||||
double Z1 = n1->Z();
|
||||
double p1[3], p2[3], p3[3], p4[3];
|
||||
n1->GetXYZ( p1 );
|
||||
n2->GetXYZ( p2 );
|
||||
n3->GetXYZ( p3 );
|
||||
n4->GetXYZ( p4 );
|
||||
|
||||
double X2 = n2->X();
|
||||
double Y2 = n2->Y();
|
||||
double Z2 = n2->Z();
|
||||
|
||||
double X3 = n3->X();
|
||||
double Y3 = n3->Y();
|
||||
double Z3 = n3->Z();
|
||||
|
||||
double X4 = n4->X();
|
||||
double Y4 = n4->Y();
|
||||
double Z4 = n4->Z();
|
||||
|
||||
double Q1 = -(X1-X2)*(Y3*Z4-Y4*Z3);
|
||||
double Q2 = (X1-X3)*(Y2*Z4-Y4*Z2);
|
||||
double R1 = -(X1-X4)*(Y2*Z3-Y3*Z2);
|
||||
double R2 = -(X2-X3)*(Y1*Z4-Y4*Z1);
|
||||
double S1 = (X2-X4)*(Y1*Z3-Y3*Z1);
|
||||
double S2 = -(X3-X4)*(Y1*Z2-Y2*Z1);
|
||||
double Q1 = -(p1[ 0 ]-p2[ 0 ])*(p3[ 1 ]*p4[ 2 ]-p4[ 1 ]*p3[ 2 ]);
|
||||
double Q2 = (p1[ 0 ]-p3[ 0 ])*(p2[ 1 ]*p4[ 2 ]-p4[ 1 ]*p2[ 2 ]);
|
||||
double R1 = -(p1[ 0 ]-p4[ 0 ])*(p2[ 1 ]*p3[ 2 ]-p3[ 1 ]*p2[ 2 ]);
|
||||
double R2 = -(p2[ 0 ]-p3[ 0 ])*(p1[ 1 ]*p4[ 2 ]-p4[ 1 ]*p1[ 2 ]);
|
||||
double S1 = (p2[ 0 ]-p4[ 0 ])*(p1[ 1 ]*p3[ 2 ]-p3[ 1 ]*p1[ 2 ]);
|
||||
double S2 = -(p3[ 0 ]-p4[ 0 ])*(p1[ 1 ]*p2[ 2 ]-p2[ 1 ]*p1[ 2 ]);
|
||||
|
||||
return (Q1+Q2+R1+R2+S1+S2)/6.0;
|
||||
}
|
||||
@ -697,23 +698,21 @@ double SMDS_VolumeTool::GetSize() const
|
||||
|
||||
// split a polyhedron into tetrahedrons
|
||||
|
||||
int saveCurFace = myCurFace;
|
||||
SaveFacet savedFacet( myCurFace );
|
||||
SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this );
|
||||
for ( int f = 0; f < NbFaces(); ++f )
|
||||
{
|
||||
me->setFace( f );
|
||||
XYZ area (0,0,0), p1( myFaceNodes[0] );
|
||||
for ( int n = 0; n < myFaceNbNodes; ++n )
|
||||
XYZ area (0,0,0), p1( myCurFace.myNodes[0] );
|
||||
for ( int n = 0; n < myCurFace.myNbNodes; ++n )
|
||||
{
|
||||
XYZ p2( myFaceNodes[ n+1 ]);
|
||||
XYZ p2( myCurFace.myNodes[ n+1 ]);
|
||||
area = area + p1.Crossed( p2 );
|
||||
p1 = p2;
|
||||
}
|
||||
V += p1.Dot( area );
|
||||
}
|
||||
V /= 6;
|
||||
if ( saveCurFace > -1 && saveCurFace != myCurFace )
|
||||
me->setFace( myCurFace );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -844,14 +843,14 @@ bool SMDS_VolumeTool::GetBaryCenter(double & X, double & Y, double & Z) const
|
||||
if ( !myVolume )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < myVolumeNbNodes; i++ ) {
|
||||
for ( int i = 0; i < myVolumeNodes.size(); i++ ) {
|
||||
X += myVolumeNodes[ i ]->X();
|
||||
Y += myVolumeNodes[ i ]->Y();
|
||||
Z += myVolumeNodes[ i ]->Z();
|
||||
}
|
||||
X /= myVolumeNbNodes;
|
||||
Y /= myVolumeNbNodes;
|
||||
Z /= myVolumeNbNodes;
|
||||
X /= myVolumeNodes.size();
|
||||
Y /= myVolumeNodes.size();
|
||||
Z /= myVolumeNodes.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -875,7 +874,7 @@ bool SMDS_VolumeTool::IsOut(double X, double Y, double Z, double tol) const
|
||||
if ( !IsFaceExternal( iF ))
|
||||
faceNormal = XYZ() - faceNormal; // reverse
|
||||
|
||||
XYZ face2p( p - XYZ( myFaceNodes[0] ));
|
||||
XYZ face2p( p - XYZ( myCurFace.myNodes[0] ));
|
||||
if ( face2p.Dot( faceNormal ) > tol )
|
||||
return true;
|
||||
}
|
||||
@ -890,7 +889,7 @@ bool SMDS_VolumeTool::IsOut(double X, double Y, double Z, double tol) const
|
||||
void SMDS_VolumeTool::SetExternalNormal ()
|
||||
{
|
||||
myExternalFaces = true;
|
||||
myCurFace = -1;
|
||||
myCurFace.myIndex = -1;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -902,7 +901,7 @@ int SMDS_VolumeTool::NbFaceNodes( int faceIndex ) const
|
||||
{
|
||||
if ( !setFace( faceIndex ))
|
||||
return 0;
|
||||
return myFaceNbNodes;
|
||||
return myCurFace.myNbNodes;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -917,7 +916,7 @@ const SMDS_MeshNode** SMDS_VolumeTool::GetFaceNodes( int faceIndex ) const
|
||||
{
|
||||
if ( !setFace( faceIndex ))
|
||||
return 0;
|
||||
return myFaceNodes;
|
||||
return &myCurFace.myNodes[0];
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -933,15 +932,7 @@ const int* SMDS_VolumeTool::GetFaceNodesIndices( int faceIndex ) const
|
||||
if ( !setFace( faceIndex ))
|
||||
return 0;
|
||||
|
||||
if (myPolyedre)
|
||||
{
|
||||
SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this );
|
||||
me->myPolyIndices.resize( myFaceNbNodes + 1 );
|
||||
me->myFaceNodeIndices = & me->myPolyIndices[0];
|
||||
for ( int i = 0; i <= myFaceNbNodes; ++i )
|
||||
me->myFaceNodeIndices[i] = myVolume->GetNodeIndex( myFaceNodes[i] );
|
||||
}
|
||||
return myFaceNodeIndices;
|
||||
return myCurFace.myNodeIndices;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -956,11 +947,44 @@ bool SMDS_VolumeTool::GetFaceNodes (int faceIndex,
|
||||
return false;
|
||||
|
||||
theFaceNodes.clear();
|
||||
theFaceNodes.insert( myFaceNodes, myFaceNodes + myFaceNbNodes );
|
||||
theFaceNodes.insert( myCurFace.myNodes.begin(), myCurFace.myNodes.end() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct NLink : public std::pair<int,int>
|
||||
{
|
||||
int myOri;
|
||||
NLink(const SMDS_MeshNode* n1=0, const SMDS_MeshNode* n2=0, int ori=1 )
|
||||
{
|
||||
if ( n1 )
|
||||
{
|
||||
if (( myOri = ( n1->GetID() < n2->GetID() )))
|
||||
{
|
||||
first = n1->GetID();
|
||||
second = n2->GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
myOri = -1;
|
||||
first = n2->GetID();
|
||||
second = n1->GetID();
|
||||
}
|
||||
myOri *= ori;
|
||||
}
|
||||
else
|
||||
{
|
||||
myOri = first = second = 0;
|
||||
}
|
||||
}
|
||||
//int Node1() const { return myOri == -1 ? second : first; }
|
||||
|
||||
//bool IsSameOri( const std::pair<int,int>& link ) const { return link.first == Node1(); }
|
||||
};
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IsFaceExternal
|
||||
//purpose : Check normal orientation of a given face
|
||||
@ -971,39 +995,179 @@ bool SMDS_VolumeTool::IsFaceExternal( int faceIndex ) const
|
||||
if ( myExternalFaces || !myVolume )
|
||||
return true;
|
||||
|
||||
if (myVolume->IsPoly()) {
|
||||
XYZ aNormal, baryCenter, p0 (myPolyedre->GetFaceNode(faceIndex + 1, 1));
|
||||
GetFaceNormal(faceIndex, aNormal.x, aNormal.y, aNormal.z);
|
||||
GetBaryCenter(baryCenter.x, baryCenter.y, baryCenter.z);
|
||||
XYZ insideVec (baryCenter - p0);
|
||||
if (insideVec.Dot(aNormal) > 0)
|
||||
return false;
|
||||
if ( !myPolyedre ) // all classical volumes have external facet normals
|
||||
return true;
|
||||
|
||||
SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* >( this );
|
||||
|
||||
if ( myPolyFacetOri[ faceIndex ])
|
||||
return myPolyFacetOri[ faceIndex ] > 0;
|
||||
|
||||
int ori = 0; // -1-in, +1-out, 0-undef
|
||||
double minProj, maxProj;
|
||||
if ( projectNodesToNormal( faceIndex, minProj, maxProj ))
|
||||
{
|
||||
// all nodes are on the same side of the facet
|
||||
ori = ( minProj < 0 ? +1 : -1 );
|
||||
me->myPolyFacetOri[ faceIndex ] = ori;
|
||||
|
||||
if ( !me->myFwdLinks.empty() ) // concave polyhedron; collect oriented links
|
||||
for ( int i = 0; i < myCurFace.myNbNodes; ++i )
|
||||
{
|
||||
NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1], ori );
|
||||
me->myFwdLinks.insert( make_pair( link, link.myOri ));
|
||||
}
|
||||
return ori > 0;
|
||||
}
|
||||
|
||||
// switch ( myVolumeNbNodes ) {
|
||||
// case 4:
|
||||
// case 5:
|
||||
// case 10:
|
||||
// case 13:
|
||||
// // only the bottom of a reversed tetrahedron can be internal
|
||||
// return ( myVolForward || faceIndex != 0 );
|
||||
// case 6:
|
||||
// case 15:
|
||||
// case 12:
|
||||
// // in a forward prism, the top is internal, in a reversed one - bottom
|
||||
// return ( myVolForward ? faceIndex != 1 : faceIndex != 0 );
|
||||
// case 8:
|
||||
// case 20:
|
||||
// case 27: {
|
||||
// // in a forward hexahedron, even face normal is external, odd - internal
|
||||
// bool odd = faceIndex % 2;
|
||||
// return ( myVolForward ? !odd : odd );
|
||||
SaveFacet savedFacet( myCurFace );
|
||||
|
||||
// concave polyhedron
|
||||
|
||||
if ( me->myFwdLinks.empty() ) // get links of the least ambiguously oriented facet
|
||||
{
|
||||
for ( size_t i = 0; i < myPolyFacetOri.size() && !ori; ++i )
|
||||
ori = me->myPolyFacetOri[ i ];
|
||||
|
||||
if ( !ori ) // none facet is oriented yet
|
||||
{
|
||||
// find the least ambiguously oriented facet
|
||||
int faceMostConvex = -1;
|
||||
std::map< double, int > convexity2face;
|
||||
for ( size_t iF = 0; iF < myPolyFacetOri.size() && faceMostConvex < 0; ++iF )
|
||||
{
|
||||
if ( projectNodesToNormal( iF, minProj, maxProj ))
|
||||
{
|
||||
// all nodes are on the same side of the facet
|
||||
me->myPolyFacetOri[ iF ] = ( minProj < 0 ? +1 : -1 );
|
||||
faceMostConvex = iF;
|
||||
}
|
||||
else
|
||||
{
|
||||
ori = ( -minProj < maxProj ? -1 : +1 );
|
||||
double convexity = std::min( -minProj, maxProj ) / std::max( -minProj, maxProj );
|
||||
convexity2face.insert( make_pair( convexity, iF * ori ));
|
||||
}
|
||||
}
|
||||
if ( faceMostConvex < 0 ) // none facet has nodes on the same side
|
||||
{
|
||||
// use the least ambiguous facet
|
||||
faceMostConvex = convexity2face.begin()->second;
|
||||
ori = ( faceMostConvex < 0 ? -1 : +1 );
|
||||
faceMostConvex = std::abs( faceMostConvex );
|
||||
me->myPolyFacetOri[ faceMostConvex ] = ori;
|
||||
}
|
||||
}
|
||||
// collect links of the oriented facets in me->myFwdLinks
|
||||
for ( size_t iF = 0; iF < myPolyFacetOri.size(); ++iF )
|
||||
{
|
||||
ori = me->myPolyFacetOri[ iF ];
|
||||
if ( !ori ) continue;
|
||||
setFace( iF );
|
||||
for ( int i = 0; i < myCurFace.myNbNodes; ++i )
|
||||
{
|
||||
NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1], ori );
|
||||
me->myFwdLinks.insert( make_pair( link, link.myOri ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compare orientation of links of the facet with myFwdLinks
|
||||
ori = 0;
|
||||
setFace( faceIndex );
|
||||
vector< NLink > links( myCurFace.myNbNodes ), links2;
|
||||
for ( int i = 0; i < myCurFace.myNbNodes && !ori; ++i )
|
||||
{
|
||||
NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1] );
|
||||
std::map<Link, int>::iterator l2o = me->myFwdLinks.find( link );
|
||||
if ( l2o != me->myFwdLinks.end() )
|
||||
ori = link.myOri * l2o->second * -1;
|
||||
links[ i ] = link;
|
||||
}
|
||||
while ( !ori ) // the facet has no common links with already oriented facets
|
||||
{
|
||||
// orient and collect links of other non-oriented facets
|
||||
for ( size_t iF = 0; iF < myPolyFacetOri.size(); ++iF )
|
||||
{
|
||||
if ( me->myPolyFacetOri[ iF ] ) continue; // already oriented
|
||||
setFace( iF );
|
||||
links2.clear();
|
||||
ori = 0;
|
||||
for ( int i = 0; i < myCurFace.myNbNodes && !ori; ++i )
|
||||
{
|
||||
NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1] );
|
||||
std::map<Link, int>::iterator l2o = me->myFwdLinks.find( link );
|
||||
if ( l2o != me->myFwdLinks.end() )
|
||||
ori = link.myOri * l2o->second * -1;
|
||||
links2.push_back( link );
|
||||
}
|
||||
if ( ori ) // one more facet oriented
|
||||
{
|
||||
me->myPolyFacetOri[ iF ] = ori;
|
||||
for ( size_t i = 0; i < links2.size(); ++i )
|
||||
me->myFwdLinks.insert( make_pair( links2[i], links2[i].myOri * ori ));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !ori )
|
||||
return false; // error in algorithm: infinite loop
|
||||
|
||||
// try to orient the facet again
|
||||
ori = 0;
|
||||
for ( size_t i = 0; i < links.size() && !ori; ++i )
|
||||
{
|
||||
std::map<Link, int>::iterator l2o = me->myFwdLinks.find( links[i] );
|
||||
if ( l2o != me->myFwdLinks.end() )
|
||||
ori = links[i].myOri * l2o->second * -1;
|
||||
}
|
||||
me->myPolyFacetOri[ faceIndex ] = ori;
|
||||
}
|
||||
|
||||
return ori > 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : projectNodesToNormal
|
||||
//purpose : compute min and max projections of all nodes to normal of a facet.
|
||||
//=======================================================================
|
||||
|
||||
bool SMDS_VolumeTool::projectNodesToNormal( int faceIndex,
|
||||
double& minProj,
|
||||
double& maxProj ) const
|
||||
{
|
||||
minProj = std::numeric_limits<double>::max();
|
||||
maxProj = std::numeric_limits<double>::min();
|
||||
|
||||
XYZ normal;
|
||||
if ( !GetFaceNormal( faceIndex, normal.x, normal.y, normal.z ))
|
||||
return false;
|
||||
XYZ p0 ( myCurFace.myNodes[0] );
|
||||
for ( size_t i = 0; i < myVolumeNodes.size(); ++i )
|
||||
{
|
||||
if ( std::find( myCurFace.myNodes.begin() + 1,
|
||||
myCurFace.myNodes.end(),
|
||||
myVolumeNodes[ i ] ) != myCurFace.myNodes.end() )
|
||||
continue; // node of the faceIndex-th facet
|
||||
|
||||
double proj = normal.Dot( XYZ( myVolumeNodes[ i ]) - p0 );
|
||||
if ( proj < minProj ) minProj = proj;
|
||||
if ( proj > maxProj ) maxProj = proj;
|
||||
}
|
||||
const double tol = 1e-7;
|
||||
minProj += tol;
|
||||
maxProj -= tol;
|
||||
bool diffSize = ( minProj * maxProj < 0 );
|
||||
// if ( diffSize )
|
||||
// {
|
||||
// minProj = -minProj;
|
||||
// }
|
||||
// default:;
|
||||
// else if ( minProj < 0 )
|
||||
// {
|
||||
// minProj = -minProj;
|
||||
// maxProj = -maxProj;
|
||||
// }
|
||||
// return false;
|
||||
return true;
|
||||
|
||||
return !diffSize; // ? 0 : (minProj >= 0);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -1016,16 +1180,16 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub
|
||||
if ( !setFace( faceIndex ))
|
||||
return false;
|
||||
|
||||
const int iQuad = ( myFaceNbNodes > 6 && !myPolyedre ) ? 2 : 1;
|
||||
XYZ p1 ( myFaceNodes[0*iQuad] );
|
||||
XYZ p2 ( myFaceNodes[1*iQuad] );
|
||||
XYZ p3 ( myFaceNodes[2*iQuad] );
|
||||
const int iQuad = ( !myPolyedre && myCurFace.myNbNodes > 6 ) ? 2 : 1;
|
||||
XYZ p1 ( myCurFace.myNodes[0*iQuad] );
|
||||
XYZ p2 ( myCurFace.myNodes[1*iQuad] );
|
||||
XYZ p3 ( myCurFace.myNodes[2*iQuad] );
|
||||
XYZ aVec12( p2 - p1 );
|
||||
XYZ aVec13( p3 - p1 );
|
||||
XYZ cross = aVec12.Crossed( aVec13 );
|
||||
|
||||
if ( myFaceNbNodes >3*iQuad ) {
|
||||
XYZ p4 ( myFaceNodes[3*iQuad] );
|
||||
if ( myCurFace.myNbNodes >3*iQuad ) {
|
||||
XYZ p4 ( myCurFace.myNodes[3*iQuad] );
|
||||
XYZ aVec14( p4 - p1 );
|
||||
XYZ cross2 = aVec13.Crossed( aVec14 );
|
||||
cross = cross + cross2;
|
||||
@ -1054,11 +1218,11 @@ bool SMDS_VolumeTool::GetFaceBaryCenter (int faceIndex, double & X, double & Y,
|
||||
return false;
|
||||
|
||||
X = Y = Z = 0.0;
|
||||
for ( int i = 0; i < myFaceNbNodes; ++i )
|
||||
for ( int i = 0; i < myCurFace.myNbNodes; ++i )
|
||||
{
|
||||
X += myFaceNodes[i]->X() / myFaceNbNodes;
|
||||
Y += myFaceNodes[i]->Y() / myFaceNbNodes;
|
||||
Z += myFaceNodes[i]->Z() / myFaceNbNodes;
|
||||
X += myCurFace.myNodes[i]->X() / myCurFace.myNbNodes;
|
||||
Y += myCurFace.myNodes[i]->Y() / myCurFace.myNbNodes;
|
||||
Z += myCurFace.myNodes[i]->Z() / myCurFace.myNbNodes;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1070,27 +1234,36 @@ bool SMDS_VolumeTool::GetFaceBaryCenter (int faceIndex, double & X, double & Y,
|
||||
|
||||
double SMDS_VolumeTool::GetFaceArea( int faceIndex ) const
|
||||
{
|
||||
if (myVolume->IsPoly()) {
|
||||
MESSAGE("Warning: attempt to obtain area of a face of polyhedral volume");
|
||||
return 0;
|
||||
}
|
||||
|
||||
double area = 0;
|
||||
if ( !setFace( faceIndex ))
|
||||
return 0;
|
||||
return area;
|
||||
|
||||
XYZ p1 ( myFaceNodes[0] );
|
||||
XYZ p2 ( myFaceNodes[1] );
|
||||
XYZ p3 ( myFaceNodes[2] );
|
||||
XYZ p1 ( myCurFace.myNodes[0] );
|
||||
XYZ p2 ( myCurFace.myNodes[1] );
|
||||
XYZ p3 ( myCurFace.myNodes[2] );
|
||||
XYZ aVec12( p2 - p1 );
|
||||
XYZ aVec13( p3 - p1 );
|
||||
double area = aVec12.Crossed( aVec13 ).Magnitude() * 0.5;
|
||||
area += aVec12.Crossed( aVec13 ).Magnitude();
|
||||
|
||||
if ( myFaceNbNodes == 4 ) {
|
||||
XYZ p4 ( myFaceNodes[3] );
|
||||
XYZ aVec14( p4 - p1 );
|
||||
area += aVec14.Crossed( aVec13 ).Magnitude() * 0.5;
|
||||
if (myVolume->IsPoly())
|
||||
{
|
||||
for ( int i = 3; i < myCurFace.myNbNodes; ++i )
|
||||
{
|
||||
XYZ pI ( myCurFace.myNodes[i] );
|
||||
XYZ aVecI( pI - p1 );
|
||||
area += aVec13.Crossed( aVecI ).Magnitude();
|
||||
aVec13 = aVecI;
|
||||
}
|
||||
return area;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( myCurFace.myNbNodes == 4 ) {
|
||||
XYZ p4 ( myCurFace.myNodes[3] );
|
||||
XYZ aVec14( p4 - p1 );
|
||||
area += aVec14.Crossed( aVec13 ).Magnitude();
|
||||
}
|
||||
}
|
||||
return area / 2;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
@ -1101,7 +1274,7 @@ double SMDS_VolumeTool::GetFaceArea( int faceIndex ) const
|
||||
|
||||
int SMDS_VolumeTool::GetCenterNodeIndex( int faceIndex ) const
|
||||
{
|
||||
if ( myAllFacesNbNodes && myVolumeNbNodes == 27 ) // classic element with 27 nodes
|
||||
if ( myAllFacesNbNodes && myVolumeNodes.size() == 27 ) // classic element with 27 nodes
|
||||
{
|
||||
switch ( faceIndex ) {
|
||||
case 0: return 20;
|
||||
@ -1129,7 +1302,7 @@ int SMDS_VolumeTool::GetOppFaceIndex( int faceIndex ) const
|
||||
const int nbHoriFaces = 2;
|
||||
|
||||
if ( faceIndex >= 0 && faceIndex < NbFaces() ) {
|
||||
switch ( myVolumeNbNodes ) {
|
||||
switch ( myVolumeNodes.size() ) {
|
||||
case 6:
|
||||
case 15:
|
||||
if ( faceIndex == 0 || faceIndex == 1 )
|
||||
@ -1182,31 +1355,42 @@ bool SMDS_VolumeTool::IsLinked (const SMDS_MeshNode* theNode1,
|
||||
MESSAGE("Warning: bad volumic element");
|
||||
return false;
|
||||
}
|
||||
bool isLinked = false;
|
||||
int iface;
|
||||
for (iface = 1; iface <= myNbFaces && !isLinked; iface++) {
|
||||
int inode, nbFaceNodes = myPolyedre->NbFaceNodes(iface);
|
||||
|
||||
for (inode = 1; inode <= nbFaceNodes && !isLinked; inode++) {
|
||||
const SMDS_MeshNode* curNode = myPolyedre->GetFaceNode(iface, inode);
|
||||
|
||||
if (curNode == theNode1 || curNode == theNode2) {
|
||||
int inextnode = (inode == nbFaceNodes) ? 1 : inode + 1;
|
||||
const SMDS_MeshNode* nextNode = myPolyedre->GetFaceNode(iface, inextnode);
|
||||
|
||||
if ((curNode == theNode1 && nextNode == theNode2) ||
|
||||
(curNode == theNode2 && nextNode == theNode1)) {
|
||||
isLinked = true;
|
||||
if ( !myAllFacesNbNodes ) {
|
||||
SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* >( this );
|
||||
me->myPolyQuantities = myPolyedre->GetQuantities();
|
||||
myAllFacesNbNodes = &myPolyQuantities[0];
|
||||
}
|
||||
int from, to = 0, d1 = 1, d2 = 2;
|
||||
if ( myPolyedre->IsQuadratic() ) {
|
||||
if ( theIgnoreMediumNodes ) {
|
||||
d1 = 2; d2 = 0;
|
||||
}
|
||||
} else {
|
||||
d2 = 0;
|
||||
}
|
||||
vector<const SMDS_MeshNode*>::const_iterator i;
|
||||
for (int iface = 0; iface < myNbFaces; iface++)
|
||||
{
|
||||
from = to;
|
||||
to += myPolyQuantities[iface];
|
||||
i = std::find( myVolumeNodes.begin() + from, myVolumeNodes.begin() + to, theNode1 );
|
||||
if ( i != myVolumeNodes.end() )
|
||||
{
|
||||
if (( theNode2 == *( i-d1 ) ||
|
||||
theNode2 == *( i+d1 )))
|
||||
return true;
|
||||
if (( d2 ) &&
|
||||
(( theNode2 == *( i-d2 ) ||
|
||||
theNode2 == *( i+d2 ))))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isLinked;
|
||||
return false;
|
||||
}
|
||||
|
||||
// find nodes indices
|
||||
int i1 = -1, i2 = -1, nbFound = 0;
|
||||
for ( int i = 0; i < myVolumeNbNodes && nbFound < 2; i++ )
|
||||
for ( int i = 0; i < myVolumeNodes.size() && nbFound < 2; i++ )
|
||||
{
|
||||
if ( myVolumeNodes[ i ] == theNode1 )
|
||||
i1 = i, ++nbFound;
|
||||
@ -1234,7 +1418,7 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
|
||||
int minInd = min( theNode1Index, theNode2Index );
|
||||
int maxInd = max( theNode1Index, theNode2Index );
|
||||
|
||||
if ( minInd < 0 || maxInd > myVolumeNbNodes - 1 || maxInd == minInd )
|
||||
if ( minInd < 0 || maxInd > myVolumeNodes.size() - 1 || maxInd == minInd )
|
||||
return false;
|
||||
|
||||
VolumeType type = GetVolumeType();
|
||||
@ -1351,7 +1535,7 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
|
||||
int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const
|
||||
{
|
||||
if ( myVolume ) {
|
||||
for ( int i = 0; i < myVolumeNbNodes; i++ ) {
|
||||
for ( int i = 0; i < myVolumeNodes.size(); i++ ) {
|
||||
if ( myVolumeNodes[ i ] == theNode )
|
||||
return i;
|
||||
}
|
||||
@ -1370,6 +1554,14 @@ int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const
|
||||
int SMDS_VolumeTool::GetAllExistingFaces(vector<const SMDS_MeshElement*> & faces) const
|
||||
{
|
||||
faces.clear();
|
||||
SaveFacet savedFacet( myCurFace );
|
||||
if ( IsPoly() )
|
||||
for ( int iF = 0; iF < NbFaces(); ++iF ) {
|
||||
if ( setFace( iF ))
|
||||
if ( const SMDS_MeshElement* face = SMDS_Mesh::FindFace( myCurFace.myNodes ))
|
||||
faces.push_back( face );
|
||||
}
|
||||
else
|
||||
for ( int iF = 0; iF < NbFaces(); ++iF ) {
|
||||
const SMDS_MeshFace* face = 0;
|
||||
const SMDS_MeshNode** nodes = GetFaceNodes( iF );
|
||||
@ -1403,9 +1595,9 @@ int SMDS_VolumeTool::GetAllExistingFaces(vector<const SMDS_MeshElement*> & faces
|
||||
int SMDS_VolumeTool::GetAllExistingEdges(vector<const SMDS_MeshElement*> & edges) const
|
||||
{
|
||||
edges.clear();
|
||||
edges.reserve( myVolumeNbNodes * 2 );
|
||||
for ( int i = 0; i < myVolumeNbNodes-1; ++i ) {
|
||||
for ( int j = i + 1; j < myVolumeNbNodes; ++j ) {
|
||||
edges.reserve( myVolumeNodes.size() * 2 );
|
||||
for ( int i = 0; i < myVolumeNodes.size()-1; ++i ) {
|
||||
for ( int j = i + 1; j < myVolumeNodes.size(); ++j ) {
|
||||
if ( IsLinked( i, j )) {
|
||||
const SMDS_MeshElement* edge =
|
||||
SMDS_Mesh::FindEdge( myVolumeNodes[i], myVolumeNodes[j] );
|
||||
@ -1428,30 +1620,20 @@ double SMDS_VolumeTool::MinLinearSize2() const
|
||||
double minSize = 1e+100;
|
||||
int iQ = myVolume->IsQuadratic() ? 2 : 1;
|
||||
|
||||
// store current face data
|
||||
int curFace = myCurFace, nbN = myFaceNbNodes;
|
||||
int* ind = myFaceNodeIndices;
|
||||
myFaceNodeIndices = NULL;
|
||||
const SMDS_MeshNode** nodes = myFaceNodes;
|
||||
myFaceNodes = NULL;
|
||||
SaveFacet savedFacet( myCurFace );
|
||||
|
||||
// it seems that compute distance twice is faster than organization of a sole computing
|
||||
myCurFace = -1;
|
||||
myCurFace.myIndex = -1;
|
||||
for ( int iF = 0; iF < myNbFaces; ++iF )
|
||||
{
|
||||
setFace( iF );
|
||||
for ( int iN = 0; iN < myFaceNbNodes; iN += iQ )
|
||||
for ( int iN = 0; iN < myCurFace.myNbNodes; iN += iQ )
|
||||
{
|
||||
XYZ n1( myFaceNodes[ iN ]);
|
||||
XYZ n2( myFaceNodes[(iN + iQ) % myFaceNbNodes]);
|
||||
XYZ n1( myCurFace.myNodes[ iN ]);
|
||||
XYZ n2( myCurFace.myNodes[(iN + iQ) % myCurFace.myNbNodes]);
|
||||
minSize = std::min( minSize, (n1 - n2).SquareMagnitude());
|
||||
}
|
||||
}
|
||||
// restore current face data
|
||||
myCurFace = curFace;
|
||||
myFaceNbNodes = nbN;
|
||||
myFaceNodeIndices = ind;
|
||||
delete [] myFaceNodes; myFaceNodes = nodes;
|
||||
|
||||
return minSize;
|
||||
}
|
||||
@ -1467,30 +1649,20 @@ double SMDS_VolumeTool::MaxLinearSize2() const
|
||||
double maxSize = -1e+100;
|
||||
int iQ = myVolume->IsQuadratic() ? 2 : 1;
|
||||
|
||||
// store current face data
|
||||
int curFace = myCurFace, nbN = myFaceNbNodes;
|
||||
int* ind = myFaceNodeIndices;
|
||||
myFaceNodeIndices = NULL;
|
||||
const SMDS_MeshNode** nodes = myFaceNodes;
|
||||
myFaceNodes = NULL;
|
||||
SaveFacet savedFacet( myCurFace );
|
||||
|
||||
// it seems that compute distance twice is faster than organization of a sole computing
|
||||
myCurFace = -1;
|
||||
myCurFace.myIndex = -1;
|
||||
for ( int iF = 0; iF < myNbFaces; ++iF )
|
||||
{
|
||||
setFace( iF );
|
||||
for ( int iN = 0; iN < myFaceNbNodes; iN += iQ )
|
||||
for ( int iN = 0; iN < myCurFace.myNbNodes; iN += iQ )
|
||||
{
|
||||
XYZ n1( myFaceNodes[ iN ]);
|
||||
XYZ n2( myFaceNodes[(iN + iQ) % myFaceNbNodes]);
|
||||
XYZ n1( myCurFace.myNodes[ iN ]);
|
||||
XYZ n2( myCurFace.myNodes[(iN + iQ) % myCurFace.myNbNodes]);
|
||||
maxSize = std::max( maxSize, (n1 - n2).SquareMagnitude());
|
||||
}
|
||||
}
|
||||
// restore current face data
|
||||
myCurFace = curFace;
|
||||
myFaceNbNodes = nbN;
|
||||
myFaceNodeIndices = ind;
|
||||
delete [] myFaceNodes; myFaceNodes = nodes;
|
||||
|
||||
return maxSize;
|
||||
}
|
||||
@ -1512,7 +1684,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex, const SMDS_MeshElement** otherV
|
||||
const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex );
|
||||
|
||||
const int di = myVolume->IsQuadratic() ? 2 : 1;
|
||||
const int nbN = ( myFaceNbNodes/di <= 4 && !IsPoly()) ? 3 : myFaceNbNodes/di; // nb nodes to check
|
||||
const int nbN = ( myCurFace.myNbNodes/di <= 4 && !IsPoly()) ? 3 : myCurFace.myNbNodes/di; // nb nodes to check
|
||||
|
||||
SMDS_ElemIteratorPtr eIt = nodes[0]->GetInverseElementIterator( SMDSAbs_Volume );
|
||||
while ( eIt->more() )
|
||||
@ -1528,7 +1700,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex, const SMDS_MeshElement** otherV
|
||||
{
|
||||
// if ( vol->IsPoly() || vol->NbFaces() > 6 ) // vol is polyhed or hex prism
|
||||
// {
|
||||
// int nb = myFaceNbNodes;
|
||||
// int nb = myCurFace.myNbNodes;
|
||||
// if ( myVolume->GetEntityType() != vol->GetEntityType() )
|
||||
// nb -= ( GetCenterNodeIndex(0) > 0 );
|
||||
// set<const SMDS_MeshNode*> faceNodes( nodes, nodes + nb );
|
||||
@ -1557,7 +1729,7 @@ bool SMDS_VolumeTool::IsFreeFaceAdv( int faceIndex, const SMDS_MeshElement** oth
|
||||
return !isFree;
|
||||
|
||||
const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex );
|
||||
const int nbFaceNodes = myFaceNbNodes;
|
||||
const int nbFaceNodes = myCurFace.myNbNodes;
|
||||
|
||||
// evaluate nb of face nodes shared by other volumes
|
||||
int maxNbShared = -1;
|
||||
@ -1736,19 +1908,14 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
|
||||
if ( !myVolume )
|
||||
return false;
|
||||
|
||||
if ( myCurFace == faceIndex )
|
||||
if ( myCurFace.myIndex == faceIndex )
|
||||
return true;
|
||||
|
||||
myCurFace = -1;
|
||||
myCurFace.myIndex = -1;
|
||||
|
||||
if ( faceIndex < 0 || faceIndex >= NbFaces() )
|
||||
return false;
|
||||
|
||||
if (myFaceNodes != NULL) {
|
||||
delete [] myFaceNodes;
|
||||
myFaceNodes = NULL;
|
||||
}
|
||||
|
||||
if (myVolume->IsPoly())
|
||||
{
|
||||
if (!myPolyedre) {
|
||||
@ -1757,21 +1924,31 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
|
||||
}
|
||||
|
||||
// set face nodes
|
||||
int iNode;
|
||||
myFaceNbNodes = myPolyedre->NbFaceNodes(faceIndex + 1);
|
||||
myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1];
|
||||
for ( iNode = 0; iNode < myFaceNbNodes; iNode++ )
|
||||
myFaceNodes[ iNode ] = myPolyedre->GetFaceNode(faceIndex + 1, iNode + 1);
|
||||
myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ]; // last = first
|
||||
SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* >( this );
|
||||
if ( !myAllFacesNbNodes ) {
|
||||
me->myPolyQuantities = myPolyedre->GetQuantities();
|
||||
myAllFacesNbNodes = &myPolyQuantities[0];
|
||||
}
|
||||
myCurFace.myNbNodes = myAllFacesNbNodes[ faceIndex ];
|
||||
myCurFace.myNodes.resize( myCurFace.myNbNodes + 1 );
|
||||
me->myPolyIndices.resize( myCurFace.myNbNodes + 1 );
|
||||
myCurFace.myNodeIndices = & me->myPolyIndices[0];
|
||||
int shift = std::accumulate( myAllFacesNbNodes, myAllFacesNbNodes+faceIndex, 0 );
|
||||
for ( int iNode = 0; iNode < myCurFace.myNbNodes; iNode++ )
|
||||
{
|
||||
myCurFace.myNodes [ iNode ] = myVolumeNodes[ shift + iNode ];
|
||||
myCurFace.myNodeIndices[ iNode ] = shift + iNode;
|
||||
}
|
||||
myCurFace.myNodes [ myCurFace.myNbNodes ] = myCurFace.myNodes[ 0 ]; // last = first
|
||||
myCurFace.myNodeIndices[ myCurFace.myNbNodes ] = myCurFace.myNodeIndices[ 0 ];
|
||||
|
||||
// check orientation
|
||||
if (myExternalFaces)
|
||||
{
|
||||
myCurFace = faceIndex; // avoid infinite recursion in IsFaceExternal()
|
||||
myCurFace.myIndex = faceIndex; // avoid infinite recursion in IsFaceExternal()
|
||||
myExternalFaces = false; // force normal computation by IsFaceExternal()
|
||||
if ( !IsFaceExternal( faceIndex ))
|
||||
for ( int i = 0, j = myFaceNbNodes; i < j; ++i, --j )
|
||||
std::swap( myFaceNodes[i], myFaceNodes[j] );
|
||||
std::reverse( myCurFace.myNodes.begin(), myCurFace.myNodes.end() );
|
||||
myExternalFaces = true;
|
||||
}
|
||||
}
|
||||
@ -1780,7 +1957,7 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
|
||||
if ( !myAllFacesNodeIndices_F )
|
||||
{
|
||||
// choose data for an element type
|
||||
switch ( myVolumeNbNodes ) {
|
||||
switch ( myVolumeNodes.size() ) {
|
||||
case 4:
|
||||
myAllFacesNodeIndices_F = &Tetra_F [0][0];
|
||||
//myAllFacesNodeIndices_FE = &Tetra_F [0][0];
|
||||
@ -1837,7 +2014,7 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
|
||||
myAllFacesNodeIndices_RE = &QuadHexa_RE[0][0];
|
||||
myAllFacesNbNodes = QuadHexa_nbN;
|
||||
myMaxFaceNbNodes = sizeof(QuadHexa_F[0])/sizeof(QuadHexa_F[0][0]);
|
||||
if ( !myIgnoreCentralNodes && myVolumeNbNodes == 27 )
|
||||
if ( !myIgnoreCentralNodes && myVolumeNodes.size() == 27 )
|
||||
{
|
||||
myAllFacesNodeIndices_F = &TriQuadHexa_F [0][0];
|
||||
//myAllFacesNodeIndices_FE = &TriQuadHexa_FE[0][0];
|
||||
@ -1857,21 +2034,21 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
|
||||
return false;
|
||||
}
|
||||
}
|
||||
myFaceNbNodes = myAllFacesNbNodes[ faceIndex ];
|
||||
myCurFace.myNbNodes = myAllFacesNbNodes[ faceIndex ];
|
||||
// if ( myExternalFaces )
|
||||
// myFaceNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_FE + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
|
||||
// myCurFace.myNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_FE + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
|
||||
// else
|
||||
// myFaceNodeIndices = (int*)( myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes );
|
||||
myFaceNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
|
||||
// myCurFace.myNodeIndices = (int*)( myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes );
|
||||
myCurFace.myNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
|
||||
|
||||
// set face nodes
|
||||
myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1];
|
||||
for ( int iNode = 0; iNode < myFaceNbNodes; iNode++ )
|
||||
myFaceNodes[ iNode ] = myVolumeNodes[ myFaceNodeIndices[ iNode ]];
|
||||
myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ];
|
||||
myCurFace.myNodes.resize( myCurFace.myNbNodes + 1 );
|
||||
for ( int iNode = 0; iNode < myCurFace.myNbNodes; iNode++ )
|
||||
myCurFace.myNodes[ iNode ] = myVolumeNodes[ myCurFace.myNodeIndices[ iNode ]];
|
||||
myCurFace.myNodes[ myCurFace.myNbNodes ] = myCurFace.myNodes[ 0 ];
|
||||
}
|
||||
|
||||
myCurFace = faceIndex;
|
||||
myCurFace.myIndex = faceIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ class SMDS_MeshVolume;
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
// =========================================================================
|
||||
//
|
||||
@ -90,10 +91,10 @@ class SMDS_EXPORT SMDS_VolumeTool
|
||||
// top and bottom faces are reversed.
|
||||
// Result of IsForward() and methods returning nodes change
|
||||
|
||||
const SMDS_MeshNode** GetNodes() { return myVolumeNodes; }
|
||||
const SMDS_MeshNode** GetNodes() { return &myVolumeNodes[0]; }
|
||||
// Return array of volume nodes
|
||||
|
||||
int NbNodes() { return myVolumeNbNodes; }
|
||||
int NbNodes() { return myVolumeNodes.size(); }
|
||||
// Return array of volume nodes
|
||||
|
||||
double GetSize() const;
|
||||
@ -246,15 +247,21 @@ private:
|
||||
|
||||
bool setFace( int faceIndex ) const;
|
||||
|
||||
bool projectNodesToNormal( int faceIndex, double& minProj, double& maxProj ) const;
|
||||
|
||||
const SMDS_MeshElement* myVolume;
|
||||
const SMDS_VtkVolume* myPolyedre;
|
||||
bool myIgnoreCentralNodes;
|
||||
|
||||
bool myVolForward;
|
||||
int myNbFaces;
|
||||
int myVolumeNbNodes;
|
||||
const SMDS_MeshNode** myVolumeNodes;
|
||||
std::vector< int > myPolyIndices;
|
||||
std::vector<const SMDS_MeshNode*> myVolumeNodes;
|
||||
std::vector< int > myPolyIndices; // of a myCurFace
|
||||
std::vector< int > myPolyQuantities;
|
||||
std::vector< int > myPolyFacetOri; // -1-in, +1-out, 0-undef
|
||||
|
||||
typedef std::pair<int,int> Link;
|
||||
std::map<Link, int> myFwdLinks; // used in IsFaceExternal() to find out myPolyFacetOri
|
||||
|
||||
mutable bool myExternalFaces;
|
||||
|
||||
@ -263,10 +270,15 @@ private:
|
||||
mutable const int* myAllFacesNbNodes;
|
||||
mutable int myMaxFaceNbNodes;
|
||||
|
||||
mutable int myCurFace;
|
||||
mutable int myFaceNbNodes;
|
||||
mutable int* myFaceNodeIndices;
|
||||
mutable const SMDS_MeshNode** myFaceNodes;
|
||||
struct SaveFacet;
|
||||
struct Facet
|
||||
{
|
||||
int myIndex;
|
||||
int myNbNodes;
|
||||
int* myNodeIndices;
|
||||
std::vector<const SMDS_MeshNode*> myNodes;
|
||||
};
|
||||
mutable Facet myCurFace;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
@ -12577,6 +12577,11 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
|
||||
TConnectivity tgtNodes;
|
||||
ElemFeatures elemKind( missType ), elemToCopy;
|
||||
|
||||
vector<const SMDS_MeshElement*> presentBndElems;
|
||||
vector<TConnectivity> missingBndElems;
|
||||
vector<int> freeFacets;
|
||||
TConnectivity nodes, elemNodes;
|
||||
|
||||
SMDS_ElemIteratorPtr eIt;
|
||||
if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
|
||||
else eIt = elemSetIterator( elements );
|
||||
@ -12590,18 +12595,24 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
|
||||
// ------------------------------------------------------------------------------------
|
||||
// 1. For an elem, get present bnd elements and connectivities of missing bnd elements
|
||||
// ------------------------------------------------------------------------------------
|
||||
vector<const SMDS_MeshElement*> presentBndElems;
|
||||
vector<TConnectivity> missingBndElems;
|
||||
TConnectivity nodes, elemNodes;
|
||||
presentBndElems.clear();
|
||||
missingBndElems.clear();
|
||||
freeFacets.clear(); nodes.clear(); elemNodes.clear();
|
||||
if ( vTool.Set(elem, /*ignoreCentralNodes=*/true) ) // elem is a volume --------------
|
||||
{
|
||||
vTool.SetExternalNormal();
|
||||
const SMDS_MeshElement* otherVol = 0;
|
||||
for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
|
||||
{
|
||||
if ( !vTool.IsFreeFace(iface, &otherVol) &&
|
||||
( !aroundElements || elements.count( otherVol )))
|
||||
continue;
|
||||
freeFacets.push_back( iface );
|
||||
}
|
||||
if ( missType == SMDSAbs_Face )
|
||||
vTool.SetExternalNormal();
|
||||
for ( size_t i = 0; i < freeFacets.size(); ++i )
|
||||
{
|
||||
int iface = freeFacets[i];
|
||||
const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
|
||||
const size_t nbFaceNodes = vTool.NbFaceNodes (iface);
|
||||
if ( missType == SMDSAbs_Edge ) // boundary edges
|
||||
|
@ -807,6 +807,24 @@ GeomAPI_ProjectPointOnSurf& SMESH_MesherHelper::GetProjector(const TopoDS_Face&
|
||||
return *( i_proj->second );
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : GetSurface
|
||||
//purpose : Return a cached ShapeAnalysis_Surface of a FACE
|
||||
//=======================================================================
|
||||
|
||||
Handle(ShapeAnalysis_Surface) SMESH_MesherHelper::GetSurface(const TopoDS_Face& F )
|
||||
{
|
||||
Handle(Geom_Surface) surface = BRep_Tool::Surface( F );
|
||||
int faceID = GetMeshDS()->ShapeToIndex( F );
|
||||
TID2Surface::iterator i_surf = myFace2Surface.find( faceID );
|
||||
if ( i_surf == myFace2Surface.end() && faceID )
|
||||
{
|
||||
Handle(ShapeAnalysis_Surface) surf( new ShapeAnalysis_Surface( surface ));
|
||||
i_surf = myFace2Surface.insert( make_pair( faceID, surf )).first;
|
||||
}
|
||||
return i_surf->second;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
gp_XY AverageUV(const gp_XY& uv1, const gp_XY& uv2) { return ( uv1 + uv2 ) / 2.; }
|
||||
@ -1581,6 +1599,26 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
|
||||
{
|
||||
F = TopoDS::Face(meshDS->IndexToShape( faceID = pos.first ));
|
||||
uv[0] = GetNodeUV(F,n1,n2, force3d ? 0 : &uvOK[0]);
|
||||
if ( HasDegeneratedEdges() && !force3d ) // IPAL52850 (degen VERTEX not at singularity)
|
||||
{
|
||||
// project middle point to a surface
|
||||
SMESH_TNodeXYZ p1( n1 ), p2( n2 );
|
||||
gp_Pnt pMid = 0.5 * ( p1 + p2 );
|
||||
Handle(ShapeAnalysis_Surface) projector = GetSurface( F );
|
||||
gp_Pnt2d uvMid;
|
||||
if ( uvOK[0] )
|
||||
uvMid = projector->NextValueOfUV( uv[0], pMid, BRep_Tool::Tolerance( F ));
|
||||
else
|
||||
uvMid = projector->ValueOfUV( pMid, getFaceMaxTol( F ));
|
||||
if ( projector->Gap() * projector->Gap() < ( p1 - p2 ).SquareModulus() / 4 )
|
||||
{
|
||||
gp_Pnt pProj = projector->Value( uvMid );
|
||||
n12 = meshDS->AddNode( pProj.X(), pProj.Y(), pProj.Z() );
|
||||
meshDS->SetNodeOnFace( n12, faceID, uvMid.X(), uvMid.Y() );
|
||||
myTLinkNodeMap.insert( make_pair ( link, n12 ));
|
||||
return n12;
|
||||
}
|
||||
}
|
||||
uv[1] = GetNodeUV(F,n2,n1, force3d ? 0 : &uvOK[1]);
|
||||
}
|
||||
else if ( pos.second == TopAbs_EDGE )
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <SMDS_QuadraticEdge.hxx>
|
||||
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <ShapeAnalysis_Surface.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
@ -528,6 +529,10 @@ public:
|
||||
GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F,
|
||||
TopLoc_Location& loc,
|
||||
double tol=0 ) const;
|
||||
/*!
|
||||
* \brief Return a cached ShapeAnalysis_Surface of a FACE
|
||||
*/
|
||||
Handle(ShapeAnalysis_Surface) GetSurface(const TopoDS_Face& F );
|
||||
|
||||
/*!
|
||||
* \brief Check if shape is a degenerated edge or it's vertex
|
||||
@ -731,8 +736,10 @@ public:
|
||||
|
||||
std::map< int, double > myFaceMaxTol;
|
||||
|
||||
typedef std::map< int, Handle(ShapeAnalysis_Surface)> TID2Surface;
|
||||
typedef std::map< int, GeomAPI_ProjectPointOnSurf* > TID2ProjectorOnSurf;
|
||||
typedef std::map< int, GeomAPI_ProjectPointOnCurve* > TID2ProjectorOnCurve;
|
||||
TID2Surface myFace2Surface;
|
||||
TID2ProjectorOnSurf myFace2Projector;
|
||||
TID2ProjectorOnCurve myEdge2Projector;
|
||||
|
||||
|
@ -4910,6 +4910,8 @@ class Mesh:
|
||||
fun = self._getFunctor( funType )
|
||||
if fun:
|
||||
if meshPart:
|
||||
if hasattr( meshPart, "SetMesh" ):
|
||||
meshPart.SetMesh( self.mesh ) # set mesh to filter
|
||||
hist = fun.GetLocalHistogram( 1, False, meshPart )
|
||||
else:
|
||||
hist = fun.GetHistogram( 1, False )
|
||||
|
@ -410,7 +410,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst,
|
||||
if ( u2node.empty() ) return myPoints;
|
||||
|
||||
const SMDS_MeshNode* node;
|
||||
if ( IsClosed() )
|
||||
if ( IsClosed() && !proxySubMesh[0] )
|
||||
node = u2node.begin()->second;
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user