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:
eap 2015-08-28 20:03:25 +03:00
parent 0db2de9312
commit 1dd2f82c6d
12 changed files with 531 additions and 279 deletions

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

View File

@ -48,6 +48,11 @@ The following dialog will appear:
<li>In this dialog: <li>In this dialog:
<ul> <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 <li>Specify \b Nodes, \b Edges and \b Faces, which will be extruded, by one
of following means: of following means:
<ul> <ul>

View File

@ -68,16 +68,16 @@ The following dialog will appear:
<ul> <ul>
<li> <b>Angle by Step</b> - the elements are revolved by the <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 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 Steps=3, the elements will be extruded by 30 degrees twice for a
total of 30*2=60) total of 30*3=90)
\image html revolutionsn2.png "Example of Revolution with Angle by Step" \image html revolutionsn2.png "Example of Revolution with Angle by Step. Angle=30 and Number of Steps=3"
</li> </li>
<li> <b>Total Angle</b> - the elements are revolved by the <li> <b>Total Angle</b> - the elements are revolved by the
specified angle only once and the number of steps defines 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, number of iterations (i.e. for Angle=30 and Number of Steps=3,
the elements will be revolved by 30/2=15 degrees twice for a the elements will be revolved by 30/3=10 degrees twice for a
total of 30). 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> </li>
</ul> </ul>
</li> </li>

View File

@ -58,7 +58,7 @@
#define MYASSERT(val) if (!(val)) throw SALOME_Exception(LOCALIZED("assertion not verified")); #define MYASSERT(val) if (!(val)) throw SALOME_Exception(LOCALIZED("assertion not verified"));
class SMDS_EXPORT SMDS_Mesh:public SMDS_MeshObject class SMDS_EXPORT SMDS_Mesh : public SMDS_MeshObject
{ {
public: public:
friend class SMDS_MeshIDFactory; friend class SMDS_MeshIDFactory;

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,7 @@ class SMDS_MeshVolume;
#include <vector> #include <vector>
#include <set> #include <set>
#include <map>
// ========================================================================= // =========================================================================
// //
@ -90,10 +91,10 @@ class SMDS_EXPORT SMDS_VolumeTool
// top and bottom faces are reversed. // top and bottom faces are reversed.
// Result of IsForward() and methods returning nodes change // 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 // Return array of volume nodes
int NbNodes() { return myVolumeNbNodes; } int NbNodes() { return myVolumeNodes.size(); }
// Return array of volume nodes // Return array of volume nodes
double GetSize() const; double GetSize() const;
@ -242,31 +243,42 @@ class SMDS_EXPORT SMDS_VolumeTool
static int GetOppFaceIndexOfHex( int faceIndex ); static int GetOppFaceIndexOfHex( int faceIndex );
// Return index of the opposite face of the hexahedron // Return index of the opposite face of the hexahedron
private: private:
bool setFace( int faceIndex ) const; bool setFace( int faceIndex ) const;
bool projectNodesToNormal( int faceIndex, double& minProj, double& maxProj ) const;
const SMDS_MeshElement* myVolume; const SMDS_MeshElement* myVolume;
const SMDS_VtkVolume* myPolyedre; const SMDS_VtkVolume* myPolyedre;
bool myIgnoreCentralNodes; bool myIgnoreCentralNodes;
bool myVolForward; bool myVolForward;
int myNbFaces; int myNbFaces;
int myVolumeNbNodes; std::vector<const SMDS_MeshNode*> myVolumeNodes;
const SMDS_MeshNode** myVolumeNodes; std::vector< int > myPolyIndices; // of a myCurFace
std::vector< int > myPolyIndices; std::vector< int > myPolyQuantities;
std::vector< int > myPolyFacetOri; // -1-in, +1-out, 0-undef
mutable bool myExternalFaces; typedef std::pair<int,int> Link;
std::map<Link, int> myFwdLinks; // used in IsFaceExternal() to find out myPolyFacetOri
mutable const int* myAllFacesNodeIndices_F; mutable bool myExternalFaces;
mutable const int* myAllFacesNodeIndices_RE;
mutable const int* myAllFacesNbNodes;
mutable int myMaxFaceNbNodes;
mutable int myCurFace; mutable const int* myAllFacesNodeIndices_F;
mutable int myFaceNbNodes; mutable const int* myAllFacesNodeIndices_RE;
mutable int* myFaceNodeIndices; mutable const int* myAllFacesNbNodes;
mutable const SMDS_MeshNode** myFaceNodes; mutable int myMaxFaceNbNodes;
struct SaveFacet;
struct Facet
{
int myIndex;
int myNbNodes;
int* myNodeIndices;
std::vector<const SMDS_MeshNode*> myNodes;
};
mutable Facet myCurFace;
}; };
#endif #endif

View File

@ -12577,6 +12577,11 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
TConnectivity tgtNodes; TConnectivity tgtNodes;
ElemFeatures elemKind( missType ), elemToCopy; ElemFeatures elemKind( missType ), elemToCopy;
vector<const SMDS_MeshElement*> presentBndElems;
vector<TConnectivity> missingBndElems;
vector<int> freeFacets;
TConnectivity nodes, elemNodes;
SMDS_ElemIteratorPtr eIt; SMDS_ElemIteratorPtr eIt;
if (elements.empty()) eIt = aMesh->elementsIterator(elemType); if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
else eIt = elemSetIterator( elements ); 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 // 1. For an elem, get present bnd elements and connectivities of missing bnd elements
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
vector<const SMDS_MeshElement*> presentBndElems; presentBndElems.clear();
vector<TConnectivity> missingBndElems; missingBndElems.clear();
TConnectivity nodes, elemNodes; freeFacets.clear(); nodes.clear(); elemNodes.clear();
if ( vTool.Set(elem, /*ignoreCentralNodes=*/true) ) // elem is a volume -------------- if ( vTool.Set(elem, /*ignoreCentralNodes=*/true) ) // elem is a volume --------------
{ {
vTool.SetExternalNormal();
const SMDS_MeshElement* otherVol = 0; const SMDS_MeshElement* otherVol = 0;
for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ ) for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
{ {
if ( !vTool.IsFreeFace(iface, &otherVol) && if ( !vTool.IsFreeFace(iface, &otherVol) &&
( !aroundElements || elements.count( otherVol ))) ( !aroundElements || elements.count( otherVol )))
continue; 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 SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
const size_t nbFaceNodes = vTool.NbFaceNodes (iface); const size_t nbFaceNodes = vTool.NbFaceNodes (iface);
if ( missType == SMDSAbs_Edge ) // boundary edges if ( missType == SMDSAbs_Edge ) // boundary edges

View File

@ -807,6 +807,24 @@ GeomAPI_ProjectPointOnSurf& SMESH_MesherHelper::GetProjector(const TopoDS_Face&
return *( i_proj->second ); 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 namespace
{ {
gp_XY AverageUV(const gp_XY& uv1, const gp_XY& uv2) { return ( uv1 + uv2 ) / 2.; } 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 )); F = TopoDS::Face(meshDS->IndexToShape( faceID = pos.first ));
uv[0] = GetNodeUV(F,n1,n2, force3d ? 0 : &uvOK[0]); 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]); uv[1] = GetNodeUV(F,n2,n1, force3d ? 0 : &uvOK[1]);
} }
else if ( pos.second == TopAbs_EDGE ) else if ( pos.second == TopAbs_EDGE )

View File

@ -34,6 +34,7 @@
#include <SMDS_QuadraticEdge.hxx> #include <SMDS_QuadraticEdge.hxx>
#include <Geom_Surface.hxx> #include <Geom_Surface.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include <TopoDS_Face.hxx> #include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx> #include <TopoDS_Shape.hxx>
#include <gp_Pnt2d.hxx> #include <gp_Pnt2d.hxx>
@ -528,6 +529,10 @@ public:
GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F, GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F,
TopLoc_Location& loc, TopLoc_Location& loc,
double tol=0 ) const; 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 * \brief Check if shape is a degenerated edge or it's vertex
@ -731,8 +736,10 @@ public:
std::map< int, double > myFaceMaxTol; 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_ProjectPointOnSurf* > TID2ProjectorOnSurf;
typedef std::map< int, GeomAPI_ProjectPointOnCurve* > TID2ProjectorOnCurve; typedef std::map< int, GeomAPI_ProjectPointOnCurve* > TID2ProjectorOnCurve;
TID2Surface myFace2Surface;
TID2ProjectorOnSurf myFace2Projector; TID2ProjectorOnSurf myFace2Projector;
TID2ProjectorOnCurve myEdge2Projector; TID2ProjectorOnCurve myEdge2Projector;

View File

@ -3619,8 +3619,8 @@ class Mesh:
## Creates 2D mesh as skin on boundary faces of a 3D mesh ## Creates 2D mesh as skin on boundary faces of a 3D mesh
# @return TRUE if operation has been completed successfully, FALSE otherwise # @return TRUE if operation has been completed successfully, FALSE otherwise
# @ingroup l2_modif_edit # @ingroup l2_modif_edit
def Make2DMeshFrom3D(self): def Make2DMeshFrom3D(self):
return self.editor. Make2DMeshFrom3D() return self.editor.Make2DMeshFrom3D()
## Creates missing boundary elements ## Creates missing boundary elements
# @param elements - elements whose boundary is to be checked: # @param elements - elements whose boundary is to be checked:
@ -4910,6 +4910,8 @@ class Mesh:
fun = self._getFunctor( funType ) fun = self._getFunctor( funType )
if fun: if fun:
if meshPart: if meshPart:
if hasattr( meshPart, "SetMesh" ):
meshPart.SetMesh( self.mesh ) # set mesh to filter
hist = fun.GetLocalHistogram( 1, False, meshPart ) hist = fun.GetLocalHistogram( 1, False, meshPart )
else: else:
hist = fun.GetHistogram( 1, False ) hist = fun.GetHistogram( 1, False )

View File

@ -410,7 +410,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst,
if ( u2node.empty() ) return myPoints; if ( u2node.empty() ) return myPoints;
const SMDS_MeshNode* node; const SMDS_MeshNode* node;
if ( IsClosed() ) if ( IsClosed() && !proxySubMesh[0] )
node = u2node.begin()->second; node = u2node.begin()->second;
else else
{ {