Merge branch 'master' into V9_3_BR

This commit is contained in:
vsr 2019-04-08 19:23:20 +03:00
commit 474a24023d
20 changed files with 480 additions and 213 deletions

View File

@ -116,7 +116,7 @@ If the parent mesh is already computed, then you can define the **Geometry** by
.. image:: ../images/choose_geom_selection_way.png
:align: center
**Direct geometry selection** enables selecting the sub-shape in the Objec Browser.
**Direct geometry selection** enables selecting the sub-shape in the Object Browser.
**Find geometry by mesh element selection** activates the following dialog.
.. image:: ../images/find_geom_by_mesh_elem.png

View File

@ -143,7 +143,7 @@ Extrusion of 2d elements along a closed path
.. |add| image:: ../images/add.png
.. |rem| image:: ../images/remove.png
* The elements can also be rotated around the path with rotaion center at the **Base point** to get the resulting mesh in a helical fashion. You can set the values of angles at the right, add them to **Rotation angles** list at the left by pressing the *"Add"* button |add| and remove them from the list by pressing the *"Remove"* button |rem|.
* The elements can also be rotated around the path with rotation center at the **Base point** to get the resulting mesh in a helical fashion. You can set the values of angles at the right, add them to **Rotation angles** list at the left by pressing the *"Add"* button |add| and remove them from the list by pressing the *"Remove"* button |rem|.
**Linear variation of angles** option allows defining the angle of gradual rotation for the whole path. At each step the elements will be rotated by *( angle / nb. of steps )*.

View File

@ -296,7 +296,7 @@ module SMESH
* \param invalidEntries - return study entries of objects whose
* counterparts are not found in the newGeometry, followed by entries
* of mesh sub-objects that are invalid because they depend on a not found
* preceeding sub-shape
* preceding sub-shape
*/
boolean CopyMeshWithGeom( in SMESH_Mesh sourceMesh,
in GEOM::GEOM_Object newGeometry,
@ -500,9 +500,9 @@ module SMESH
* Return indices of elements, which are located inside the sphere
* \param theSource - mesh, sub-mesh or group
* \param theElemType - mesh element type
* \param theX - x cooridate of the center of the sphere
* \param theY - y cooridate of the center of the sphere
* \param theZ - y cooridate of the center of the sphere
* \param theX - x coordinate of the center of the sphere
* \param theY - y coordinate of the center of the sphere
* \param theZ - y coordinate of the center of the sphere
* \param theR - radius of the sphere
*/
long_array GetInsideSphere( in SMESH_IDSource theSource,
@ -516,12 +516,12 @@ module SMESH
* Return indices of elements, which are located inside the box
* \param theSource - mesh, sub-mesh or group
* \param theElemType - mesh element type
* \param theX1 - x cooridate of the first opposite point
* \param theY1 - y cooridate of the first opposite point
* \param theZ1 - y cooridate of the first opposite point
* \param theX2 - x cooridate of the second opposite point
* \param theY2 - y cooridate of the second opposite point
* \param theZ2 - y cooridate of the second opposite point
* \param theX1 - x coordinate of the first opposite point
* \param theY1 - y coordinate of the first opposite point
* \param theZ1 - y coordinate of the first opposite point
* \param theX2 - x coordinate of the second opposite point
* \param theY2 - y coordinate of the second opposite point
* \param theZ2 - y coordinate of the second opposite point
*/
long_array GetInsideBox( in SMESH_IDSource theSource,
in ElementType theElemType,
@ -535,12 +535,12 @@ module SMESH
* Return indices of elements, which are located inside the box
* \param theSource - mesh, sub-mesh or group
* \param theElemType - mesh element type
* \param theX - x cooridate of the cented of the bottom face
* \param theY - y cooridate of the cented of the bottom face
* \param theZ - y cooridate of the cented of the bottom face
* \param theDX - x cooridate of the cented of the base vector
* \param theDY - y cooridate of the cented of the base vector
* \param theDZ - z cooridate of the cented of the base vector
* \param theX - x coordinate of the cented of the bottom face
* \param theY - y coordinate of the cented of the bottom face
* \param theZ - y coordinate of the cented of the bottom face
* \param theDX - x coordinate of the cented of the base vector
* \param theDY - y coordinate of the cented of the base vector
* \param theDZ - z coordinate of the cented of the base vector
* \param theH - height of the cylinder
* \param theR - radius of the cylinder
*/

View File

@ -193,7 +193,7 @@ namespace MED
TInt myNbElem; //<! Number of corresponding mesh entities
TInt GetNbElem() const { return myNbElem; } //! Get number of mesh elements
//! Defines sequence MED Family indexes for corresponding mesh entites
//! Defines sequence MED Family indexes for corresponding mesh entities
PElemNum myFamNum;
//! Get number of a MED FAMILY by order number of the mesh element
TInt GetFamNum(TInt theId) const;
@ -587,7 +587,7 @@ namespace MED
size_t
GetSize() const;
//! Returns MED interpetation of the value size
//! Returns MED interpretation of the value size
size_t
GetNbVal() const;

View File

@ -239,6 +239,9 @@ int SMDS_ElementFactory::FromVtkToSmds( vtkIdType vtkID )
void SMDS_ElementFactory::Free( const SMDS_MeshElement* e )
{
if ( e != FindElement( e->GetID() ))
SALOME_Exception("SMDS_ElementFactory::Free(): element of other mesh");
if ( !myVtkIDs.empty() )
{
size_t id = e->GetID() - 1;

View File

@ -147,6 +147,7 @@ namespace // Iterator
size_t myNbToFind, myNbFound, myTotalNb;
vector< const SMDS_MeshElement*>& myFoundElems;
bool & myFoundElemsOK;
bool myFoundElemsChecked;
TIterator( const SMESH_PredicatePtr& filter,
SMDS_ElemIteratorPtr& elems,
@ -161,14 +162,15 @@ namespace // Iterator
myNbFound( 0 ),
myTotalNb( totalNb ),
myFoundElems( foundElems ),
myFoundElemsOK( foundElemsOK )
myFoundElemsOK( foundElemsOK ),
myFoundElemsChecked( false )
{
myFoundElemsOK = false;
next();
}
~TIterator()
{
if ( !myFoundElemsOK )
if ( !myFoundElemsChecked && !myFoundElemsOK )
clearVector( myFoundElems );
}
virtual bool more()
@ -225,6 +227,8 @@ namespace // Iterator
}
if ( !myFoundElemsOK )
clearVector( myFoundElems );
myFoundElemsChecked = true; // in destructor: not to clearVector() which may already die
}
};

View File

@ -356,7 +356,7 @@ QString SMESHGUI_CopyMeshDlg::getErrorMsg( SMESH::string_array_var theInvalidEnt
// theInvalidEntries - SObject's that hold geometry objects whose
// counterparts are not found in the newGeometry, followed by SObject's
// holding mesh sub-objects that are invalid because they depend on a not found
// preceeding sub-shape
// preceding sub-shape
QString msg = tr("SUBSHAPES_NOT_FOUND_MSG") + "\n";

View File

@ -1402,7 +1402,7 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow,
theCriterion.Type != SMESH::FT_OverConstrainedVolume &&
theCriterion.Type != SMESH::FT_LinearOrQuadratic)
{
// Numberic criterion
// Numeric criterion
aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15));
}
else

View File

@ -81,7 +81,7 @@ public:
/*!
\brief Constructor.
\param parent Parent widget.
\param name Field name. Defauls to null string.
\param name Field name. Defaults to null string.
*/
Field::Field( QWidget* parent, const QString& name ): QLabel( parent )
{
@ -382,7 +382,7 @@ namespace
\brief Format connectivity data to string representation.
\param connectivity Connectivity map.
\param type Element type or face index if negative
\return Stringifed representation of the connectivity.
\return Stringified representation of the connectivity.
*/
QString formatConnectivity( SMESH::Connectivity connectivity, int type )
{
@ -1036,7 +1036,7 @@ void SMESHGUI_BaseInfo::setFieldsVisible( int startRow, int lastRow, bool on )
}
/*!
\brief Write information from panel to ouput stream.
\brief Write information from panel to output stream.
\param out Text stream output.
*/
void SMESHGUI_BaseInfo::saveInfo( QTextStream& out )
@ -1999,7 +1999,7 @@ void SMESHGUI_ElemInfo::updateControls()
}
/*!
\brief Write information from panel to ouput stream.
\brief Write information from panel to output stream.
\param out Text stream output.
*/
void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
@ -2864,7 +2864,7 @@ void SMESHGUI_AddInfo::showNextSubMeshes()
}
/*!
\brief Write information from panel to ouput stream.
\brief Write information from panel to output stream.
\param out Text stream output.
*/
void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
@ -2926,7 +2926,7 @@ public:
};
/*!
\brief Contructor.
\brief Constructor.
\param parent Parent widget.
\internal
*/

View File

@ -101,7 +101,7 @@ SMESH::SelectionProxy::SelectionProxy( const SelectionProxy& other )
void SMESH::SelectionProxy::init()
{
if ( myIO.IsNull() )
myIO = new SALOME_InteractiveObject(); // create dummy IO to avoid crashes when accesing it
myIO = new SALOME_InteractiveObject(); // create dummy IO to avoid crashes when accessing it
if ( !CORBA::is_nil( myObject ) )
{
@ -1376,7 +1376,7 @@ void SMESH::MedInfo::setVersion( uint major, uint minor, uint release )
////////////////////////////////////////////////////////////////////////////////
/*!
\brief Contructor. Creates invalid position.
\brief Constructor. Creates invalid position.
*/
SMESH::Position::Position():
myShapeId(-1), myShapeType(-1), myU(0), myV(0), myHasU(false), myHasV(false)

View File

@ -759,10 +759,7 @@ namespace SMESH_MeshAlgos
const double theSign,
const bool theOptimize );
//! Cut a face by planes, whose normals point to parts to keep
bool CutByPlanes(const SMDS_MeshElement* face,
const std::vector< gp_Ax1 > & planes,
std::vector< SMESH_NodeXYZ > & newConnectivity );
void IntersectNewEdges( const CutFace& theCFace );
private:
@ -815,7 +812,6 @@ namespace SMESH_MeshAlgos
bool & isCollinear );
bool intersectEdgeEdge( int iE1, int iE2, IntPoint2D& intPoint );
bool isPointInTriangle( const gp_XYZ& p, const std::vector< SMESH_NodeXYZ >& nodes );
void intersectNewEdges( const CutFace& theCFace );
const SMDS_MeshNode* createNode( const gp_XYZ& p );
};
@ -1662,7 +1658,7 @@ namespace SMESH_MeshAlgos
*/
//================================================================================
void Intersector::Algo::intersectNewEdges( const CutFace& cf )
void Intersector::Algo::IntersectNewEdges( const CutFace& cf )
{
IntPoint2D intPoint;
@ -1859,7 +1855,7 @@ namespace SMESH_MeshAlgos
}
}
if ( cf.myLinks.size() >= limit )
throw SALOME_Exception( "Infinite loop in Intersector::Algo::intersectNewEdges()" );
throw SALOME_Exception( "Infinite loop in Intersector::Algo::IntersectNewEdges()" );
}
++i1; // each internal edge encounters twice
}
@ -1913,7 +1909,7 @@ namespace SMESH_MeshAlgos
{
const CutFace& cf = *cutFacesIt;
cf.ReplaceNodes( myRemove2KeepNodes );
intersectNewEdges( cf );
IntersectNewEdges( cf );
}
// make new faces
@ -1948,7 +1944,7 @@ namespace SMESH_MeshAlgos
// avoid loops that are not connected to boundary edges of cf.myInitFace
if ( cf.RemoveInternalLoops( loopSet ))
{
intersectNewEdges( cf );
IntersectNewEdges( cf );
cf.MakeLoops( loopSet, normal );
}
// erase loops that are cut off by face intersections
@ -2228,6 +2224,10 @@ namespace SMESH_MeshAlgos
theNewFaceConnectivity.push_back( facePoints );
break;
}
// intersect cut lines
algo.IntersectNewEdges( cf );
// form loops of new faces
EdgeLoopSet loopSet;
cf.MakeLoops( loopSet, normals[ faceToCut->GetID() ]);
@ -2391,8 +2391,9 @@ namespace
// if ( !myLinks[i].IsInternal() )
// myLinks[ i ].myFace = cutterFace;
// else
myLinks[ i ].ReplaceCoplanar( newEdge );
myLinks[ i+1 ].ReplaceCoplanar( newEdge );
myLinks[ i ].ReplaceCoplanar( newEdge );
if ( myLinks[i].IsInternal() && i+1 < myLinks.size() )
myLinks[ i+1 ].ReplaceCoplanar( newEdge );
return;
}
i += myLinks[i].IsInternal();

View File

@ -42,12 +42,10 @@
#include <Utils_SALOME_Exception.hxx>
#include <boost/container/flat_set.hpp>
namespace
{
typedef SMESH_MeshAlgos::Edge TEdge;
//================================================================================
//! point of intersection of a face edge with the cylinder
struct IntPoint
@ -55,19 +53,50 @@ namespace
SMESH_NodeXYZ myNode; // point and a node
int myEdgeIndex; // face edge index
bool myIsOutPln[2]; // isOut of two planes
double SquareDistance( const IntPoint& p ) const { return ( myNode-p.myNode ).SquareModulus(); }
};
//================================================================================
//! cut of a face
struct Cut
{
IntPoint myIntPnt1, myIntPnt2;
const SMDS_MeshElement* myFace;
const IntPoint& operator[]( size_t i ) const { return i ? myIntPnt2 : myIntPnt1; }
double SquareDistance( const gp_Pnt& p, gp_XYZ & pClosest ) const
{
gp_Vec edge( myIntPnt1.myNode, myIntPnt2.myNode );
gp_Vec n1p ( myIntPnt1.myNode, p );
double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
if ( u <= 0. )
{
pClosest = myIntPnt1.myNode;
return n1p.SquareMagnitude();
}
if ( u >= 1. )
{
pClosest = myIntPnt2.myNode;
return p.SquareDistance( myIntPnt2.myNode );
}
pClosest = myIntPnt1.myNode + u * edge.XYZ(); // projection of the point on the edge
return p.SquareDistance( pClosest );
}
};
//================================================================================
//! poly-line segment
struct Segment
{
typedef boost::container::flat_set< const SMDS_MeshNode* > TNodeSet;
//typedef std::list< TEdge > TEdgeList;
typedef std::vector< Cut > TCutList;
const SMDS_MeshElement* myEdge;
TNodeSet myEndNodes; // ends of cut edges
//TEdgeList myCutEdges[2];
const SMDS_MeshElement* myEdge;
TCutList myCuts;
std::vector< const IntPoint* > myFreeEnds; // ends of cut edges
Segment( const SMDS_MeshElement* e = 0 ): myEdge(e) { myCuts.reserve( 4 ); }
// return its axis
gp_Ax1 Ax1( bool reversed = false ) const
@ -76,67 +105,100 @@ namespace
SMESH_NodeXYZ n2 = myEdge->GetNode( !reversed );
return gp_Ax1( n1, gp_Dir( n2 - n1 ));
}
// return a node
const SMDS_MeshNode* Node(int i) const
{
return myEdge->GetNode( i % 2 );
}
// store an intersection edge forming the slot border
void AddEdge( TEdge& e, double tol )
void AddCutEdge( const IntPoint& p1,
const IntPoint& p2,
const SMDS_MeshElement* myFace )
{
const SMDS_MeshNode** nodes = & e._node1;
for ( int i = 0; i < 2; ++i )
{
std::pair< TNodeSet::iterator, bool > nItAdded = myEndNodes.insert( nodes[ i ]);
if ( !nItAdded.second )
myEndNodes.erase( nItAdded.first );
}
myCuts.push_back( Cut({ p1, p2, myFace }));
}
// { -- PREV version
// int i = myCutEdges[0].empty() ? 0 : 1;
// std::insert_iterator< TEdgeList > where = inserter( myCutEdges[i], myCutEdges[i].begin() );
// //double minDist = 1e100;
// SMESH_NodeXYZ nNew[2] = { e._node1, e._node2 };
// int iNewMin = 0, iCurMin = 1;
// for ( i = 0; i < 2; ++i )
// {
// if ( myCutEdges[i].empty() )
// continue;
// SMESH_NodeXYZ nCur[2] = { myCutEdges[i].front()._node1,
// myCutEdges[i].back()._node2 };
// for ( int iN = 0; iN < 2; ++iN )
// for ( int iC = 0; iC < 2; ++iC )
// {
// if (( nCur[iC].Node() && nCur[iC] == nNew[iN] ) ||
// ( nCur[iC] - nNew[iN] ).SquareModulus() < tol * tol )
// {
// where = inserter( myCutEdges[i], iC ? myCutEdges[i].end() : myCutEdges[i].begin() );
// iNewMin = iN;
// iCurMin = iC;
// //minDist = dist;
// iN = 2;
// break;
// }
// }
// }
// if ( iNewMin == iCurMin )
// std::swap( e._node1, e._node2 );
// where = e;
// }
Segment( const SMDS_MeshElement* e = 0 ): myEdge(e) { myEndNodes.reserve( 4 ); }
// return number of not shared IntPoint's
int NbFreeEnds( double tol )
{
if ( myCuts.empty() )
return 0;
if ( myFreeEnds.empty() )
{
int nbShared = 0;
std::vector< bool > isSharedPnt( myCuts.size() * 2, false );
for ( size_t iC1 = 0; iC1 < myCuts.size() - 1; ++iC1 )
for ( size_t iP1 = 0; iP1 < 2; ++iP1 )
{
size_t i1 = iC1 * 2 + iP1;
if ( isSharedPnt[ i1 ])
continue;
for ( size_t iC2 = iC1 + 1; iC2 < myCuts.size(); ++iC2 )
for ( size_t iP2 = 0; iP2 < 2; ++iP2 )
{
size_t i2 = iC2 * 2 + iP2;
if ( isSharedPnt[ i2 ])
continue;
if ( myCuts[ iC1 ][ iP1 ].SquareDistance( myCuts[ iC2 ][ iP2 ]) < tol * tol )
{
nbShared += 2;
isSharedPnt[ i1 ] = isSharedPnt[ i2 ] = true;
}
}
}
myFreeEnds.reserve( isSharedPnt.size() - nbShared );
for ( size_t i = 0; i < isSharedPnt.size(); ++i )
if ( !isSharedPnt[ i ] )
{
int iP = i % 2;
int iC = i / 2;
myFreeEnds.push_back( & myCuts[ iC ][ iP ]);
}
}
return myFreeEnds.size();
}
};
typedef ObjectPoolIterator<Segment> TSegmentIterator;
//================================================================================
//! Segments and plane separating domains of segments, at common node
struct NodeData
{
std::vector< Segment* > mySegments;
gp_Ax1 myPlane; // oriented OK for mySegments[0]
void AddSegment( Segment* seg, const SMDS_MeshNode* n )
{
mySegments.reserve(2);
mySegments.push_back( seg );
if ( mySegments.size() == 1 )
{
myPlane = mySegments[0]->Ax1( mySegments[0]->myEdge->GetNodeIndex( n ));
}
else
{
gp_Ax1 axis2 = mySegments[1]->Ax1( mySegments[1]->myEdge->GetNodeIndex( n ));
myPlane.SetDirection( myPlane.Direction().XYZ() - axis2.Direction().XYZ() );
}
}
gp_Ax1 Plane( const Segment* seg )
{
return ( seg == mySegments[0] ) ? myPlane : myPlane.Reversed();
}
};
typedef NCollection_DataMap< const SMDS_MeshNode*, NodeData, SMESH_Hasher > TSegmentsOfNode;
//================================================================================
/*!
* \brief Intersect a face edge given by its nodes with a cylinder.
*/
//================================================================================
void intersectEdge( const gp_Cylinder& cyl,
bool intersectEdge( const gp_Cylinder& cyl,
const SMESH_NodeXYZ& n1,
const SMESH_NodeXYZ& n2,
const double tol,
@ -149,7 +211,7 @@ namespace
intersection.IsParallel() ||
intersection.IsInQuadric() ||
intersection.NbPoints() == 0 )
return;
return false;
gp_Vec edge( n1, n2 );
@ -196,7 +258,7 @@ namespace
std::swap( intPoints[ i ], intPoints[ i - 1 ]);
}
return;
return intPoints.size() - oldNbPnts > 0;
}
//================================================================================
@ -218,11 +280,11 @@ namespace
*/
//================================================================================
bool isOut( const gp_Pnt& p, const gp_Ax1* planeNormal, bool* isOutPtr )
bool isOut( const gp_Pnt& p, const gp_Ax1* planeNormal, bool* isOutPtr, int nbPln = 2 )
{
isOutPtr[0] = isOutPtr[1] = false;
for ( int i = 0; i < 2; ++i )
for ( int i = 0; i < nbPln; ++i )
{
isOutPtr[i] = ( signedDist( p, planeNormal[i] ) <= 0. );
}
@ -317,6 +379,131 @@ namespace
if ( !theWorkGroups.empty() )
theFaceID2Groups.Bind( theFace->GetID(), theWorkGroups );
}
//================================================================================
/*!
* \brief Check distance between a point and an edge defined by a couple of nodes
*/
//================================================================================
bool isOnEdge( const SMDS_MeshNode* n1,
const SMDS_MeshNode* n2,
const gp_Pnt& p,
const double tol )
{
SMDS_LinearEdge edge( n1, n2 );
return ( SMESH_MeshAlgos::GetDistance( &edge, p ) < tol );
}
//================================================================================
/*!
* \return Index of intersection point detected on a triangle cut by planes
* \param [in] i - index of a cut triangle side
* \param [in] n1 - 1st point of a cut triangle side
* \param [in] n2 - 2nd point of a cut triangle side
* \param [in] face - a not cut triangle
* \param [in] intPoint - the intersection point
* \param [in] faceNodes - nodes of not cut triangle
* \param [in] tol - tolerance
*/
//================================================================================
int edgeIndex( const int i,
const SMESH_NodeXYZ& n1,
const SMESH_NodeXYZ& n2,
const SMDS_MeshElement* face,
const IntPoint& intPoint,
const std::vector< const SMDS_MeshNode* >& faceNodes,
const double tol )
{
if ( n1.Node() && n2.Node() )
return face->GetNodeIndex( n1.Node() );
// project intPoint to sides of face
for ( size_t i = 1; i < faceNodes.size(); ++i )
if ( isOnEdge( faceNodes[ i-1 ], faceNodes[ i ], intPoint.myNode, tol ))
return i - 1;
return -(i+1);
}
//================================================================================
/*!
* \brief Find a neighboring segment and its next node
* \param [in] curSegment - a current segment
* \param [in,out] curNode - a current node to update
* \param [in] segmentsOfNode - map of segments of nodes
* \return Segment* - the found segment
*/
//================================================================================
Segment* nextSegment( const Segment* curSegment,
const SMDS_MeshNode* & curNode,
const TSegmentsOfNode& segmentsOfNode )
{
Segment* neighborSeg = 0;
const NodeData& noData = segmentsOfNode( curNode );
for ( size_t iS = 0; iS < noData.mySegments.size() && !neighborSeg; ++iS )
if ( noData.mySegments[ iS ] != curSegment )
neighborSeg = noData.mySegments[ iS ];
if ( neighborSeg )
{
int iN = ( neighborSeg->Node(0) == curNode );
curNode = neighborSeg->Node( iN );
}
return neighborSeg;
}
//================================================================================
/*!
* \brief Tries to find a segment to which a given point is too close
* \param [in] p - the point
* \param [in] minDist - minimal allowed distance from segment
* \param [in] curSegment - start segment
* \param [in] curNode - start node
* \param [in] segmentsOfNode - map of segments of nodes
* \return bool - true if a too close segment found
*/
//================================================================================
const Segment* findTooCloseSegment( const IntPoint& p,
const double minDist,
const double tol,
const Segment* curSegment,
const SMDS_MeshNode* curNode,
const TSegmentsOfNode& segmentsOfNode )
{
double prevDist = Precision::Infinite();
while ( curSegment )
{
double dist = SMESH_MeshAlgos::GetDistance( curSegment->myEdge, p.myNode );
if ( dist < minDist )
{
// check if dist is less than distance of curSegment to its cuts
// double minCutDist = prevDist;
// bool coincide = false;
// for ( size_t iC = 0; iC < curSegment->myCuts.size(); ++iC )
// {
// if (( coincide = ( curSegment->myCuts[iC].SquareDistance( p.myNode ) < tol * tol )))
// break;
// for ( size_t iP = 0; iP < 2; ++iP )
// {
// double cutDist = SMESH_MeshAlgos::GetDistance( curSegment->myEdge,
// curSegment->myCuts[iC][iP].myNode );
// minCutDist = std::min( minCutDist, cutDist );
// }
// }
// if ( !coincide && minCutDist > dist )
return curSegment;
}
if ( dist > prevDist )
break;
prevDist = dist;
curSegment = nextSegment( curSegment, curNode, segmentsOfNode );
}
return 0;
}
}
//================================================================================
@ -338,10 +525,10 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
if ( !theSegmentIt || !theSegmentIt->more() || !theMesh || theWidth == 0.)
return bndEdges;
// ----------------------------------------------------------------------------------
// put the input segments to a data map in order to be able finding neighboring ones
// ----------------------------------------------------------------------------------
typedef std::vector< Segment* > TSegmentVec;
typedef NCollection_DataMap< const SMDS_MeshNode*, TSegmentVec, SMESH_Hasher > TSegmentsOfNode;
TSegmentsOfNode segmentsOfNode;
ObjectPool< Segment > segmentPool;
@ -357,15 +544,16 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
for ( SMDS_NodeIteratorPtr nIt = edge->nodeIterator(); nIt->more(); )
{
const SMDS_MeshNode* n = nIt->next();
TSegmentVec* segVec = segmentsOfNode.ChangeSeek( n );
if ( !segVec )
segVec = segmentsOfNode.Bound( n, TSegmentVec() );
segVec->reserve(2);
segVec->push_back( segment );
NodeData* noData = segmentsOfNode.ChangeSeek( n );
if ( !noData )
noData = segmentsOfNode.Bound( n, NodeData() );
noData->AddSegment( segment, n );
}
}
// ---------------------------------
// Cut the mesh around the segments
// ---------------------------------
const double tol = Precision::Confusion();
std::vector< gp_XYZ > faceNormals;
@ -398,21 +586,8 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
// get normals of planes separating domains of neighboring segments
for ( int i = 0; i < 2; ++i ) // loop on 2 segment ends
{
planeNormal[i] = segment->Ax1(i);
const SMDS_MeshNode* n = segment->Node( i );
const TSegmentVec& segVec = segmentsOfNode( n );
for ( size_t iS = 0; iS < segVec.size(); ++iS )
{
if ( segVec[iS] == segment )
continue;
gp_Ax1 axis2 = segVec[iS]->Ax1();
if ( n != segVec[iS]->Node( 1 ))
axis2.Reverse(); // along a wire
planeNormal[i].SetDirection( planeNormal[i].Direction().XYZ() + axis2.Direction().XYZ() );
}
const SMDS_MeshNode* n = segment->Node( i );
planeNormal[i] = segmentsOfNode( n ).Plane( segment );
}
// we explore faces around a segment starting from face edges;
@ -455,11 +630,12 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
int nbNodes = face->NbCornerNodes();
if ( nbNodes != 3 )
throw SALOME_Exception( "MakeSlot() accepts triangles only" );
facePoints.assign( face->begin_nodes(), face->end_nodes() );
facePoints.resize( nbNodes + 1 );
facePoints[ nbNodes ] = facePoints[ 0 ];
faceNodes.assign( face->begin_nodes(), face->end_nodes() );
faceNodes.resize( nbNodes + 1 );
faceNodes[ nbNodes ] = faceNodes[ 0 ];
facePoints.assign( faceNodes.begin(), faceNodes.end() );
// check if cylinder axis || face
// check if cylinder axis || face
const gp_XYZ& faceNorm = computeNormal( face, faceNormals );
bool isCylinderOnFace = ( Abs( faceNorm * cylAxis.Direction().XYZ() ) < tol );
@ -489,28 +665,23 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
intPoints[ iP ].myEdgeIndex = i;
else
for ( ; iP < intPoints.size(); ++iP )
if ( n1.Node() && n2.Node() )
intPoints[ iP ].myEdgeIndex = face->GetNodeIndex( n1.Node() );
else
intPoints[ iP ].myEdgeIndex = -(i+1);
intPoints[ iP ].myEdgeIndex = edgeIndex( i, n1, n2, face,
intPoints[ iP ], faceNodes, tol );
nbFarPoints += ( segLine.SquareDistance( n1 ) > radius2 );
}
// feed startEdges
if ( nbFarPoints < nbPoints || !intPoints.empty() )
for ( int i = 0; i < nbPoints; ++i )
for ( size_t i = 1; i < faceNodes.size(); ++i )
{
const SMESH_NodeXYZ& n1 = facePoints[i];
const SMESH_NodeXYZ& n2 = facePoints[i+1];
if ( n1.Node() && n2.Node() )
const SMESH_NodeXYZ& n1 = faceNodes[i];
const SMESH_NodeXYZ& n2 = faceNodes[i-1];
isOut( n1, planeNormal, p[0].myIsOutPln );
isOut( n2, planeNormal, p[1].myIsOutPln );
if ( !isSegmentOut( p[0].myIsOutPln, p[1].myIsOutPln ))
{
isOut( n1, planeNormal, p[0].myIsOutPln );
isOut( n2, planeNormal, p[1].myIsOutPln );
if ( !isSegmentOut( p[0].myIsOutPln, p[1].myIsOutPln ))
{
startEdges.push_back( NLink( n1.Node(), n2.Node() ));
}
startEdges.push_back( NLink( n1.Node(), n2.Node() ));
}
}
@ -570,20 +741,12 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
cutOff( intPoints[iE-1], intPoints[iE],
planeNormal[ intPoints[iE-1].myIsOutPln[1] ], tol );
edegDir = intPoints[iE].myNode - intPoints[iE-1].myNode;
if ( edegDir.SquareModulus() < tol * tol )
gp_XYZ edegDirNew = intPoints[iE].myNode - intPoints[iE-1].myNode;
if ( edegDir * edegDirNew < 0 ||
edegDir.SquareModulus() < tol * tol )
continue; // fully cut off
// face cut
meshIntersector.Cut( face,
intPoints[iE-1].myNode, intPoints[iE-1].myEdgeIndex,
intPoints[iE ].myNode, intPoints[iE ].myEdgeIndex );
Edge e = { intPoints[iE].myNode.Node(), intPoints[iE-1].myNode.Node(), 0 };
segment->AddEdge( e, tol );
bndEdges.push_back( e );
findGroups( face, theGroupsToUpdate, faceID2Groups, groupVec );
segment->AddCutEdge( intPoints[iE], intPoints[iE-1], face );
}
} // loop on faces sharing an edge
@ -595,63 +758,151 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
} // loop on all input segments
// ----------------------------------------------------------
// If a plane fully cuts off edges of one side of a segment,
// it also may cut edges of adjacent segments
// ----------------------------------------------------------
for ( TSegmentIterator segIt( segmentPool ); segIt.more(); ) // loop on all segments
{
Segment* segment = const_cast< Segment* >( segIt.next() );
if ( segment->NbFreeEnds( tol ) >= 4 )
continue;
for ( int iE = 0; iE < 2; ++iE ) // loop on 2 segment ends
{
const SMDS_MeshNode* n1 = segment->Node( iE );
const SMDS_MeshNode* n2 = segment->Node( 1 - iE );
planeNormal[0] = segmentsOfNode( n1 ).Plane( segment );
bool isNeighborCut;
Segment* neighborSeg = segment;
do // check segments connected to the segment via n2
{
neighborSeg = nextSegment( neighborSeg, n2, segmentsOfNode );
if ( !neighborSeg )
break;
isNeighborCut = false;
for ( size_t iC = 0; iC < neighborSeg->myCuts.size(); ++iC ) // check cut edges
{
IntPoint* intPnt = &( neighborSeg->myCuts[iC].myIntPnt1 );
isOut( intPnt[0].myNode, planeNormal, intPnt[0].myIsOutPln, 1 );
isOut( intPnt[1].myNode, planeNormal, intPnt[1].myIsOutPln, 1 );
const Segment * closeSeg[2] = { 0, 0 };
if ( intPnt[0].myIsOutPln[0] )
closeSeg[0] = findTooCloseSegment( intPnt[0], 0.5 * theWidth - tol, tol,
segment, n1, segmentsOfNode );
if ( intPnt[1].myIsOutPln[0] )
closeSeg[1] = findTooCloseSegment( intPnt[1], 0.5 * theWidth - tol, tol,
segment, n1, segmentsOfNode );
int nbCut = bool( closeSeg[0] ) + bool( closeSeg[1] );
if ( nbCut == 0 )
continue;
isNeighborCut = true;
if ( nbCut == 2 ) // remove a cut
{
if ( iC < neighborSeg->myCuts.size() - 1 )
neighborSeg->myCuts[iC] = neighborSeg->myCuts.back();
neighborSeg->myCuts.pop_back();
}
else // shorten cuts of 1) neighborSeg and 2) closeSeg
{
// 1)
int iP = bool( closeSeg[1] );
gp_Lin segLine( closeSeg[iP]->Ax1() );
gp_Ax3 cylAxis( segLine.Location(), segLine.Direction() );
gp_Cylinder cyl( cylAxis, 0.5 * theWidth );
intPoints.clear();
if ( intersectEdge( cyl, intPnt[iP].myNode, intPnt[1-iP].myNode, tol, intPoints ) &&
intPoints[0].SquareDistance( intPnt[iP] ) > tol * tol )
intPnt[iP].myNode = intPoints[0].myNode;
// 2)
double minCutDist = theWidth;
gp_XYZ projection, closestProj;
int iCut;
for ( size_t iC = 0; iC < closeSeg[iP]->myCuts.size(); ++iC )
{
double cutDist = closeSeg[iP]->myCuts[iC].SquareDistance( intPnt[iP].myNode,
projection );
if ( cutDist < minCutDist )
{
closestProj = projection;
minCutDist = cutDist;
iCut = iC;
}
if ( minCutDist < tol * tol )
break;
}
double d1 = SMESH_MeshAlgos::GetDistance( neighborSeg->myEdge,
closeSeg[iP]->myCuts[iCut][0].myNode );
double d2 = SMESH_MeshAlgos::GetDistance( neighborSeg->myEdge,
closeSeg[iP]->myCuts[iCut][1].myNode );
int iP2 = ( d2 < d1 );
IntPoint& ip = const_cast< IntPoint& >( closeSeg[iP]->myCuts[iCut][iP2] );
ip = intPnt[iP];
}
// update myFreeEnds
neighborSeg->myFreeEnds.clear();
neighborSeg->NbFreeEnds( tol );
}
}
while ( isNeighborCut );
}
}
// -----------------------
// Cut faces by cut edges
// -----------------------
for ( TSegmentIterator segIt( segmentPool ); segIt.more(); ) // loop on all segments
{
Segment* segment = const_cast< Segment* >( segIt.next() );
for ( size_t iC = 0; iC < segment->myCuts.size(); ++iC )
{
Cut & cut = segment->myCuts[ iC ];
computeNormal( cut.myFace, faceNormals );
meshIntersector.Cut( cut.myFace,
cut.myIntPnt1.myNode, cut.myIntPnt1.myEdgeIndex,
cut.myIntPnt2.myNode, cut.myIntPnt2.myEdgeIndex );
Edge e = { cut.myIntPnt1.myNode.Node(), cut.myIntPnt2.myNode.Node(), 0 };
bndEdges.push_back( e );
findGroups( cut.myFace, theGroupsToUpdate, faceID2Groups, groupVec );
}
}
// -----------------------------------------
// Make cut at the end of group of segments
// -----------------------------------------
std::vector<const SMDS_MeshElement*> polySegments;
for ( TSegmentsOfNode::Iterator nSegsIt( segmentsOfNode ); nSegsIt.More(); nSegsIt.Next() )
{
const TSegmentVec& segVec = nSegsIt.Value();
if ( segVec.size() != 1 )
const NodeData& noData = nSegsIt.Value();
if ( noData.mySegments.size() != 1 )
continue;
const Segment* segment = segVec[0];
const SMDS_MeshNode* segNode = nSegsIt.Key();
const Segment* segment = noData.mySegments[0];
// find two end nodes of cut edges to make a cut between
if ( segment->myEndNodes.size() != 4 )
// find two IntPoint's of cut edges to make a cut between
if ( segment->myFreeEnds.size() != 4 )
throw SALOME_Exception( "MakeSlot(): too short end edge?" );
SMESH_MeshAlgos::PolySegment linkNodes;
gp_Ax1 planeNorm = segment->Ax1( segNode != segment->Node(0) );
double minDist[2] = { 1e100, 1e100 };
Segment::TNodeSet::const_iterator nIt = segment->myEndNodes.begin();
for ( ; nIt != segment->myEndNodes.end(); ++nIt )
std::multimap< double, const IntPoint* > dist2IntPntMap;
for ( size_t iE = 0; iE < segment->myFreeEnds.size(); ++iE )
{
SMESH_NodeXYZ n = *nIt;
double d = Abs( signedDist( n, planeNorm ));
double diff1 = minDist[0] - d, diff2 = minDist[1] - d;
int i;
if ( diff1 > 0 && diff2 > 0 )
{
i = ( diff1 < diff2 );
}
else if ( diff1 > 0 )
{
i = 0;
}
else if ( diff2 > 0 )
{
i = 1;
}
else
{
continue;
}
linkNodes.myXYZ[ i ] = n;
minDist [ i ] = d;
const SMESH_NodeXYZ& n = segment->myFreeEnds[ iE ]->myNode;
double d = Abs( signedDist( n, noData.myPlane ));
dist2IntPntMap.insert( std::make_pair( d, segment->myFreeEnds[ iE ]));
}
// for ( int iSide = 0; iSide < 2; ++iSide )
// {
// if ( segment->myCutEdges[ iSide ].empty() )
// throw SALOME_Exception( "MakeSlot(): too short end edge?" );
// SMESH_NodeXYZ n1 = segment->myCutEdges[ iSide ].front()._node1;
// SMESH_NodeXYZ n2 = segment->myCutEdges[ iSide ].back ()._node2;
// double d1 = Abs( signedDist( n1, planeNorm ));
// double d2 = Abs( signedDist( n2, planeNorm ));
// linkNodes.myXYZ [ iSide ] = ( d1 < d2 ) ? n1 : n2;
// linkNodes.myNode1[ iSide ] = linkNodes.myNode2[ iSide ] = 0;
// }
linkNodes.myVector = planeNorm.Direction() ^ (linkNodes.myXYZ[0] - linkNodes.myXYZ[1]);
std::multimap< double, const IntPoint* >::iterator d2ip = dist2IntPntMap.begin();
SMESH_MeshAlgos::PolySegment linkNodes;
linkNodes.myXYZ[0] = d2ip->second->myNode;
linkNodes.myXYZ[1] = (++d2ip)->second->myNode;
linkNodes.myVector = noData.myPlane.Direction() ^ (linkNodes.myXYZ[0] - linkNodes.myXYZ[1]);
linkNodes.myNode1[ 0 ] = linkNodes.myNode2[ 0 ] = 0;
linkNodes.myNode1[ 1 ] = linkNodes.myNode2[ 1 ] = 0;
@ -682,8 +933,7 @@ SMESH_MeshAlgos::MakeSlot( SMDS_ElemIteratorPtr theSegmentIt,
intPoints[iP].myEdgeIndex = -1;
for ( int iN = 0; iN < nbNodes && intPoints[iP].myEdgeIndex < 0; ++iN )
{
SMDS_LinearEdge edge( faceNodes[iN], faceNodes[iN+1] );
if ( SMESH_MeshAlgos::GetDistance( &edge, intPoints[iP].myNode) < tol )
if ( isOnEdge( faceNodes[iN], faceNodes[iN+1], intPoints[iP].myNode, tol ))
intPoints[iP].myEdgeIndex = iN;
}
}

View File

@ -3453,7 +3453,7 @@ namespace // utils for CopyMeshWithGeom()
* \param [out] invalidEntries - return study entries of objects whose
* counterparts are not found in the newGeometry, followed by entries
* of mesh sub-objects that are invalid because they depend on a not found
* preceeding sub-shape
* preceding sub-shape
* \return CORBA::Boolean - is a success
*/
//================================================================================

View File

@ -1104,6 +1104,10 @@ void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
if ( !aGroup )
return;
if ( aGroup->GetMeshServant() != this )
THROW_SALOME_CORBA_EXCEPTION( "RemoveGroup(): group does not belong to this mesh",
SALOME::BAD_PARAM );
SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup );
if ( !aGroupSO->_is_nil() )
{
@ -1138,6 +1142,11 @@ void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup
if ( theGroup->_is_nil() )
return;
SMESH_GroupBase_i* groupImpl = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup );
if ( !groupImpl || groupImpl->GetMeshServant() != this )
THROW_SALOME_CORBA_EXCEPTION( "RemoveGroupWithContents(): group does not belong to this mesh",
SALOME::BAD_PARAM);
vector<int> nodeIds; // to remove nodes becoming free
bool isNodal = ( theGroup->GetType() == SMESH::NODE );
if ( !isNodal && !theGroup->IsEmpty() )

View File

@ -603,7 +603,7 @@ SMESH_Invalid_subMesh_i::SMESH_Invalid_subMesh_i( PortableServer::POA_ptr thePOA
//=======================================================================
//function : GetSubShape
//purpose : return geomtry which is not a sub-shape of the main shape
//purpose : return geometry which is not a sub-shape of the main shape
//=======================================================================
GEOM::GEOM_Object_ptr SMESH_Invalid_subMesh_i::GetSubShape()

View File

@ -34,7 +34,7 @@ import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New()
# ---- define a boxe
# ---- define a box
box = geompy.MakeBox(0., 0., 0., 100., 200., 300.)
@ -52,7 +52,7 @@ print("number of Edges in box : ", len(subEdgeList))
### ---------------------------- SMESH --------------------------------------
# ---- init a Mesh with the boxe
# ---- init a Mesh with the box
mesh = smesh.Mesh(box, "MeshBox")
@ -90,7 +90,7 @@ print(hypVolume.GetId())
print(hypVolume.GetMaxElementVolume())
smesh.SetName(hypVolume, "MaxElementVolume_" + str(maxElementVolume))
print("-------------------------- compute the mesh of the boxe")
print("-------------------------- compute the mesh of the box")
ret = mesh.Compute()
print(ret)
if ret != 0:

View File

@ -812,7 +812,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
Parameters:
sourceMesh: the mesh to copy definition of.
newGeom: the new geomtry.
newGeom: the new geometry.
meshName: an optional name of the new mesh. If omitted, the mesh name is kept.
toCopyGroups: to create groups in the new mesh.
toReuseHypotheses: to reuse hypotheses of the *sourceMesh*.
@ -823,7 +823,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
*invalidEntries* are study entries of objects whose
counterparts are not found in the *newGeom*, followed by entries
of mesh sub-objects that are invalid because they depend on a not found
preceeding sub-shape
preceding sub-shape
"""
if isinstance( sourceMesh, Mesh ):
sourceMesh = sourceMesh.GetMesh()
@ -6419,7 +6419,7 @@ class Mesh(metaclass = MeshMeta):
holeNodes = SMESH.FreeBorder(nodeIDs=holeNodes)
if not isinstance( holeNodes, SMESH.FreeBorder ):
raise TypeError("holeNodes must be either SMESH.FreeBorder or list of integer and not %s" % holeNodes)
self.editor.FillHole( holeNodes, groupName )
return self.editor.FillHole( holeNodes, groupName )
def FindCoincidentFreeBorders (self, tolerance=0.):
"""

View File

@ -3989,10 +3989,10 @@ bool StdMeshers_PrismAsBlock::GetLayersTransformation(vector<gp_Trsf> &
//================================================================================
/*!
* \brief Check curve orientation of a bootom edge
* \brief Check curve orientation of a bottom edge
* \param meshDS - mesh DS
* \param columnsMap - node columns map of side face
* \param bottomEdge - the bootom edge
* \param bottomEdge - the bottom edge
* \param sideFaceID - side face in-block ID
* \retval bool - true if orientation coincide with in-block forward orientation
*/

View File

@ -245,10 +245,10 @@ class STDMESHERS_EXPORT StdMeshers_PrismAsBlock: public SMESH_Block
{ return myShapeIDMap.FindIndex( shape ); }
/*!
* \brief Check curve orientation of a bootom edge
* \brief Check curve orientation of a bottom edge
* \param meshDS - mesh DS
* \param columnsMap - node columns map of side face
* \param bottomEdge - the bootom edge
* \param bottomEdge - the bottom edge
* \param sideFaceID - side face in-block ID
* \retval bool - true if orientation coincide with in-block forward orientation
*/

View File

@ -1591,7 +1591,7 @@ namespace VISCOUS_3D
//================================================================================
/*!
* \brief Computes mimimal distance of face in-FACE nodes from an EDGE
* \brief Computes minimal distance of face in-FACE nodes from an EDGE
* \param [in] face - the mesh face to treat
* \param [in] nodeOnEdge - a node on the EDGE
* \param [out] faceSize - the computed distance
@ -4091,7 +4091,7 @@ gp_XYZ _OffsetPlane::GetCommonPoint(bool& isFound,
//================================================================================
/*!
* \brief Find 2 neigbor nodes of a node on EDGE
* \brief Find 2 neighbor nodes of a node on EDGE
*/
//================================================================================
@ -4136,7 +4136,7 @@ bool _ViscousBuilder::findNeiborsOnEdge(const _LayerEdge* edge,
//================================================================================
/*!
* \brief Set _curvature and _2neibors->_plnNorm by 2 neigbor nodes residing the same EDGE
* \brief Set _curvature and _2neibors->_plnNorm by 2 neighbor nodes residing the same EDGE
*/
//================================================================================