// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
// File : SMESH_Pattern.hxx
// Created : Mon Aug 2 10:30:00 2004
// Author : Edward AGAPOV (eap)
+using namespace std;
+
#include "SMESH_Pattern.hxx"
-#include <Bnd_Box2d.hxx>
+#include <BRepAdaptor_Curve.hxx>
#include <BRepTools.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <BRep_Tool.hxx>
+#include <Bnd_Box.hxx>
+#include <Bnd_Box2d.hxx>
+#include <ElSLib.hxx>
+#include <Extrema_ExtPC.hxx>
+#include <Extrema_GenExtPS.hxx>
+#include <Extrema_POnSurf.hxx>
#include <Geom2d_Curve.hxx>
+#include <GeomAdaptor_Surface.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
-#include <IntAna2d_AnaIntersection.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
+#include <gp_Ax2.hxx>
#include <gp_Lin2d.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_XY.hxx>
#include <gp_XYZ.hxx>
-#include <Extrema_GenExtPS.hxx>
-#include <Extrema_POnSurf.hxx>
-#include <GeomAdaptor_Surface.hxx>
#include "SMDS_EdgePosition.hxx"
#include "SMDS_FacePosition.hxx"
#include "SMDS_MeshElement.hxx"
+#include "SMDS_MeshFace.hxx"
#include "SMDS_MeshNode.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMESHDS_Group.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESHDS_SubMesh.hxx"
-#include "SMESH_Mesh.hxx"
#include "SMESH_Block.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
#include "SMESH_subMesh.hxx"
#include "utilities.h"
typedef map< const SMDS_MeshElement*, int > TNodePointIDMap;
+#define smdsNode( elem ) static_cast<const SMDS_MeshNode*>( elem )
+
//=======================================================================
//function : SMESH_Pattern
//purpose :
while ( readLine( fields, lineBeg, clearFields ))
{
- myElemPointIDs.push_back( list< int >() );
- list< int >& elemPoints = myElemPointIDs.back();
+ myElemPointIDs.push_back( TElemDef() );
+ TElemDef& elemPoints = myElemPointIDs.back();
for ( fIt = fields.begin(); fIt != fields.end(); fIt++ )
{
int pointIndex = getInt( *fIt );
}
// elements
theFile << "!!! Indices of points of " << myElemPointIDs.size() << " elements:" << endl;
- list<list< int > >::const_iterator epIt = myElemPointIDs.begin();
+ list<TElemDef >::const_iterator epIt = myElemPointIDs.begin();
for ( ; epIt != myElemPointIDs.end(); epIt++ )
{
- const list< int > & elemPoints = *epIt;
- list< int >::const_iterator iIt = elemPoints.begin();
+ const TElemDef & elemPoints = *epIt;
+ TElemDef::const_iterator iIt = elemPoints.begin();
for ( ; iIt != elemPoints.end(); iIt++ )
theFile << " " << *iIt;
theFile << endl;
template<typename T> void sortBySize( list< list < T > > & theListOfList )
{
if ( theListOfList.size() > 2 ) {
- // keep the car
- //list < T > & aFront = theListOfList.front();
- // sort the whole list
TSizeCmp< T > SizeCmp;
theListOfList.sort( SizeCmp );
}
}
-//=======================================================================
-//function : getOrderedEdges
-//purpose : return nb wires and a list of oredered edges
-//=======================================================================
-
-static int getOrderedEdges (const TopoDS_Face& theFace,
- const TopoDS_Vertex& theFirstVertex,
- list< TopoDS_Edge >& theEdges,
- list< int > & theNbVertexInWires)
-{
- // put wires in a list, so that an outer wire comes first
- list<TopoDS_Wire> aWireList;
- TopoDS_Wire anOuterWire = BRepTools::OuterWire( theFace );
- aWireList.push_back( anOuterWire );
- for ( TopoDS_Iterator wIt (theFace); wIt.More(); wIt.Next() )
- if ( !anOuterWire.IsSame( wIt.Value() ))
- aWireList.push_back( TopoDS::Wire( wIt.Value() ));
-
- // loop on edges of wires
- theNbVertexInWires.clear();
- list<TopoDS_Wire>::iterator wlIt = aWireList.begin();
- for ( ; wlIt != aWireList.end(); wlIt++ )
- {
- int iE;
- BRepTools_WireExplorer wExp( *wlIt, theFace );
- for ( iE = 0; wExp.More(); wExp.Next(), iE++ )
- {
- TopoDS_Edge edge = wExp.Current();
- edge = TopoDS::Edge( edge.Oriented( wExp.Orientation() ));
- theEdges.push_back( edge );
- }
- theNbVertexInWires.push_back( iE );
- iE = 0;
- if ( wlIt == aWireList.begin() && theEdges.size() > 1 ) { // the outer wire
- // orient closed edges
- list< TopoDS_Edge >::iterator eIt, eIt2;
- for ( eIt = theEdges.begin(); eIt != theEdges.end(); eIt++ )
- {
- TopoDS_Edge& edge = *eIt;
- if ( TopExp::FirstVertex( edge ).IsSame( TopExp::LastVertex( edge ) ))
- {
- eIt2 = eIt;
- bool isNext = ( eIt2 == theEdges.begin() );
- TopoDS_Edge edge2 = isNext ? *(++eIt2) : *(--eIt2);
- double f1,l1,f2,l2;
- Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( edge, theFace, f1,l1 );
- Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( edge2, theFace, f2,l2 );
- gp_Pnt2d pf = c1->Value( edge.Orientation() == TopAbs_FORWARD ? f1 : l1 );
- gp_Pnt2d pl = c1->Value( edge.Orientation() == TopAbs_FORWARD ? l1 : f1 );
- bool isFirst = ( edge2.Orientation() == TopAbs_FORWARD ? isNext : !isNext );
- gp_Pnt2d p2 = c2->Value( isFirst ? f2 : l2 );
- isFirst = ( p2.SquareDistance( pf ) < p2.SquareDistance( pl ));
- if ( isNext ? isFirst : !isFirst )
- edge.Reverse();
- }
- }
- // rotate theEdges until it begins from theFirstVertex
- if ( ! theFirstVertex.IsNull() )
- while ( !theFirstVertex.IsSame( TopExp::FirstVertex( theEdges.front(), true )))
- {
- theEdges.splice(theEdges.end(), theEdges,
- theEdges.begin(), ++ theEdges.begin());
- if ( iE++ > theNbVertexInWires.back() )
- break; // break infinite loop
- }
- }
- }
-
- return aWireList.size();
-}
-
//=======================================================================
//function : project
//purpose :
}
//=======================================================================
-//function : isMeshBoundToShape
-//purpose : return true if all 2d elements are bound to shape
+//function : areNodesBound
+//purpose : true if all nodes of faces are bound to shapes
//=======================================================================
-static bool isMeshBoundToShape(SMESH_Mesh* theMesh)
+template <class TFaceIterator> bool areNodesBound( TFaceIterator & faceItr )
{
- // check faces binding
- SMESHDS_Mesh * aMeshDS = theMesh->GetMeshDS();
- SMESHDS_SubMesh * aMainSubMesh = aMeshDS->MeshElements( aMeshDS->ShapeToMesh() );
- if ( aMeshDS->NbFaces() != aMainSubMesh->NbElements() )
- return false;
-
- // check face nodes binding
- SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
- while ( fIt->more() )
+ while ( faceItr->more() )
{
- SMDS_ElemIteratorPtr nIt = fIt->next()->nodesIterator();
+ SMDS_ElemIteratorPtr nIt = faceItr->next()->nodesIterator();
while ( nIt->more() )
{
- const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nIt->next() );
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
SMDS_PositionPtr pos = node->GetPosition();
- if ( !pos || !pos->GetShapeId() )
+ if ( !pos || !pos->GetShapeId() ) {
return false;
+ }
}
}
return true;
}
+//=======================================================================
+//function : isMeshBoundToShape
+//purpose : return true if all 2d elements are bound to shape
+// if aFaceSubmesh != NULL, then check faces bound to it
+// else check all faces in aMeshDS
+//=======================================================================
+
+static bool isMeshBoundToShape(SMESHDS_Mesh * aMeshDS,
+ SMESHDS_SubMesh * aFaceSubmesh,
+ const bool isMainShape)
+{
+ if ( isMainShape ) {
+ // check that all faces are bound to aFaceSubmesh
+ if ( aMeshDS->NbFaces() != aFaceSubmesh->NbElements() )
+ return false;
+ }
+
+ // check face nodes binding
+ if ( aFaceSubmesh ) {
+ SMDS_ElemIteratorPtr fIt = aFaceSubmesh->GetElements();
+ return areNodesBound( fIt );
+ }
+ SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
+ return areNodesBound( fIt );
+}
+
//=======================================================================
//function : Load
//purpose : Create a pattern from the mesh built on <theFace>.
SMESHDS_Mesh * aMeshDS = theMesh->GetMeshDS();
SMESHDS_SubMesh * fSubMesh = aMeshDS->MeshElements( theFace );
+ SMESH_MesherHelper helper( *theMesh );
+ helper.SetSubShape( theFace );
int nbNodes = ( !fSubMesh ? 0 : fSubMesh->NbNodes() );
int nbElems = ( !fSubMesh ? 0 : fSubMesh->NbElements() );
return setErrorCode( ERR_LOAD_EMPTY_SUBMESH );
}
+ TopoDS_Face face = TopoDS::Face( theFace.Oriented( TopAbs_FORWARD ));
+
// check that face is not closed
+ bool isClosed = helper.HasSeam();
TopoDS_Vertex bidon;
list<TopoDS_Edge> eList;
- getOrderedEdges( theFace, bidon, eList, myNbKeyPntInBoundary );
- list<TopoDS_Edge>::iterator elIt = eList.begin();
- for ( ; elIt != eList.end() ; elIt++ )
- if ( BRep_Tool::IsClosed( *elIt , theFace ))
- return setErrorCode( ERR_LOADF_CLOSED_FACE );
-
+ list<TopoDS_Edge>::iterator elIt;
+ SMESH_Block::GetOrderedEdges( face, bidon, eList, myNbKeyPntInBoundary );
+
+ // check that requested or needed projection is possible
+ bool isMainShape = theMesh->IsMainShape( face );
+ bool needProject = !isMeshBoundToShape( aMeshDS, fSubMesh, isMainShape );
+ bool canProject = ( nbElems ? true : isMainShape );
+ if ( isClosed )
+ canProject = false; // so far
+
+ if ( ( theProject || needProject ) && !canProject )
+ return setErrorCode( ERR_LOADF_CANT_PROJECT );
Extrema_GenExtPS projector;
- GeomAdaptor_Surface aSurface( BRep_Tool::Surface( theFace ));
- if ( theProject || nbElems == 0 )
+ GeomAdaptor_Surface aSurface( BRep_Tool::Surface( face ));
+ if ( theProject || needProject )
projector.Initialize( aSurface, 20,20, 1e-5,1e-5 );
int iPoint = 0;
TNodePointIDMap nodePointIDMap;
+ TNodePointIDMap closeNodePointIDMap; // for nodes on seam edges
- if ( nbElems == 0 || (theProject &&
- theMesh->IsMainShape( theFace ) &&
- !isMeshBoundToShape( theMesh )))
+ if ( needProject )
{
- MESSAGE("Project the whole mesh");
+ MESSAGE("Project the submesh");
// ---------------------------------------------------------------
- // The case where the whole mesh is projected to theFace
+ // The case where the submesh is projected to theFace
// ---------------------------------------------------------------
- // put nodes of all faces in the nodePointIDMap and fill myElemPointIDs
- SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
- while ( fIt->more() )
+ // get all faces
+ list< const SMDS_MeshElement* > faces;
+ if ( nbElems > 0 ) {
+ SMDS_ElemIteratorPtr fIt = fSubMesh->GetElements();
+ while ( fIt->more() ) {
+ const SMDS_MeshElement* f = fIt->next();
+ if ( f && f->GetType() == SMDSAbs_Face )
+ faces.push_back( f );
+ }
+ }
+ else {
+ SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
+ while ( fIt->more() )
+ faces.push_back( fIt->next() );
+ }
+
+ // put nodes of all faces into the nodePointIDMap and fill myElemPointIDs
+ list< const SMDS_MeshElement* >::iterator fIt = faces.begin();
+ for ( ; fIt != faces.end(); ++fIt )
{
- myElemPointIDs.push_back( list< int >() );
- list< int >& elemPoints = myElemPointIDs.back();
- SMDS_ElemIteratorPtr nIt = fIt->next()->nodesIterator();
+ myElemPointIDs.push_back( TElemDef() );
+ TElemDef& elemPoints = myElemPointIDs.back();
+ SMDS_ElemIteratorPtr nIt = (*fIt)->nodesIterator();
while ( nIt->more() )
{
const SMDS_MeshElement* node = nIt->next();
if ( nIdIt == nodePointIDMap.end() )
{
elemPoints.push_back( iPoint );
- nodePointIDMap.insert( TNodePointIDMap::value_type( node, iPoint++ ));
+ nodePointIDMap.insert( make_pair( node, iPoint++ ));
}
else
elemPoints.push_back( (*nIdIt).second );
TNodePointIDMap::iterator nIdIt = nodePointIDMap.begin();
for ( ; nIdIt != nodePointIDMap.end(); nIdIt++ )
{
- const SMDS_MeshNode* node =
- static_cast<const SMDS_MeshNode*>( (*nIdIt).first );
+ const SMDS_MeshNode* node = smdsNode( (*nIdIt).first );
TPoint * p = & myPoints[ (*nIdIt).second ];
p->myInitUV = project( node, projector );
p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 );
}
// find key-points: the points most close to UV of vertices
- TopExp_Explorer vExp( theFace, TopAbs_VERTEX );
+ TopExp_Explorer vExp( face, TopAbs_VERTEX );
set<int> foundIndices;
for ( ; vExp.More(); vExp.Next() ) {
const TopoDS_Vertex v = TopoDS::Vertex( vExp.Current() );
- gp_Pnt2d uv = BRep_Tool::Parameters( v, theFace );
+ gp_Pnt2d uv = BRep_Tool::Parameters( v, face );
double minDist = DBL_MAX;
int index;
vector< TPoint >::const_iterator pVecIt = myPoints.begin();
// vertices
for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) {
myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
+ if ( BRep_Tool::IsClosed( *elIt, theFace ) )
+ myShapeIDMap.Add( TopExp::LastVertex( *elIt, true ));
SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( *elIt );
if ( eSubMesh )
nbNodes += eSubMesh->NbNodes() + 1;
for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
myShapeIDMap.Add( *elIt );
// the face
- myShapeIDMap.Add( theFace );
+ myShapeIDMap.Add( face );
myPoints.resize( nbNodes );
TopoDS_Edge & edge = *elIt;
list< TPoint* > & ePoints = getShapePoints( edge );
double f, l;
- Handle(Geom2d_Curve) C2d;
- if ( !theProject )
- C2d = BRep_Tool::CurveOnSurface( edge, theFace, f, l );
+ Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( edge, face, f, l );
bool isForward = ( edge.Orientation() == TopAbs_FORWARD );
+ TopoDS_Shape v1 = TopExp::FirstVertex( edge, true ); // always FORWARD
+ TopoDS_Shape v2 = TopExp::LastVertex( edge, true ); // always REVERSED
+ // to make adjacent edges share key-point, we make v2 FORWARD too
+ // (as we have different points for same shape with different orienation)
+ v2.Reverse();
+
+ // on closed face we must have REVERSED some of seam vertices
+ bool isSeam = helper.IsSeamShape( edge );
+ if ( isClosed ) {
+ if ( isSeam ) { // reverse on reversed SEAM edge
+ if ( !isForward ) {
+ v1.Reverse();
+ v2.Reverse();
+ }
+ }
+ else { // on CLOSED edge
+ for ( int is2 = 0; is2 < 2; ++is2 ) {
+ TopoDS_Shape & v = is2 ? v2 : v1;
+ if ( helper.IsSeamShape( v ) ) {
+ // reverse or not depending on orientation of adjacent seam
+ TopoDS_Edge seam;
+ list<TopoDS_Edge>::iterator eIt2 = elIt;
+ if ( is2 )
+ seam = ( ++eIt2 == eList.end() ? eList.front() : *eIt2 );
+ else
+ seam = ( eIt2 == eList.begin() ? eList.back() : *(--eIt2) );
+ if ( seam.Orientation() == TopAbs_REVERSED )
+ v.Reverse();
+ }
+ }
+ }
+ }
+
// the forward key-point
- TopoDS_Shape v = TopExp::FirstVertex( edge, true );
- list< TPoint* > & vPoint = getShapePoints( v );
- if ( vPoint.empty() )
+ list< TPoint* > * vPoint = & getShapePoints( v1 );
+ if ( vPoint->empty() )
{
- SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v );
+ SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v1 );
if ( vSubMesh && vSubMesh->NbNodes() ) {
myKeyPointIDs.push_back( iPoint );
SMDS_NodeIteratorPtr nIt = vSubMesh->GetNodes();
const SMDS_MeshNode* node = nIt->next();
- nodePointIDMap.insert( TNodePointIDMap::value_type( node, iPoint ));
+ if ( v1.Orientation() == TopAbs_REVERSED )
+ closeNodePointIDMap.insert( make_pair( node, iPoint ));
+ else
+ nodePointIDMap.insert( make_pair( node, iPoint ));
TPoint* keyPoint = &myPoints[ iPoint++ ];
- vPoint.push_back( keyPoint );
+ vPoint->push_back( keyPoint );
if ( theProject )
keyPoint->myInitUV = project( node, projector );
else
keyPoint->myInitXYZ.SetCoord (keyPoint->myInitUV.X(), keyPoint->myInitUV.Y(), 0);
}
}
- if ( !vPoint.empty() )
- ePoints.push_back( vPoint.front() );
+ if ( !vPoint->empty() )
+ ePoints.push_back( vPoint->front() );
// on-edge points
SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edge );
SMDS_NodeIteratorPtr nIt = eSubMesh->GetNodes();
while ( nIt->more() )
{
- const SMDS_MeshNode* node =
- static_cast<const SMDS_MeshNode*>( nIt->next() );
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
const SMDS_EdgePosition* epos =
static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
double u = epos->GetUParameter();
- paramNodeMap.insert( TParamNodeMap::value_type( u, node ));
+ paramNodeMap.insert( make_pair( u, node ));
+ }
+ if ( paramNodeMap.size() != eSubMesh->NbNodes() ) {
+ // wrong U on edge, project
+ Extrema_ExtPC proj;
+ BRepAdaptor_Curve aCurve( edge );
+ proj.Initialize( aCurve, f, l );
+ paramNodeMap.clear();
+ nIt = eSubMesh->GetNodes();
+ for ( int iNode = 0; nIt->more(); ++iNode ) {
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
+ proj.Perform( gp_Pnt( node->X(), node->Y(), node->Z()));
+ double u = 0;
+ if ( proj.IsDone() ) {
+ for ( int i = 1, nb = proj.NbExt(); i <= nb; ++i )
+ if ( proj.IsMin( i )) {
+ u = proj.Point( i ).Parameter();
+ break;
+ }
+ } else {
+ u = isForward ? iNode : eSubMesh->NbNodes() - iNode;
+ }
+ paramNodeMap.insert( make_pair( u, node ));
+ }
}
// put U in [0,1] so that the first key-point has U==0
double du = l - f;
TPoint* p = & myPoints[ iPoint ];
ePoints.push_back( p );
const SMDS_MeshNode* node = isForward ? (*unIt).second : (*unRIt).second;
- nodePointIDMap.insert ( TNodePointIDMap::value_type( node, iPoint ));
+ if ( isSeam && !isForward )
+ closeNodePointIDMap.insert( make_pair( node, iPoint ));
+ else
+ nodePointIDMap.insert ( make_pair( node, iPoint ));
if ( theProject )
p->myInitUV = project( node, projector );
}
}
// the reverse key-point
- v = TopExp::LastVertex( edge, true ).Reversed();
- list< TPoint* > & vPoint2 = getShapePoints( v );
- if ( vPoint2.empty() )
+ vPoint = & getShapePoints( v2 );
+ if ( vPoint->empty() )
{
- SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v );
+ SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v2 );
if ( vSubMesh && vSubMesh->NbNodes() ) {
myKeyPointIDs.push_back( iPoint );
SMDS_NodeIteratorPtr nIt = vSubMesh->GetNodes();
const SMDS_MeshNode* node = nIt->next();
- nodePointIDMap.insert( TNodePointIDMap::value_type( node, iPoint ));
+ if ( v2.Orientation() == TopAbs_REVERSED )
+ closeNodePointIDMap.insert( make_pair( node, iPoint ));
+ else
+ nodePointIDMap.insert( make_pair( node, iPoint ));
TPoint* keyPoint = &myPoints[ iPoint++ ];
- vPoint2.push_back( keyPoint );
+ vPoint->push_back( keyPoint );
if ( theProject )
keyPoint->myInitUV = project( node, projector );
else
keyPoint->myInitXYZ.SetCoord( keyPoint->myInitUV.X(), keyPoint->myInitUV.Y(), 0 );
}
}
- if ( !vPoint2.empty() )
- ePoints.push_back( vPoint2.front() );
+ if ( !vPoint->empty() )
+ ePoints.push_back( vPoint->front() );
// compute U of edge-points
if ( theProject )
if ( fSubMesh && fSubMesh->NbElements() )
{
- list< TPoint* > & fPoints = getShapePoints( theFace );
+ list< TPoint* > & fPoints = getShapePoints( face );
SMDS_NodeIteratorPtr nIt = fSubMesh->GetNodes();
while ( nIt->more() )
{
- const SMDS_MeshNode* node =
- static_cast<const SMDS_MeshNode*>( nIt->next() );
- nodePointIDMap.insert( TNodePointIDMap::value_type( node, iPoint ));
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
+ nodePointIDMap.insert( make_pair( node, iPoint ));
TPoint* p = &myPoints[ iPoint++ ];
fPoints.push_back( p );
if ( theProject )
}
// load elements
SMDS_ElemIteratorPtr elemIt = fSubMesh->GetElements();
- while ( elemIt->more() ) {
- SMDS_ElemIteratorPtr nIt = elemIt->next()->nodesIterator();
- myElemPointIDs.push_back( list< int >() );
- list< int >& elemPoints = myElemPointIDs.back();
+ while ( elemIt->more() )
+ {
+ const SMDS_MeshElement* elem = elemIt->next();
+ SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
+ myElemPointIDs.push_back( TElemDef() );
+ TElemDef& elemPoints = myElemPointIDs.back();
+ // find point indices corresponding to element nodes
while ( nIt->more() )
- elemPoints.push_back( nodePointIDMap[ nIt->next() ]);
+ {
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
+ iPoint = nodePointIDMap[ node ]; // point index of interest
+ // for a node on a seam edge there are two points
+ TNodePointIDMap::iterator n_id = closeNodePointIDMap.end();
+ if ( helper.IsSeamShape( node->GetPosition()->GetShapeId() ))
+ n_id = closeNodePointIDMap.find( node );
+ if ( n_id != closeNodePointIDMap.end() )
+ {
+ TPoint & p1 = myPoints[ iPoint ];
+ TPoint & p2 = myPoints[ n_id->second ];
+ // Select point closest to the rest nodes of element in UV space
+ SMDS_ElemIteratorPtr nIt2 = elem->nodesIterator();
+ const SMDS_MeshNode* notSeamNode = 0;
+ // find node not on a seam edge
+ while ( nIt2->more() && !notSeamNode ) {
+ const SMDS_MeshNode* n = smdsNode( nIt2->next() );
+ if ( !helper.IsSeamShape( n->GetPosition()->GetShapeId() ))
+ notSeamNode = n;
+ }
+ gp_Pnt2d uv = helper.GetNodeUV( theFace, node, notSeamNode );
+ double dist1 = uv.SquareDistance( p1.myInitUV );
+ double dist2 = uv.SquareDistance( p2.myInitUV );
+ if ( dist2 < dist1 )
+ iPoint = n_id->second;
+ }
+ elemPoints.push_back( iPoint );
+ }
}
}
double dU = maxU - minU, dV = maxV - minV;
if ( dU <= DBL_MIN || dV <= DBL_MIN ) {
Clear();
- return setErrorCode( ERR_LOADF_NARROW_FACE );
+ bndBox.SetVoid();
+ // define where is the problem, in the face or in the mesh
+ TopExp_Explorer vExp( face, TopAbs_VERTEX );
+ for ( ; vExp.More(); vExp.Next() ) {
+ gp_Pnt2d uv = BRep_Tool::Parameters( TopoDS::Vertex( vExp.Current() ), face );
+ bndBox.Add( uv );
+ }
+ bndBox.Get( minU, minV, maxU, maxV );
+ dU = maxU - minU, dV = maxV - minV;
+ if ( dU <= DBL_MIN || dV <= DBL_MIN )
+ // face problem
+ return setErrorCode( ERR_LOADF_NARROW_FACE );
+ else
+ // mesh is projected onto a line, e.g.
+ return setErrorCode( ERR_LOADF_CANT_PROJECT );
}
double ratio = dU / dV, maxratio = 3, scale;
int iCoord = 0;
gp_XY loc1 = uv11 * ( 1 - r1 ) + uv12 * r1;
gp_XY loc2 = uv21 * ( 1 - r2 ) + uv22 * r2;
resUV = 0.5 * ( loc1 + loc2 );
- isDeformed = ( loc1 - loc2 ).SquareModulus() > 1e-8;
+ //isDeformed = ( loc1 - loc2 ).SquareModulus() > 1e-8;
+ // SKL 26.07.2007 for NPAL16567
+ double d1 = (uv11-uv12).Modulus();
+ double d2 = (uv21-uv22).Modulus();
+ // double delta = d1*d2*1e-6; PAL17233
+ double delta = min( d1, d2 ) / 10.;
+ isDeformed = ( loc1 - loc2 ).SquareModulus() > delta * delta;
+
// double len1 = ( uv11 - uv12 ).Modulus();
// double len2 = ( uv21 - uv22 ).Modulus();
// resUV = loc1 * len2 / ( len1 + len2 ) + loc2 * len1 / ( len1 + len2 );
// resUV /= 2.;
// }
+ if ( isDeformed ) {
+ MESSAGE("intersectIsolines(), d1 = " << d1 << ", d2 = " << d2 << ", delta = " << delta <<
+ ", " << (loc1 - loc2).SquareModulus() << " > " << delta * delta);
+ }
return true;
}
compUVByElasticIsolines(const list< list< TPoint* > >& theBndPoints,
const list< TPoint* >& thePntToCompute)
{
+ return false; // PAL17233
//cout << "============================== KEY POINTS =============================="<<endl;
// list< int >::iterator kpIt = myKeyPointIDs.begin();
// for ( ; kpIt != myKeyPointIDs.end(); kpIt++ ) {
// " dir0: "<<bndNode2->myDir[0].X()<<" "<<bndNode2->myDir[0].Y() <<
// " dir1: "<<bndNode2->myDir[1].X()<<" "<<bndNode2->myDir[1].Y() << endl;
}
+ else {
+ /// WHAT IN THIS CASE ????????????? MAY BE THIS, I AM NOT SURE :(
+ node->SetBoundaryNode( 0, iDir, 0 );
+ node->SetBoundaryNode( 0, iDir, 1 );
+ }
}
nIt++; nPrevIt++;
if ( nNextIt != isoLine.end() ) nNextIt++;
// dir = node->myDir[ 1 - iDir ].XY() * ( isEnd ? -1. : 1. );
//cout << "__________"<<endl<< "NODE: "<<node->myInitUV.X()<<" "<<node->myInitUV.Y()<<endl;
TIsoNode* bndNode = node->GetBoundaryNode( iDir, isEnd );
+ if ( !bndNode ) {
+ MESSAGE("Why we are here?");
+ continue;
+ }
gp_XY tgt( bndNode->myDir[0].XY() + bndNode->myDir[1].XY() );
dir.SetCoord( 1, tgt.Y() * ( reversed ? 1 : -1 ));
dir.SetCoord( 2, tgt.X() * ( reversed ? -1 : 1 ));
nbComp++;
}
}
+ if ( !nbComp ) continue;
newUV /= nbComp;
node->myUV = newUV;
//cout << "NODE: "<<node->myInitUV.X()<<" "<<node->myInitUV.Y()<<endl;
// line[ iDir ].SetDirection( node->myDir[ iDir ] );
}
// define ratio
+ bool ok = true; // <- stupid fix TO AVOID PB OF NODES WITH NULL BND NODES
double locR[2] = { 0, 0 };
for ( iDir = 0; iDir < 2; iDir++ )
{
const int iCoord = 2 - iDir; // coord changing along an isoline
TIsoNode* bndNode1 = node->GetBoundaryNode( iDir, 0 );
TIsoNode* bndNode2 = node->GetBoundaryNode( iDir, 1 );
+ if ( !bndNode1 || !bndNode2 ) {
+ ok = false; break;
+ }
double par1 = bndNode1->myInitUV.Coord( iCoord );
double par2 = node->myInitUV.Coord( iCoord );
double par3 = bndNode2->myInitUV.Coord( iCoord );
//locR[0] = locR[1] = 0.25;
// intersect the 2 lines and move a node
//IntAna2d_AnaIntersection inter( line[0], line[1] );
- if ( /*inter.IsDone() && inter.NbPoints() ==*/ 1 )
+ if ( ok /*inter.IsDone() && inter.NbPoints() ==*/ )
{
// double intR = 1 - locR[0] - locR[1];
// gp_XY newUV = inter.Point(1).Value().XY();
list< TopoDS_Edge > eList;
list< int > nbVertexInWires;
- int nbWires = getOrderedEdges( face, theVertexOnKeyPoint1, eList, nbVertexInWires);
+ int nbWires = SMESH_Block::GetOrderedEdges( face, theVertexOnKeyPoint1, eList, nbVertexInWires);
if ( !theVertexOnKeyPoint1.IsSame( TopExp::FirstVertex( eList.front(), true )))
{
MESSAGE( " theVertexOnKeyPoint1 not found in the outer wire ");
}
int nbVertices = myShapeIDMap.Extent();
- //int nbSeamShapes = 0; // count twice seam edge and its vertices
for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
myShapeIDMap.Add( *elIt );
TopLoc_Location loc;
for ( iE = nbVertices + 1, elIt = eList.begin(); elIt != eList.end(); elIt++ )
{
- double f,l;
- Handle(Geom_Curve) C3d = BRep_Tool::Curve( *elIt, loc, f, l );
- const gp_Trsf & aTrsf = loc.Transformation();
+ BRepAdaptor_Curve C3d( *elIt );
list< TPoint* > & ePoints = getShapePoints( iE++ );
pIt = ePoints.begin();
for ( pIt++; pIt != ePoints.end(); pIt++ )
{
TPoint* point = *pIt;
- point->myXYZ = C3d->Value( point->myU );
- if ( !loc.IsIdentity() )
- aTrsf.Transforms( point->myXYZ.ChangeCoord() );
+ point->myXYZ = C3d.Value( point->myU );
}
}
}
//=======================================================================
-//function : Load
-//purpose : Create a pattern from the mesh built on <theBlock>
+//function : Apply
+//purpose : Compute nodes coordinates applying
+// the loaded pattern to <theFace>. The first key-point
+// will be mapped into <theNodeIndexOnKeyPoint1>-th node
//=======================================================================
-bool SMESH_Pattern::Load (SMESH_Mesh* theMesh,
- const TopoDS_Shell& theBlock)
+bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace,
+ const int theNodeIndexOnKeyPoint1,
+ const bool theReverse)
{
- MESSAGE(" ::Load(volume) " );
- Clear();
- myIs2D = false;
- SMESHDS_Mesh * aMeshDS = theMesh->GetMeshDS();
+// MESSAGE(" ::Apply(MeshFace) " );
- // load shapes in myShapeIDMap
- SMESH_Block block;
- TopoDS_Vertex v1, v2;
- if ( !block.LoadBlockShapes( theBlock, v1, v2, myShapeIDMap ))
- return setErrorCode( ERR_LOADV_BAD_SHAPE );
+ if ( !IsLoaded() ) {
+ MESSAGE( "Pattern not loaded" );
+ return setErrorCode( ERR_APPL_NOT_LOADED );
+ }
- // count nodes
- int nbNodes = 0, shapeID;
- for ( shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
- {
- const TopoDS_Shape& S = myShapeIDMap( shapeID );
- SMESHDS_SubMesh * aSubMesh = aMeshDS->MeshElements( S );
- if ( aSubMesh )
- nbNodes += aSubMesh->NbNodes();
+ // check nb of nodes
+ if (theFace->NbNodes() != myNbKeyPntInBoundary.front() ) {
+ MESSAGE( myKeyPointIDs.size() << " != " << theFace->NbNodes() );
+ return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
}
- myPoints.resize( nbNodes );
- // load U of points on edges
- TNodePointIDMap nodePointIDMap;
- int iPoint = 0;
- for ( shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
- {
- const TopoDS_Shape& S = myShapeIDMap( shapeID );
- list< TPoint* > & shapePoints = getShapePoints( shapeID );
- SMESHDS_SubMesh * aSubMesh = aMeshDS->MeshElements( S );
- if ( ! aSubMesh ) continue;
- SMDS_NodeIteratorPtr nIt = aSubMesh->GetNodes();
- if ( !nIt->more() ) continue;
+ // find points on edges, it fills myNbKeyPntInBoundary
+ if ( !findBoundaryPoints() )
+ return false;
- // store a node and a point
- while ( nIt->more() ) {
- const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nIt->next() );
- nodePointIDMap.insert( TNodePointIDMap::value_type( node, iPoint ));
- if ( block.IsVertexID( shapeID ))
- myKeyPointIDs.push_back( iPoint );
- TPoint* p = & myPoints[ iPoint++ ];
- shapePoints.push_back( p );
- p->myXYZ.SetCoord( node->X(), node->Y(), node->Z() );
- p->myInitXYZ.SetCoord( 0,0,0 );
+ // check that there are no holes in a pattern
+ if (myNbKeyPntInBoundary.size() > 1 ) {
+ return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
+ }
+
+ // Define the nodes order
+
+ list< const SMDS_MeshNode* > nodes;
+ list< const SMDS_MeshNode* >::iterator n = nodes.end();
+ SMDS_ElemIteratorPtr noIt = theFace->nodesIterator();
+ int iSub = 0;
+ while ( noIt->more() ) {
+ const SMDS_MeshNode* node = smdsNode( noIt->next() );
+ nodes.push_back( node );
+ if ( iSub++ == theNodeIndexOnKeyPoint1 )
+ n = --nodes.end();
+ }
+ if ( n != nodes.end() ) {
+ if ( theReverse ) {
+ if ( n != --nodes.end() )
+ nodes.splice( nodes.begin(), nodes, ++n, nodes.end() );
+ nodes.reverse();
}
- list< TPoint* >::iterator pIt = shapePoints.begin();
+ else if ( n != nodes.begin() )
+ nodes.splice( nodes.end(), nodes, nodes.begin(), n );
+ }
+ list< gp_XYZ > xyzList;
+ myOrderedNodes.resize( theFace->NbNodes() );
+ for ( iSub = 0, n = nodes.begin(); n != nodes.end(); ++n ) {
+ xyzList.push_back( gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() ));
+ myOrderedNodes[ iSub++] = *n;
+ }
- // compute init XYZ
- switch ( S.ShapeType() )
+ // Define a face plane
+
+ list< gp_XYZ >::iterator xyzIt = xyzList.begin();
+ gp_Pnt P ( *xyzIt++ );
+ gp_Vec Vx( P, *xyzIt++ ), N;
+ do {
+ N = Vx ^ gp_Vec( P, *xyzIt++ );
+ } while ( N.SquareMagnitude() <= DBL_MIN && xyzIt != xyzList.end() );
+ if ( N.SquareMagnitude() <= DBL_MIN )
+ return setErrorCode( ERR_APPLF_BAD_FACE_GEOM );
+ gp_Ax2 pos( P, N, Vx );
+
+ // Compute UV of key-points on a plane
+ for ( xyzIt = xyzList.begin(), iSub = 1; xyzIt != xyzList.end(); xyzIt++, iSub++ )
+ {
+ gp_Vec vec ( pos.Location(), *xyzIt );
+ TPoint* p = getShapePoints( iSub ).front();
+ p->myUV.SetX( vec * pos.XDirection() );
+ p->myUV.SetY( vec * pos.YDirection() );
+ p->myXYZ = *xyzIt;
+ }
+
+ // points on edges to be used for UV computation of in-face points
+ list< list< TPoint* > > edgesPointsList;
+ edgesPointsList.push_back( list< TPoint* >() );
+ list< TPoint* > * edgesPoints = & edgesPointsList.back();
+ list< TPoint* >::iterator pIt;
+
+ // compute UV and XYZ of points on edges
+
+ for ( xyzIt = xyzList.begin(); xyzIt != xyzList.end(); iSub++ )
+ {
+ gp_XYZ& xyz1 = *xyzIt++;
+ gp_XYZ& xyz2 = ( xyzIt != xyzList.end() ) ? *xyzIt : xyzList.front();
+
+ list< TPoint* > & ePoints = getShapePoints( iSub );
+ ePoints.back()->myInitU = 1.0;
+ list< TPoint* >::const_iterator pIt = ++ePoints.begin();
+ while ( *pIt != ePoints.back() )
{
- case TopAbs_VERTEX:
- case TopAbs_EDGE: {
+ TPoint* p = *pIt++;
+ p->myXYZ = xyz1 * ( 1 - p->myInitU ) + xyz2 * p->myInitU;
+ gp_Vec vec ( pos.Location(), p->myXYZ );
+ p->myUV.SetX( vec * pos.XDirection() );
+ p->myUV.SetY( vec * pos.YDirection() );
+ }
+ // collect on-edge points (excluding the last one)
+ edgesPoints->insert( edgesPoints->end(), ePoints.begin(), --ePoints.end());
+ }
- for ( ; pIt != shapePoints.end(); pIt++ ) {
- double * coef = block.GetShapeCoef( shapeID );
- for ( int iCoord = 1; iCoord <= 3; iCoord++ )
- if ( coef[ iCoord - 1] > 0 )
- (*pIt)->myInitXYZ.SetCoord( iCoord, 1. );
- }
- if ( S.ShapeType() == TopAbs_VERTEX )
- break;
+ // Compute UV and XYZ of in-face points
- const TopoDS_Edge& edge = TopoDS::Edge( S );
- double f,l;
- BRep_Tool::Range( edge, f, l );
- int iCoord = SMESH_Block::GetCoordIndOnEdge( shapeID );
- bool isForward = SMESH_Block::IsForwardEdge( edge, myShapeIDMap );
- pIt = shapePoints.begin();
- nIt = aSubMesh->GetNodes();
- for ( ; nIt->more(); pIt++ )
- {
- const SMDS_MeshNode* node =
- static_cast<const SMDS_MeshNode*>( nIt->next() );
- const SMDS_EdgePosition* epos =
- static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
- double u = ( epos->GetUParameter() - f ) / ( l - f );
- (*pIt)->myInitXYZ.SetCoord( iCoord, isForward ? u : 1 - u );
- }
- break;
+ // try to use a simple algo to compute UV
+ list< TPoint* > & fPoints = getShapePoints( iSub );
+ bool isDeformed = false;
+ for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ )
+ if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
+ (*pIt)->myUV, isDeformed )) {
+ MESSAGE("cant Apply(face)");
+ return false;
}
- default:
- for ( ; pIt != shapePoints.end(); pIt++ )
- {
- if ( !block.ComputeParameters( (*pIt)->myXYZ, (*pIt)->myInitXYZ, shapeID )) {
- MESSAGE( "!block.ComputeParameters()" );
- return setErrorCode( ERR_LOADV_COMPUTE_PARAMS );
- }
+ // try to use a complex algo if it is a difficult case
+ if ( isDeformed && !compUVByElasticIsolines( edgesPointsList, fPoints ))
+ {
+ for ( ; pIt != fPoints.end(); pIt++ ) // continue with the simple algo
+ if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
+ (*pIt)->myUV, isDeformed )) {
+ MESSAGE("cant Apply(face)");
+ return false;
}
- }
- } // loop on block sub-shapes
-
- // load elements
+ }
- SMESHDS_SubMesh * aSubMesh = aMeshDS->MeshElements( theBlock );
- if ( aSubMesh )
+ for ( pIt = fPoints.begin(); pIt != fPoints.end(); pIt++ )
{
- SMDS_ElemIteratorPtr elemIt = aSubMesh->GetElements();
- while ( elemIt->more() ) {
- SMDS_ElemIteratorPtr nIt = elemIt->next()->nodesIterator();
- myElemPointIDs.push_back( list< int >() );
- list< int >& elemPoints = myElemPointIDs.back();
- while ( nIt->more() )
- elemPoints.push_back( nodePointIDMap[ nIt->next() ]);
- }
+ (*pIt)->myXYZ = ElSLib::PlaneValue( (*pIt)->myUV.X(), (*pIt)->myUV.Y(), pos );
}
- myIsBoundaryPointsFound = true;
+ myIsComputed = true;
return setErrorCode( ERR_OK );
}
//=======================================================================
//function : Apply
//purpose : Compute nodes coordinates applying
-// the loaded pattern to <theBlock>. The (0,0,0) key-point
-// will be mapped into <theVertex000>. The (0,0,1)
-// fifth key-point will be mapped into <theVertex001>.
+// the loaded pattern to <theFace>. The first key-point
+// will be mapped into <theNodeIndexOnKeyPoint1>-th node
//=======================================================================
-bool SMESH_Pattern::Apply (const TopoDS_Shell& theBlock,
- const TopoDS_Vertex& theVertex000,
- const TopoDS_Vertex& theVertex001)
+bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
+ const SMDS_MeshFace* theFace,
+ const TopoDS_Shape& theSurface,
+ const int theNodeIndexOnKeyPoint1,
+ const bool theReverse)
{
- MESSAGE(" ::Apply(volume) " );
-
- if (!findBoundaryPoints() || // bind ID to points
- !setShapeToMesh( theBlock )) // check theBlock is a suitable shape
- return false;
+// MESSAGE(" ::Apply(MeshFace) " );
+ if ( theSurface.IsNull() || theSurface.ShapeType() != TopAbs_FACE ) {
+ return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse);
+ }
+ const TopoDS_Face& face = TopoDS::Face( theSurface );
+ TopLoc_Location loc;
+ Handle(Geom_Surface) surface = BRep_Tool::Surface( face, loc );
+ const gp_Trsf & aTrsf = loc.Transformation();
- SMESH_Block block; // bind ID to shape
- if (!block.LoadBlockShapes( theBlock, theVertex000, theVertex001, myShapeIDMap ))
- return setErrorCode( ERR_APPLV_BAD_SHAPE );
+ if ( !IsLoaded() ) {
+ MESSAGE( "Pattern not loaded" );
+ return setErrorCode( ERR_APPL_NOT_LOADED );
+ }
+ // check nb of nodes
+ if (theFace->NbNodes() != myNbKeyPntInBoundary.front() ) {
+ MESSAGE( myKeyPointIDs.size() << " != " << theFace->NbNodes() );
+ return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
+ }
+
+ // find points on edges, it fills myNbKeyPntInBoundary
+ if ( !findBoundaryPoints() )
+ return false;
+
+ // check that there are no holes in a pattern
+ if (myNbKeyPntInBoundary.size() > 1 ) {
+ return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
+ }
+
+ // Define the nodes order
+
+ list< const SMDS_MeshNode* > nodes;
+ list< const SMDS_MeshNode* >::iterator n = nodes.end();
+ SMDS_ElemIteratorPtr noIt = theFace->nodesIterator();
+ int iSub = 0;
+ while ( noIt->more() ) {
+ const SMDS_MeshNode* node = smdsNode( noIt->next() );
+ nodes.push_back( node );
+ if ( iSub++ == theNodeIndexOnKeyPoint1 )
+ n = --nodes.end();
+ }
+ if ( n != nodes.end() ) {
+ if ( theReverse ) {
+ if ( n != --nodes.end() )
+ nodes.splice( nodes.begin(), nodes, ++n, nodes.end() );
+ nodes.reverse();
+ }
+ else if ( n != nodes.begin() )
+ nodes.splice( nodes.end(), nodes, nodes.begin(), n );
+ }
+
+ // find a node not on a seam edge, if necessary
+ SMESH_MesherHelper helper( *theMesh );
+ helper.SetSubShape( theSurface );
+ const SMDS_MeshNode* inFaceNode = 0;
+ if ( helper.GetNodeUVneedInFaceNode() )
+ {
+ SMESH_MeshEditor editor( theMesh );
+ for ( n = nodes.begin(); ( !inFaceNode && n != nodes.end()); ++n ) {
+ int shapeID = editor.FindShape( *n );
+ if ( !shapeID )
+ return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse);
+ if ( !helper.IsSeamShape( shapeID ))
+ inFaceNode = *n;
+ }
+ }
+
+ // Set UV of key-points (i.e. of nodes of theFace )
+ vector< gp_XY > keyUV( theFace->NbNodes() );
+ myOrderedNodes.resize( theFace->NbNodes() );
+ for ( iSub = 1, n = nodes.begin(); n != nodes.end(); ++n, ++iSub )
+ {
+ TPoint* p = getShapePoints( iSub ).front();
+ p->myUV = helper.GetNodeUV( face, *n, inFaceNode );
+ p->myXYZ = gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() );
+
+ keyUV[ iSub-1 ] = p->myUV;
+ myOrderedNodes[ iSub-1 ] = *n;
+ }
+
+ // points on edges to be used for UV computation of in-face points
+ list< list< TPoint* > > edgesPointsList;
+ edgesPointsList.push_back( list< TPoint* >() );
+ list< TPoint* > * edgesPoints = & edgesPointsList.back();
+ list< TPoint* >::iterator pIt;
+
+ // compute UV and XYZ of points on edges
+
+ for ( int i = 0; i < myOrderedNodes.size(); ++i, ++iSub )
+ {
+ gp_XY& uv1 = keyUV[ i ];
+ gp_XY& uv2 = ( i+1 < keyUV.size() ) ? keyUV[ i+1 ] : keyUV[ 0 ];
+
+ list< TPoint* > & ePoints = getShapePoints( iSub );
+ ePoints.back()->myInitU = 1.0;
+ list< TPoint* >::const_iterator pIt = ++ePoints.begin();
+ while ( *pIt != ePoints.back() )
+ {
+ TPoint* p = *pIt++;
+ p->myUV = uv1 * ( 1 - p->myInitU ) + uv2 * p->myInitU;
+ p->myXYZ = surface->Value( p->myUV.X(), p->myUV.Y() );
+ if ( !loc.IsIdentity() )
+ aTrsf.Transforms( p->myXYZ.ChangeCoord() );
+ }
+ // collect on-edge points (excluding the last one)
+ edgesPoints->insert( edgesPoints->end(), ePoints.begin(), --ePoints.end());
+ }
+
+ // Compute UV and XYZ of in-face points
+
+ // try to use a simple algo to compute UV
+ list< TPoint* > & fPoints = getShapePoints( iSub );
+ bool isDeformed = false;
+ for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ )
+ if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
+ (*pIt)->myUV, isDeformed )) {
+ MESSAGE("cant Apply(face)");
+ return false;
+ }
+ // try to use a complex algo if it is a difficult case
+ if ( isDeformed && !compUVByElasticIsolines( edgesPointsList, fPoints ))
+ {
+ for ( ; pIt != fPoints.end(); pIt++ ) // continue with the simple algo
+ if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
+ (*pIt)->myUV, isDeformed )) {
+ MESSAGE("cant Apply(face)");
+ return false;
+ }
+ }
+
+ for ( pIt = fPoints.begin(); pIt != fPoints.end(); pIt++ )
+ {
+ TPoint * point = *pIt;
+ point->myXYZ = surface->Value( point->myUV.X(), point->myUV.Y() );
+ if ( !loc.IsIdentity() )
+ aTrsf.Transforms( point->myXYZ.ChangeCoord() );
+ }
+
+ myIsComputed = true;
+
+ return setErrorCode( ERR_OK );
+}
+
+//=======================================================================
+//function : undefinedXYZ
+//purpose :
+//=======================================================================
+
+static const gp_XYZ& undefinedXYZ()
+{
+ static gp_XYZ xyz( 1.e100, 0., 0. );
+ return xyz;
+}
+
+//=======================================================================
+//function : isDefined
+//purpose :
+//=======================================================================
+
+inline static bool isDefined(const gp_XYZ& theXYZ)
+{
+ return theXYZ.X() < 1.e100;
+}
+
+//=======================================================================
+//function : Apply
+//purpose : Compute nodes coordinates applying
+// the loaded pattern to <theFaces>. The first key-point
+// will be mapped into <theNodeIndexOnKeyPoint1>-th node
+//=======================================================================
+
+bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
+ std::set<const SMDS_MeshFace*>& theFaces,
+ const int theNodeIndexOnKeyPoint1,
+ const bool theReverse)
+{
+ MESSAGE(" ::Apply(set<MeshFace>) " );
+
+ if ( !IsLoaded() ) {
+ MESSAGE( "Pattern not loaded" );
+ return setErrorCode( ERR_APPL_NOT_LOADED );
+ }
+
+ // find points on edges, it fills myNbKeyPntInBoundary
+ if ( !findBoundaryPoints() )
+ return false;
+
+ // check that there are no holes in a pattern
+ if (myNbKeyPntInBoundary.size() > 1 ) {
+ return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
+ }
+
+ myShape.Nullify();
+ myXYZ.clear();
+ myElemXYZIDs.clear();
+ myXYZIdToNodeMap.clear();
+ myElements.clear();
+ myIdsOnBoundary.clear();
+ myReverseConnectivity.clear();
+
+ myXYZ.resize( myPoints.size() * theFaces.size(), undefinedXYZ() );
+ myElements.reserve( theFaces.size() );
+
+ // to find point index
+ map< TPoint*, int > pointIndex;
+ for ( int i = 0; i < myPoints.size(); i++ )
+ pointIndex.insert( make_pair( & myPoints[ i ], i ));
+
+ int ind1 = 0; // lowest point index for a face
+
+ // meshed geometry
+ TopoDS_Shape shape;
+// int shapeID = 0;
+// SMESH_MeshEditor editor( theMesh );
+
+ // apply to each face in theFaces set
+ set<const SMDS_MeshFace*>::iterator face = theFaces.begin();
+ for ( ; face != theFaces.end(); ++face )
+ {
+// int curShapeId = editor.FindShape( *face );
+// if ( curShapeId != shapeID ) {
+// if ( curShapeId )
+// shape = theMesh->GetMeshDS()->IndexToShape( curShapeId );
+// else
+// shape.Nullify();
+// shapeID = curShapeId;
+// }
+ bool ok;
+ if ( shape.IsNull() )
+ ok = Apply( *face, theNodeIndexOnKeyPoint1, theReverse );
+ else
+ ok = Apply( theMesh, *face, shape, theNodeIndexOnKeyPoint1, theReverse );
+ if ( !ok ) {
+ MESSAGE( "Failed on " << *face );
+ continue;
+ }
+ myElements.push_back( *face );
+
+ // store computed points belonging to elements
+ list< TElemDef >::iterator ll = myElemPointIDs.begin();
+ for ( ; ll != myElemPointIDs.end(); ++ll )
+ {
+ myElemXYZIDs.push_back(TElemDef());
+ TElemDef& xyzIds = myElemXYZIDs.back();
+ TElemDef& pIds = *ll;
+ for ( TElemDef::iterator id = pIds.begin(); id != pIds.end(); id++ ) {
+ int pIndex = *id + ind1;
+ xyzIds.push_back( pIndex );
+ myXYZ[ pIndex ] = myPoints[ *id ].myXYZ.XYZ();
+ myReverseConnectivity[ pIndex ].push_back( & xyzIds );
+ }
+ }
+ // put points on links to myIdsOnBoundary,
+ // they will be used to sew new elements on adjacent refined elements
+ int nbNodes = (*face)->NbNodes(), eID = nbNodes + 1;
+ for ( int i = 0; i < nbNodes; i++ )
+ {
+ list< TPoint* > & linkPoints = getShapePoints( eID++ );
+ const SMDS_MeshNode* n1 = myOrderedNodes[ i ];
+ const SMDS_MeshNode* n2 = myOrderedNodes[ i + 1 == nbNodes ? 0 : i + 1 ];
+ // make a link and a node set
+ TNodeSet linkSet, node1Set;
+ linkSet.insert( n1 );
+ linkSet.insert( n2 );
+ node1Set.insert( n1 );
+ list< TPoint* >::iterator p = linkPoints.begin();
+ {
+ // map the first link point to n1
+ int nId = pointIndex[ *p ] + ind1;
+ myXYZIdToNodeMap[ nId ] = n1;
+ list< list< int > >& groups = myIdsOnBoundary[ node1Set ];
+ groups.push_back(list< int > ());
+ groups.back().push_back( nId );
+ }
+ // add the linkSet to the map
+ list< list< int > >& groups = myIdsOnBoundary[ linkSet ];
+ groups.push_back(list< int > ());
+ list< int >& indList = groups.back();
+ // add points to the map excluding the end points
+ for ( p++; *p != linkPoints.back(); p++ )
+ indList.push_back( pointIndex[ *p ] + ind1 );
+ }
+ ind1 += myPoints.size();
+ }
+
+ return !myElemXYZIDs.empty();
+}
+
+//=======================================================================
+//function : Apply
+//purpose : Compute nodes coordinates applying
+// the loaded pattern to <theVolumes>. The (0,0,0) key-point
+// will be mapped into <theNode000Index>-th node. The
+// (0,0,1) key-point will be mapped into <theNode000Index>-th
+// node.
+//=======================================================================
+
+bool SMESH_Pattern::Apply (std::set<const SMDS_MeshVolume*> & theVolumes,
+ const int theNode000Index,
+ const int theNode001Index)
+{
+ MESSAGE(" ::Apply(set<MeshVolumes>) " );
+
+ if ( !IsLoaded() ) {
+ MESSAGE( "Pattern not loaded" );
+ return setErrorCode( ERR_APPL_NOT_LOADED );
+ }
+
+ // bind ID to points
+ if ( !findBoundaryPoints() )
+ return false;
+
+ // check that there are no holes in a pattern
+ if (myNbKeyPntInBoundary.size() > 1 ) {
+ return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
+ }
+
+ myShape.Nullify();
+ myXYZ.clear();
+ myElemXYZIDs.clear();
+ myXYZIdToNodeMap.clear();
+ myElements.clear();
+ myIdsOnBoundary.clear();
+ myReverseConnectivity.clear();
+
+ myXYZ.resize( myPoints.size() * theVolumes.size(), undefinedXYZ() );
+ myElements.reserve( theVolumes.size() );
+
+ // to find point index
+ map< TPoint*, int > pointIndex;
+ for ( int i = 0; i < myPoints.size(); i++ )
+ pointIndex.insert( make_pair( & myPoints[ i ], i ));
+
+ int ind1 = 0; // lowest point index for an element
+
+ // apply to each element in theVolumes set
+ set<const SMDS_MeshVolume*>::iterator vol = theVolumes.begin();
+ for ( ; vol != theVolumes.end(); ++vol )
+ {
+ if ( !Apply( *vol, theNode000Index, theNode001Index )) {
+ MESSAGE( "Failed on " << *vol );
+ continue;
+ }
+ myElements.push_back( *vol );
+
+ // store computed points belonging to elements
+ list< TElemDef >::iterator ll = myElemPointIDs.begin();
+ for ( ; ll != myElemPointIDs.end(); ++ll )
+ {
+ myElemXYZIDs.push_back(TElemDef());
+ TElemDef& xyzIds = myElemXYZIDs.back();
+ TElemDef& pIds = *ll;
+ for ( TElemDef::iterator id = pIds.begin(); id != pIds.end(); id++ ) {
+ int pIndex = *id + ind1;
+ xyzIds.push_back( pIndex );
+ myXYZ[ pIndex ] = myPoints[ *id ].myXYZ.XYZ();
+ myReverseConnectivity[ pIndex ].push_back( & xyzIds );
+ }
+ }
+ // put points on edges and faces to myIdsOnBoundary,
+ // they will be used to sew new elements on adjacent refined elements
+ for ( int Id = SMESH_Block::ID_V000; Id <= SMESH_Block::ID_F1yz; Id++ )
+ {
+ // make a set of sub-points
+ TNodeSet subNodes;
+ vector< int > subIDs;
+ if ( SMESH_Block::IsVertexID( Id )) {
+ subNodes.insert( myOrderedNodes[ Id - 1 ]);
+ }
+ else if ( SMESH_Block::IsEdgeID( Id )) {
+ SMESH_Block::GetEdgeVertexIDs( Id, subIDs );
+ subNodes.insert( myOrderedNodes[ subIDs.front() - 1 ]);
+ subNodes.insert( myOrderedNodes[ subIDs.back() - 1 ]);
+ }
+ else {
+ SMESH_Block::GetFaceEdgesIDs( Id, subIDs );
+ int e1 = subIDs[ 0 ], e2 = subIDs[ 1 ];
+ SMESH_Block::GetEdgeVertexIDs( e1, subIDs );
+ subNodes.insert( myOrderedNodes[ subIDs.front() - 1 ]);
+ subNodes.insert( myOrderedNodes[ subIDs.back() - 1 ]);
+ SMESH_Block::GetEdgeVertexIDs( e2, subIDs );
+ subNodes.insert( myOrderedNodes[ subIDs.front() - 1 ]);
+ subNodes.insert( myOrderedNodes[ subIDs.back() - 1 ]);
+ }
+ // add points
+ list< TPoint* > & points = getShapePoints( Id );
+ list< TPoint* >::iterator p = points.begin();
+ list< list< int > >& groups = myIdsOnBoundary[ subNodes ];
+ groups.push_back(list< int > ());
+ list< int >& indList = groups.back();
+ for ( ; p != points.end(); p++ )
+ indList.push_back( pointIndex[ *p ] + ind1 );
+ if ( subNodes.size() == 1 ) // vertex case
+ myXYZIdToNodeMap[ indList.back() ] = myOrderedNodes[ Id - 1 ];
+ }
+ ind1 += myPoints.size();
+ }
+
+ return !myElemXYZIDs.empty();
+}
+
+//=======================================================================
+//function : Load
+//purpose : Create a pattern from the mesh built on <theBlock>
+//=======================================================================
+
+bool SMESH_Pattern::Load (SMESH_Mesh* theMesh,
+ const TopoDS_Shell& theBlock)
+{
+ MESSAGE(" ::Load(volume) " );
+ Clear();
+ myIs2D = false;
+ SMESHDS_SubMesh * aSubMesh;
+
+ // load shapes in myShapeIDMap
+ SMESH_Block block;
+ TopoDS_Vertex v1, v2;
+ if ( !block.LoadBlockShapes( theBlock, v1, v2, myShapeIDMap ))
+ return setErrorCode( ERR_LOADV_BAD_SHAPE );
+
+ // count nodes
+ int nbNodes = 0, shapeID;
+ for ( shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
+ {
+ const TopoDS_Shape& S = myShapeIDMap( shapeID );
+ aSubMesh = getSubmeshWithElements( theMesh, S );
+ if ( aSubMesh )
+ nbNodes += aSubMesh->NbNodes();
+ }
+ myPoints.resize( nbNodes );
+
+ // load U of points on edges
+ TNodePointIDMap nodePointIDMap;
+ int iPoint = 0;
+ for ( shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
+ {
+ const TopoDS_Shape& S = myShapeIDMap( shapeID );
+ list< TPoint* > & shapePoints = getShapePoints( shapeID );
+ aSubMesh = getSubmeshWithElements( theMesh, S );
+ if ( ! aSubMesh ) continue;
+ SMDS_NodeIteratorPtr nIt = aSubMesh->GetNodes();
+ if ( !nIt->more() ) continue;
+
+ // store a node and a point
+ while ( nIt->more() ) {
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
+ nodePointIDMap.insert( make_pair( node, iPoint ));
+ if ( block.IsVertexID( shapeID ))
+ myKeyPointIDs.push_back( iPoint );
+ TPoint* p = & myPoints[ iPoint++ ];
+ shapePoints.push_back( p );
+ p->myXYZ.SetCoord( node->X(), node->Y(), node->Z() );
+ p->myInitXYZ.SetCoord( 0,0,0 );
+ }
+ list< TPoint* >::iterator pIt = shapePoints.begin();
+
+ // compute init XYZ
+ switch ( S.ShapeType() )
+ {
+ case TopAbs_VERTEX:
+ case TopAbs_EDGE: {
+
+ for ( ; pIt != shapePoints.end(); pIt++ ) {
+ double * coef = block.GetShapeCoef( shapeID );
+ for ( int iCoord = 1; iCoord <= 3; iCoord++ )
+ if ( coef[ iCoord - 1] > 0 )
+ (*pIt)->myInitXYZ.SetCoord( iCoord, 1. );
+ }
+ if ( S.ShapeType() == TopAbs_VERTEX )
+ break;
+
+ const TopoDS_Edge& edge = TopoDS::Edge( S );
+ double f,l;
+ BRep_Tool::Range( edge, f, l );
+ int iCoord = SMESH_Block::GetCoordIndOnEdge( shapeID );
+ bool isForward = SMESH_Block::IsForwardEdge( edge, myShapeIDMap );
+ pIt = shapePoints.begin();
+ nIt = aSubMesh->GetNodes();
+ for ( ; nIt->more(); pIt++ )
+ {
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
+ const SMDS_EdgePosition* epos =
+ static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+ double u = ( epos->GetUParameter() - f ) / ( l - f );
+ (*pIt)->myInitXYZ.SetCoord( iCoord, isForward ? u : 1 - u );
+ }
+ break;
+ }
+ default:
+ for ( ; pIt != shapePoints.end(); pIt++ )
+ {
+ if ( !block.ComputeParameters( (*pIt)->myXYZ, (*pIt)->myInitXYZ, shapeID )) {
+ MESSAGE( "!block.ComputeParameters()" );
+ return setErrorCode( ERR_LOADV_COMPUTE_PARAMS );
+ }
+ }
+ }
+ } // loop on block sub-shapes
+
+ // load elements
+
+ aSubMesh = getSubmeshWithElements( theMesh, theBlock );
+ if ( aSubMesh )
+ {
+ SMDS_ElemIteratorPtr elemIt = aSubMesh->GetElements();
+ while ( elemIt->more() ) {
+ SMDS_ElemIteratorPtr nIt = elemIt->next()->nodesIterator();
+ myElemPointIDs.push_back( TElemDef() );
+ TElemDef& elemPoints = myElemPointIDs.back();
+ while ( nIt->more() )
+ elemPoints.push_back( nodePointIDMap[ nIt->next() ]);
+ }
+ }
+
+ myIsBoundaryPointsFound = true;
+
+ return setErrorCode( ERR_OK );
+}
+
+//=======================================================================
+//function : getSubmeshWithElements
+//purpose : return submesh containing elements bound to theBlock in theMesh
+//=======================================================================
+
+SMESHDS_SubMesh * SMESH_Pattern::getSubmeshWithElements(SMESH_Mesh* theMesh,
+ const TopoDS_Shape& theShape)
+{
+ SMESHDS_SubMesh * aSubMesh = theMesh->GetMeshDS()->MeshElements( theShape );
+ if ( aSubMesh && ( aSubMesh->GetElements()->more() || aSubMesh->GetNodes()->more() ))
+ return aSubMesh;
+
+ if ( theShape.ShapeType() == TopAbs_SHELL )
+ {
+ // look for submesh of VOLUME
+ TopTools_ListIteratorOfListOfShape it( theMesh->GetAncestors( theShape ));
+ for (; it.More(); it.Next()) {
+ aSubMesh = theMesh->GetMeshDS()->MeshElements( it.Value() );
+ if ( aSubMesh && ( aSubMesh->GetElements()->more() || aSubMesh->GetNodes()->more() ))
+ return aSubMesh;
+ }
+ }
+ return 0;
+}
+
+
+//=======================================================================
+//function : Apply
+//purpose : Compute nodes coordinates applying
+// the loaded pattern to <theBlock>. The (0,0,0) key-point
+// will be mapped into <theVertex000>. The (0,0,1)
+// fifth key-point will be mapped into <theVertex001>.
+//=======================================================================
+
+bool SMESH_Pattern::Apply (const TopoDS_Shell& theBlock,
+ const TopoDS_Vertex& theVertex000,
+ const TopoDS_Vertex& theVertex001)
+{
+ MESSAGE(" ::Apply(volume) " );
+
+ if (!findBoundaryPoints() || // bind ID to points
+ !setShapeToMesh( theBlock )) // check theBlock is a suitable shape
+ return false;
+
+ SMESH_Block block; // bind ID to shape
+ if (!block.LoadBlockShapes( theBlock, theVertex000, theVertex001, myShapeIDMap ))
+ return setErrorCode( ERR_APPLV_BAD_SHAPE );
+
+ // compute XYZ of points on shapes
+
+ for ( int shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
+ {
+ list< TPoint* > & shapePoints = getShapePoints( shapeID );
+ list< TPoint* >::iterator pIt = shapePoints.begin();
+ const TopoDS_Shape& S = myShapeIDMap( shapeID );
+ switch ( S.ShapeType() )
+ {
+ case TopAbs_VERTEX: {
+
+ for ( ; pIt != shapePoints.end(); pIt++ )
+ block.VertexPoint( shapeID, (*pIt)->myXYZ.ChangeCoord() );
+ break;
+ }
+ case TopAbs_EDGE: {
+
+ for ( ; pIt != shapePoints.end(); pIt++ )
+ block.EdgePoint( shapeID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
+ break;
+ }
+ case TopAbs_FACE: {
+
+ for ( ; pIt != shapePoints.end(); pIt++ )
+ block.FacePoint( shapeID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
+ break;
+ }
+ default:
+ for ( ; pIt != shapePoints.end(); pIt++ )
+ block.ShellPoint( (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
+ }
+ } // loop on block sub-shapes
+
+ myIsComputed = true;
+
+ return setErrorCode( ERR_OK );
+}
+
+//=======================================================================
+//function : Apply
+//purpose : Compute nodes coordinates applying
+// the loaded pattern to <theVolume>. The (0,0,0) key-point
+// will be mapped into <theNode000Index>-th node. The
+// (0,0,1) key-point will be mapped into <theNode000Index>-th
+// node.
+//=======================================================================
+
+bool SMESH_Pattern::Apply (const SMDS_MeshVolume* theVolume,
+ const int theNode000Index,
+ const int theNode001Index)
+{
+ //MESSAGE(" ::Apply(MeshVolume) " );
+
+ if (!findBoundaryPoints()) // bind ID to points
+ return false;
+
+ SMESH_Block block; // bind ID to shape
+ if (!block.LoadMeshBlock( theVolume, theNode000Index, theNode001Index, myOrderedNodes ))
+ return setErrorCode( ERR_APPLV_BAD_SHAPE );
// compute XYZ of points on shapes
- for ( int shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
+ for ( int ID = SMESH_Block::ID_V000; ID <= SMESH_Block::ID_Shell; ID++ )
+ {
+ list< TPoint* > & shapePoints = getShapePoints( ID );
+ list< TPoint* >::iterator pIt = shapePoints.begin();
+
+ if ( block.IsVertexID( ID ))
+ for ( ; pIt != shapePoints.end(); pIt++ ) {
+ block.VertexPoint( ID, (*pIt)->myXYZ.ChangeCoord() );
+ }
+ else if ( block.IsEdgeID( ID ))
+ for ( ; pIt != shapePoints.end(); pIt++ ) {
+ block.EdgePoint( ID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
+ }
+ else if ( block.IsFaceID( ID ))
+ for ( ; pIt != shapePoints.end(); pIt++ ) {
+ block.FacePoint( ID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
+ }
+ else
+ for ( ; pIt != shapePoints.end(); pIt++ )
+ block.ShellPoint( (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
+ } // loop on block sub-shapes
+
+ myIsComputed = true;
+
+ return setErrorCode( ERR_OK );
+}
+
+//=======================================================================
+//function : mergePoints
+//purpose : Merge XYZ on edges and/or faces.
+//=======================================================================
+
+void SMESH_Pattern::mergePoints (const bool uniteGroups)
+{
+ map< TNodeSet, list< list< int > > >::iterator idListIt = myIdsOnBoundary.begin();
+ for ( ; idListIt != myIdsOnBoundary.end(); idListIt++ )
{
- list< TPoint* > & shapePoints = getShapePoints( shapeID );
- list< TPoint* >::iterator pIt = shapePoints.begin();
- const TopoDS_Shape& S = myShapeIDMap( shapeID );
- switch ( S.ShapeType() )
+ list<list< int > >& groups = idListIt->second;
+ if ( groups.size() < 2 )
+ continue;
+
+ // find tolerance
+ const TNodeSet& nodes = idListIt->first;
+ double tol2 = 1.e-10;
+ if ( nodes.size() > 1 ) {
+ Bnd_Box box;
+ TNodeSet::const_iterator n = nodes.begin();
+ for ( ; n != nodes.end(); ++n )
+ box.Add( gp_Pnt( (*n)->X(), (*n)->Y(), (*n)->Z() ));
+ double x, y, z, X, Y, Z;
+ box.Get( x, y, z, X, Y, Z );
+ gp_Pnt p( x, y, z ), P( X, Y, Z );
+ tol2 = 1.e-4 * p.SquareDistance( P );
+ }
+
+ // to unite groups on link
+ bool unite = ( uniteGroups && nodes.size() == 2 );
+ map< double, int > distIndMap;
+ const SMDS_MeshNode* node = *nodes.begin();
+ gp_Pnt P( node->X(), node->Y(), node->Z() );
+
+ // compare points, replace indices
+
+ list< int >::iterator ind1, ind2;
+ list< list< int > >::iterator grpIt1, grpIt2;
+ for ( grpIt1 = groups.begin(); grpIt1 != groups.end(); grpIt1++ )
{
- case TopAbs_VERTEX: {
+ list< int >& indices1 = *grpIt1;
+ grpIt2 = grpIt1;
+ for ( grpIt2++; grpIt2 != groups.end(); grpIt2++ )
+ {
+ list< int >& indices2 = *grpIt2;
+ for ( ind1 = indices1.begin(); ind1 != indices1.end(); ind1++ )
+ {
+ gp_XYZ& p1 = myXYZ[ *ind1 ];
+ ind2 = indices2.begin();
+ while ( ind2 != indices2.end() )
+ {
+ gp_XYZ& p2 = myXYZ[ *ind2 ];
+ //MESSAGE("COMP: " << *ind1 << " " << *ind2 << " X: " << p2.X() << " tol2: " << tol2);
+ if ( ( p1 - p2 ).SquareModulus() <= tol2 )
+ {
+ ASSERT( myReverseConnectivity.find( *ind2 ) != myReverseConnectivity.end() );
+ list< TElemDef* > & elemXYZIDsList = myReverseConnectivity[ *ind2 ];
+ list< TElemDef* >::iterator elemXYZIDs = elemXYZIDsList.begin();
+ for ( ; elemXYZIDs != elemXYZIDsList.end(); elemXYZIDs++ )
+ {
+ //MESSAGE( " Replace " << *ind2 << " with " << *ind1 );
+ myXYZ[ *ind2 ] = undefinedXYZ();
+ replace( (*elemXYZIDs)->begin(), (*elemXYZIDs)->end(), *ind2, *ind1 );
+ }
+ ind2 = indices2.erase( ind2 );
+ }
+ else
+ ind2++;
+ }
+ }
+ }
+ if ( unite ) { // sort indices using distIndMap
+ for ( ind1 = indices1.begin(); ind1 != indices1.end(); ind1++ )
+ {
+ ASSERT( isDefined( myXYZ[ *ind1 ] ));
+ double dist = P.SquareDistance( myXYZ[ *ind1 ]);
+ distIndMap.insert( make_pair( dist, *ind1 ));
+ }
+ }
+ }
+ if ( unite ) { // put all sorted indices into the first group
+ list< int >& g = groups.front();
+ g.clear();
+ map< double, int >::iterator dist_ind = distIndMap.begin();
+ for ( ; dist_ind != distIndMap.end(); dist_ind++ )
+ g.push_back( dist_ind->second );
+ }
+ } // loop on myIdsOnBoundary
+}
- for ( ; pIt != shapePoints.end(); pIt++ )
- block.VertexPoint( shapeID, (*pIt)->myXYZ.ChangeCoord() );
- break;
+//=======================================================================
+//function : makePolyElements
+//purpose : prepare intermediate data to create Polygons and Polyhedrons
+//=======================================================================
+
+void SMESH_Pattern::
+ makePolyElements(const vector< const SMDS_MeshNode* >& theNodes,
+ const bool toCreatePolygons,
+ const bool toCreatePolyedrs)
+{
+ myPolyElemXYZIDs.clear();
+ myPolyElems.clear();
+ myPolyElems.reserve( myIdsOnBoundary.size() );
+
+ // make a set of refined elements
+ TIDSortedElemSet avoidSet, elemSet;
+ std::vector<const SMDS_MeshElement*>::iterator itv = myElements.begin();
+ for(; itv!=myElements.end(); itv++) {
+ const SMDS_MeshElement* el = (*itv);
+ avoidSet.insert( el );
+ }
+ //avoidSet.insert( myElements.begin(), myElements.end() );
+
+ map< TNodeSet, list< list< int > > >::iterator indListIt, nn_IdList;
+
+ if ( toCreatePolygons )
+ {
+ int lastFreeId = myXYZ.size();
+
+ // loop on links of refined elements
+ indListIt = myIdsOnBoundary.begin();
+ for ( ; indListIt != myIdsOnBoundary.end(); indListIt++ )
+ {
+ const TNodeSet & linkNodes = indListIt->first;
+ if ( linkNodes.size() != 2 )
+ continue; // skip face
+ const SMDS_MeshNode* n1 = * linkNodes.begin();
+ const SMDS_MeshNode* n2 = * linkNodes.rbegin();
+
+ list<list< int > >& idGroups = indListIt->second; // ids of nodes to build
+ if ( idGroups.empty() || idGroups.front().empty() )
+ continue;
+
+ // find not refined face having n1-n2 link
+
+ while (true)
+ {
+ const SMDS_MeshElement* face =
+ SMESH_MeshEditor::FindFaceInSet( n1, n2, elemSet, avoidSet );
+ if ( face )
+ {
+ avoidSet.insert ( face );
+ myPolyElems.push_back( face );
+
+ // some links of <face> are split;
+ // make list of xyz for <face>
+ myPolyElemXYZIDs.push_back(TElemDef());
+ TElemDef & faceNodeIds = myPolyElemXYZIDs.back();
+ // loop on links of a <face>
+ SMDS_ElemIteratorPtr nIt = face->nodesIterator();
+ int i = 0, nbNodes = face->NbNodes();
+ vector<const SMDS_MeshNode*> nodes( nbNodes + 1 );
+ while ( nIt->more() )
+ nodes[ i++ ] = smdsNode( nIt->next() );
+ nodes[ i ] = nodes[ 0 ];
+ for ( i = 0; i < nbNodes; ++i )
+ {
+ // look for point mapped on a link
+ TNodeSet faceLinkNodes;
+ faceLinkNodes.insert( nodes[ i ] );
+ faceLinkNodes.insert( nodes[ i + 1 ] );
+ if ( faceLinkNodes == linkNodes )
+ nn_IdList = indListIt;
+ else
+ nn_IdList = myIdsOnBoundary.find( faceLinkNodes );
+ // add face point ids
+ faceNodeIds.push_back( ++lastFreeId );
+ myXYZIdToNodeMap.insert( make_pair( lastFreeId, nodes[ i ]));
+ if ( nn_IdList != myIdsOnBoundary.end() )
+ {
+ // there are points mapped on a link
+ list< int >& mappedIds = nn_IdList->second.front();
+ if ( isReversed( nodes[ i ], mappedIds ))
+ faceNodeIds.insert (faceNodeIds.end(),mappedIds.rbegin(), mappedIds.rend() );
+ else
+ faceNodeIds.insert (faceNodeIds.end(),mappedIds.begin(), mappedIds.end() );
+ }
+ } // loop on links of a <face>
+ } // if ( face )
+ else
+ break;
+ } // while (true)
+
+ if ( myIs2D && idGroups.size() > 1 ) {
+
+ // sew new elements on 2 refined elements sharing n1-n2 link
+
+ list< int >& idsOnLink = idGroups.front();
+ // temporarily add ids of link nodes to idsOnLink
+ bool rev = isReversed( n1, idsOnLink );
+ for ( int i = 0; i < 2; ++i )
+ {
+ TNodeSet nodeSet;
+ nodeSet.insert( i ? n2 : n1 );
+ ASSERT( myIdsOnBoundary.find( nodeSet ) != myIdsOnBoundary.end() );
+ list<list< int > >& groups = myIdsOnBoundary[ nodeSet ];
+ int nodeId = groups.front().front();
+ bool append = i;
+ if ( rev ) append = !append;
+ if ( append )
+ idsOnLink.push_back( nodeId );
+ else
+ idsOnLink.push_front( nodeId );
+ }
+ list< int >::iterator id = idsOnLink.begin();
+ for ( ; id != idsOnLink.end(); ++id ) // loop on XYZ ids on a link
+ {
+ list< TElemDef* >& elemDefs = myReverseConnectivity[ *id ]; // elems sharing id
+ list< TElemDef* >::iterator pElemDef = elemDefs.begin();
+ for ( ; pElemDef != elemDefs.end(); pElemDef++ ) // loop on elements sharing id
+ {
+ TElemDef* pIdList = *pElemDef; // ptr on list of ids making element up
+ // look for <id> in element definition
+ TElemDef::iterator idDef = find( pIdList->begin(), pIdList->end(), *id );
+ ASSERT ( idDef != pIdList->end() );
+ // look for 2 neighbour ids of <id> in element definition
+ for ( int prev = 0; prev < 2; ++prev ) {
+ TElemDef::iterator idDef2 = idDef;
+ if ( prev )
+ idDef2 = ( idDef2 == pIdList->begin() ) ? --pIdList->end() : --idDef2;
+ else
+ idDef2 = ( ++idDef2 == pIdList->end() ) ? pIdList->begin() : idDef2;
+ // look for idDef2 on a link starting from id
+ list< int >::iterator id2 = find( id, idsOnLink.end(), *idDef2 );
+ if ( id2 != idsOnLink.end() && id != --id2 ) { // found not next to id
+ // insert ids located on link between <id> and <id2>
+ // into the element definition between idDef and idDef2
+ if ( prev )
+ for ( ; id2 != id; --id2 )
+ pIdList->insert( idDef, *id2 );
+ else {
+ list< int >::iterator id1 = id;
+ for ( ++id1, ++id2; id1 != id2; ++id1 )
+ pIdList->insert( idDef2, *id1 );
+ }
+ }
+ }
+ }
+ }
+ // remove ids of link nodes
+ idsOnLink.pop_front();
+ idsOnLink.pop_back();
+ }
+ } // loop on myIdsOnBoundary
+ } // if ( toCreatePolygons )
+
+ if ( toCreatePolyedrs )
+ {
+ // check volumes adjacent to the refined elements
+ SMDS_VolumeTool volTool;
+ vector<const SMDS_MeshElement*>::iterator refinedElem = myElements.begin();
+ for ( ; refinedElem != myElements.end(); ++refinedElem )
+ {
+ // loop on nodes of refinedElem
+ SMDS_ElemIteratorPtr nIt = (*refinedElem)->nodesIterator();
+ while ( nIt->more() ) {
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
+ // loop on inverse elements of node
+ SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
+ while ( eIt->more() )
+ {
+ const SMDS_MeshElement* elem = eIt->next();
+ if ( !volTool.Set( elem ) || !avoidSet.insert( elem ).second )
+ continue; // skip faces or refined elements
+ // add polyhedron definition
+ myPolyhedronQuantities.push_back(vector<int> ());
+ myPolyElemXYZIDs.push_back(TElemDef());
+ vector<int>& quantity = myPolyhedronQuantities.back();
+ TElemDef & elemDef = myPolyElemXYZIDs.back();
+ // get definitions of new elements on volume faces
+ bool makePoly = false;
+ for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
+ {
+ if ( getFacesDefinition(volTool.GetFaceNodes( iF ),
+ volTool.NbFaceNodes( iF ),
+ theNodes, elemDef, quantity))
+ makePoly = true;
+ }
+ if ( makePoly )
+ myPolyElems.push_back( elem );
+ else {
+ myPolyhedronQuantities.pop_back();
+ myPolyElemXYZIDs.pop_back();
+ }
+ }
+ }
}
- case TopAbs_EDGE: {
+ }
+}
- for ( ; pIt != shapePoints.end(); pIt++ )
- block.EdgePoint( shapeID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
- break;
+//=======================================================================
+//function : getFacesDefinition
+//purpose : return faces definition for a volume face defined by theBndNodes
+//=======================================================================
+
+bool SMESH_Pattern::
+ getFacesDefinition(const SMDS_MeshNode** theBndNodes,
+ const int theNbBndNodes,
+ const vector< const SMDS_MeshNode* >& theNodes,
+ list< int >& theFaceDefs,
+ vector<int>& theQuantity)
+{
+ bool makePoly = false;
+// cout << "FROM FACE NODES: " <<endl;
+// for ( int i = 0; i < theNbBndNodes; ++i )
+// cout << theBndNodes[ i ];
+
+ set< const SMDS_MeshNode* > bndNodeSet;
+ for ( int i = 0; i < theNbBndNodes; ++i )
+ bndNodeSet.insert( theBndNodes[ i ]);
+
+ map< TNodeSet, list< list< int > > >::iterator nn_IdList;
+
+ // make a set of all nodes on a face
+ set< int > ids;
+ if ( !myIs2D ) { // for 2D, merge only edges
+ nn_IdList = myIdsOnBoundary.find( bndNodeSet );
+ if ( nn_IdList != myIdsOnBoundary.end() ) {
+ makePoly = true;
+ list< int > & faceIds = nn_IdList->second.front();
+ ids.insert( faceIds.begin(), faceIds.end() );
}
- case TopAbs_FACE: {
+ }
+ //bool hasIdsInFace = !ids.empty();
- for ( ; pIt != shapePoints.end(); pIt++ )
- block.FacePoint( shapeID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
- break;
+ // add ids on links and bnd nodes
+ int lastFreeId = Max( myXYZIdToNodeMap.rbegin()->first, theNodes.size() );
+ TElemDef faceDef; // definition for the case if there is no new adjacent volumes
+ for ( int iN = 0; iN < theNbBndNodes; ++iN )
+ {
+ // add id of iN-th bnd node
+ TNodeSet nSet;
+ nSet.insert( theBndNodes[ iN ] );
+ nn_IdList = myIdsOnBoundary.find( nSet );
+ int bndId = ++lastFreeId;
+ if ( nn_IdList != myIdsOnBoundary.end() ) {
+ bndId = nn_IdList->second.front().front();
+ ids.insert( bndId );
}
- default:
- for ( ; pIt != shapePoints.end(); pIt++ )
- block.ShellPoint( (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
+ else
+ myXYZIdToNodeMap.insert( make_pair( bndId, theBndNodes[ iN ] ));
+ faceDef.push_back( bndId );
+ // add ids on a link
+ TNodeSet linkNodes;
+ linkNodes.insert( theBndNodes[ iN ]);
+ linkNodes.insert( theBndNodes[ iN + 1 == theNbBndNodes ? 0 : iN + 1 ]);
+ nn_IdList = myIdsOnBoundary.find( linkNodes );
+ if ( nn_IdList != myIdsOnBoundary.end() ) {
+ makePoly = true;
+ list< int > & linkIds = nn_IdList->second.front();
+ ids.insert( linkIds.begin(), linkIds.end() );
+ if ( isReversed( theBndNodes[ iN ], linkIds ))
+ faceDef.insert( faceDef.end(), linkIds.begin(), linkIds.end() );
+ else
+ faceDef.insert( faceDef.end(), linkIds.rbegin(), linkIds.rend() );
}
- } // loop on block sub-shapes
+ }
- myIsComputed = true;
+ // find faces definition of new volumes
- return setErrorCode( ERR_OK );
+ bool defsAdded = false;
+ if ( !myIs2D ) { // for 2D, merge only edges
+ SMDS_VolumeTool vol;
+ set< TElemDef* > checkedVolDefs;
+ set< int >::iterator id = ids.begin();
+ for ( ; id != ids.end(); ++id )
+ {
+ // definitions of volumes sharing id
+ list< TElemDef* >& defList = myReverseConnectivity[ *id ];
+ ASSERT( !defList.empty() );
+ // loop on volume definitions
+ list< TElemDef* >::iterator pIdList = defList.begin();
+ for ( ; pIdList != defList.end(); ++pIdList)
+ {
+ if ( !checkedVolDefs.insert( *pIdList ).second )
+ continue; // skip already checked volume definition
+ vector< int > idVec;
+ idVec.reserve( (*pIdList)->size() );
+ idVec.insert( idVec.begin(), (*pIdList)->begin(), (*pIdList)->end() );
+ // loop on face defs of a volume
+ SMDS_VolumeTool::VolumeType volType = vol.GetType( idVec.size() );
+ if ( volType == SMDS_VolumeTool::UNKNOWN )
+ continue;
+ int nbFaces = vol.NbFaces( volType );
+ for ( int iF = 0; iF < nbFaces; ++iF )
+ {
+ const int* nodeInds = vol.GetFaceNodesIndices( volType, iF, true );
+ int iN, nbN = vol.NbFaceNodes( volType, iF );
+ // check if all nodes of a faces are in <ids>
+ bool all = true;
+ for ( iN = 0; iN < nbN && all; ++iN ) {
+ int nodeId = idVec[ nodeInds[ iN ]];
+ all = ( ids.find( nodeId ) != ids.end() );
+ }
+ if ( all ) {
+ // store a face definition
+ for ( iN = 0; iN < nbN; ++iN ) {
+ theFaceDefs.push_back( idVec[ nodeInds[ iN ]]);
+ }
+ theQuantity.push_back( nbN );
+ defsAdded = true;
+ }
+ }
+ }
+ }
+ }
+ if ( !defsAdded ) {
+ theQuantity.push_back( faceDef.size() );
+ theFaceDefs.splice( theFaceDefs.end(), faceDef, faceDef.begin(), faceDef.end() );
+ }
+
+ return makePoly;
+}
+
+//=======================================================================
+//function : clearSubMesh
+//purpose :
+//=======================================================================
+
+static bool clearSubMesh( SMESH_Mesh* theMesh,
+ const TopoDS_Shape& theShape)
+{
+ bool removed = false;
+ if ( SMESH_subMesh * aSubMesh = theMesh->GetSubMeshContaining( theShape ))
+ {
+ if ( aSubMesh->GetSubMeshDS() ) {
+ removed =
+ aSubMesh->GetSubMeshDS()->NbElements() || aSubMesh->GetSubMeshDS()->NbNodes();
+ aSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN );
+ }
+ }
+ else {
+ SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS();
+ if ( SMESHDS_SubMesh* aSubMeshDS = aMeshDS->MeshElements( theShape ))
+ {
+ SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
+ removed = eIt->more();
+ while ( eIt->more() )
+ aMeshDS->RemoveElement( eIt->next() );
+ SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
+ removed = removed || nIt->more();
+ while ( nIt->more() )
+ aMeshDS->RemoveNode( smdsNode( nIt->next() ));
+ }
+ }
+ return removed;
+}
+
+//=======================================================================
+//function : clearMesh
+//purpose : clear mesh elements existing on myShape in theMesh
+//=======================================================================
+
+void SMESH_Pattern::clearMesh(SMESH_Mesh* theMesh) const
+{
+
+ if ( !myShape.IsNull() )
+ {
+ if ( !clearSubMesh( theMesh, myShape ) && !myIs2D ) { // myShape is SHELL but volumes may be bound to SOLID
+ TopTools_ListIteratorOfListOfShape it( theMesh->GetAncestors( myShape ));
+ for (; it.More() && it.Value().ShapeType() == TopAbs_SOLID; it.Next())
+ {
+ clearSubMesh( theMesh, it.Value() );
+ }
+ }
+ }
}
//=======================================================================
//function : MakeMesh
//purpose : Create nodes and elements in <theMesh> using nodes
// coordinates computed by either of Apply...() methods
+// WARNING : StdMeshers_Projection_... relies on MakeMesh() behavior: that
+// it does not care of nodes and elements already existing on
+// subshapes. DO NOT MERGE them or modify also StdMeshers_Projection_..
//=======================================================================
-bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh)
+bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
+ const bool toCreatePolygons,
+ const bool toCreatePolyedrs)
{
MESSAGE(" ::MakeMesh() " );
if ( !myIsComputed )
return setErrorCode( ERR_MAKEM_NOT_COMPUTED );
+ mergePoints( toCreatePolygons );
+
SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS();
// clear elements and nodes existing on myShape
- SMESH_subMesh * aSubMesh = theMesh->GetSubMeshContaining( myShape );
- SMESHDS_SubMesh * aSubMeshDS = aMeshDS->MeshElements( myShape );
- if ( aSubMesh )
- aSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN );
- else if ( aSubMeshDS )
+ clearMesh(theMesh);
+
+ bool onMeshElements = ( !myElements.empty() );
+
+ // Create missing nodes
+
+ vector< const SMDS_MeshNode* > nodesVector; // i-th point/xyz -> node
+ if ( onMeshElements )
{
- SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
- while ( eIt->more() )
- aMeshDS->RemoveElement( eIt->next() );
- SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
- while ( nIt->more() )
- aMeshDS->RemoveNode( static_cast<const SMDS_MeshNode*>( nIt->next() ));
+ nodesVector.resize( Max( myXYZ.size(), myXYZIdToNodeMap.rbegin()->first ), 0 );
+ map< int, const SMDS_MeshNode*>::iterator i_node = myXYZIdToNodeMap.begin();
+ for ( ; i_node != myXYZIdToNodeMap.end(); i_node++ ) {
+ nodesVector[ i_node->first ] = i_node->second;
+ }
+ for ( int i = 0; i < myXYZ.size(); ++i ) {
+ if ( !nodesVector[ i ] && isDefined( myXYZ[ i ] ) )
+ nodesVector[ i ] = aMeshDS->AddNode (myXYZ[ i ].X(),
+ myXYZ[ i ].Y(),
+ myXYZ[ i ].Z());
+ }
}
-
- // loop on sub-shapes of myShape: create nodes and build point-node map
- typedef map< TPoint*, const SMDS_MeshNode* > TPointNodeMap;
- TPointNodeMap pointNodeMap;
- map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
- for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
+ else
{
- const TopoDS_Shape & S = myShapeIDMap( (*idPointIt).first );
- list< TPoint* > & points = (*idPointIt).second;
- SMESHDS_SubMesh * subMeshDS = aMeshDS->MeshElements( S );
- SMESH_subMesh * subMesh = theMesh->GetSubMeshContaining( myShape );
- list< TPoint* >::iterator pIt = points.begin();
- for ( ; pIt != points.end(); pIt++ )
+ nodesVector.resize( myPoints.size(), 0 );
+
+ // to find point index
+ map< TPoint*, int > pointIndex;
+ for ( int i = 0; i < myPoints.size(); i++ )
+ pointIndex.insert( make_pair( & myPoints[ i ], i ));
+
+ // loop on sub-shapes of myShape: create nodes
+ map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
+ for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
{
- TPoint* point = *pIt;
- if ( pointNodeMap.find( point ) != pointNodeMap.end() )
- continue;
- SMDS_MeshNode* node = aMeshDS->AddNode (point->myXYZ.X(),
- point->myXYZ.Y(),
- point->myXYZ.Z());
- pointNodeMap.insert( TPointNodeMap::value_type( point, node ));
- if ( subMeshDS ) {
- switch ( S.ShapeType() ) {
- case TopAbs_VERTEX: {
- aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S ));
- break;
- }
- case TopAbs_EDGE: {
- aMeshDS->SetNodeOnEdge( node, TopoDS::Edge( S ));
- SMDS_EdgePosition* epos =
- dynamic_cast<SMDS_EdgePosition *>(node->GetPosition().get());
- epos->SetUParameter( point->myU );
- break;
- }
- case TopAbs_FACE: {
- aMeshDS->SetNodeOnFace( node, TopoDS::Face( S ));
- SMDS_FacePosition* pos =
- dynamic_cast<SMDS_FacePosition *>(node->GetPosition().get());
- pos->SetUParameter( point->myUV.X() );
- pos->SetVParameter( point->myUV.Y() );
- break;
- }
- default:
- aMeshDS->SetNodeInVolume( node, TopoDS::Shell( S ));
+ TopoDS_Shape S;
+ //SMESHDS_SubMesh * subMeshDS = 0;
+ if ( !myShapeIDMap.IsEmpty() ) {
+ S = myShapeIDMap( idPointIt->first );
+ //subMeshDS = aMeshDS->MeshElements( S );
+ }
+ list< TPoint* > & points = idPointIt->second;
+ list< TPoint* >::iterator pIt = points.begin();
+ for ( ; pIt != points.end(); pIt++ )
+ {
+ TPoint* point = *pIt;
+ int pIndex = pointIndex[ point ];
+ if ( nodesVector [ pIndex ] )
+ continue;
+ SMDS_MeshNode* node = aMeshDS->AddNode (point->myXYZ.X(),
+ point->myXYZ.Y(),
+ point->myXYZ.Z());
+ nodesVector [ pIndex ] = node;
+
+ if ( true /*subMeshDS*/ ) {
+ // !!!!! do not merge new nodes with ones existing on submeshes (see method comment)
+ switch ( S.ShapeType() ) {
+ case TopAbs_VERTEX: {
+ aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S )); break;
+ }
+ case TopAbs_EDGE: {
+ aMeshDS->SetNodeOnEdge( node, TopoDS::Edge( S ), point->myU ); break;
+ }
+ case TopAbs_FACE: {
+ aMeshDS->SetNodeOnFace( node, TopoDS::Face( S ),
+ point->myUV.X(), point->myUV.Y() ); break;
+ }
+ default:
+ aMeshDS->SetNodeInVolume( node, TopoDS::Shell( S ));
+ }
}
}
}
- // make that SMESH_subMesh::_computeState = COMPUTE_OK
- // so that operations with hypotheses will erase the mesh
- // being built
- if ( subMesh )
- subMesh->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
}
// create elements
- list<list< int > >::iterator epIt = myElemPointIDs.begin();
- for ( ; epIt != myElemPointIDs.end(); epIt++ )
+
+ if ( onMeshElements )
+ {
+ // prepare data to create poly elements
+ makePolyElements( nodesVector, toCreatePolygons, toCreatePolyedrs );
+
+ // refine elements
+ createElements( theMesh, nodesVector, myElemXYZIDs, myElements );
+ // sew old and new elements
+ createElements( theMesh, nodesVector, myPolyElemXYZIDs, myPolyElems );
+ }
+ else
+ {
+ createElements( theMesh, nodesVector, myElemPointIDs, myElements );
+ }
+
+// const map<int,SMESHDS_SubMesh*>& sm = aMeshDS->SubMeshes();
+// map<int,SMESHDS_SubMesh*>::const_iterator i_sm = sm.begin();
+// for ( ; i_sm != sm.end(); i_sm++ )
+// {
+// cout << " SM " << i_sm->first << " ";
+// TopAbs::Print( aMeshDS->IndexToShape( i_sm->first ).ShapeType(), cout)<< " ";
+// //SMDS_ElemIteratorPtr GetElements();
+// SMDS_NodeIteratorPtr nit = i_sm->second->GetNodes();
+// while ( nit->more() )
+// cout << nit->next()->GetID() << " ";
+// cout << endl;
+// }
+ return setErrorCode( ERR_OK );
+}
+
+//=======================================================================
+//function : createElements
+//purpose : add elements to the mesh
+//=======================================================================
+
+void SMESH_Pattern::createElements(SMESH_Mesh* theMesh,
+ const vector<const SMDS_MeshNode* >& theNodesVector,
+ const list< TElemDef > & theElemNodeIDs,
+ const vector<const SMDS_MeshElement*>& theElements)
+{
+ SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS();
+ SMESH_MeshEditor editor( theMesh );
+
+ bool onMeshElements = !theElements.empty();
+
+ // shapes and groups theElements are on
+ vector< int > shapeIDs;
+ vector< list< SMESHDS_Group* > > groups;
+ set< const SMDS_MeshNode* > shellNodes;
+ if ( onMeshElements )
+ {
+ shapeIDs.resize( theElements.size() );
+ groups.resize( theElements.size() );
+ const set<SMESHDS_GroupBase*>& allGroups = aMeshDS->GetGroups();
+ set<SMESHDS_GroupBase*>::const_iterator grIt;
+ for ( int i = 0; i < theElements.size(); i++ )
+ {
+ shapeIDs[ i ] = editor.FindShape( theElements[ i ] );
+ for ( grIt = allGroups.begin(); grIt != allGroups.end(); grIt++ ) {
+ SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *grIt );
+ if ( group && group->SMDSGroup().Contains( theElements[ i ] ))
+ groups[ i ].push_back( group );
+ }
+ }
+ // get all nodes bound to shells because their SpacePosition is not set
+ // by SMESHDS_Mesh::SetNodeInVolume()
+ TopoDS_Shape aMainShape = aMeshDS->ShapeToMesh();
+ if ( !aMainShape.IsNull() ) {
+ TopExp_Explorer shellExp( aMainShape, TopAbs_SHELL );
+ for ( ; shellExp.More(); shellExp.Next() )
+ {
+ SMESHDS_SubMesh * sm = aMeshDS->MeshElements( shellExp.Current() );
+ if ( sm ) {
+ SMDS_NodeIteratorPtr nIt = sm->GetNodes();
+ while ( nIt->more() )
+ shellNodes.insert( nIt->next() );
+ }
+ }
+ }
+ }
+ // nb new elements per a refined element
+ int nbNewElemsPerOld = 1;
+ if ( onMeshElements )
+ nbNewElemsPerOld = theElemNodeIDs.size() / theElements.size();
+
+ bool is2d = myIs2D;
+
+ list< TElemDef >::const_iterator enIt = theElemNodeIDs.begin();
+ list< vector<int> >::iterator quantity = myPolyhedronQuantities.begin();
+ for ( int iElem = 0; enIt != theElemNodeIDs.end(); enIt++, iElem++ )
{
- list< int > & elemPoints = *epIt;
+ const TElemDef & elemNodeInd = *enIt;
// retrieve nodes
- const SMDS_MeshNode* nodes[ 8 ];
- list< int >::iterator iIt = elemPoints.begin();
+ vector< const SMDS_MeshNode* > nodes( elemNodeInd.size() );
+ TElemDef::const_iterator id = elemNodeInd.begin();
int nbNodes;
- for ( nbNodes = 0; iIt != elemPoints.end(); iIt++ ) {
- nodes[ nbNodes++ ] = pointNodeMap[ & myPoints[ *iIt ]];
+ for ( nbNodes = 0; id != elemNodeInd.end(); id++ ) {
+ if ( *id < theNodesVector.size() )
+ nodes[ nbNodes++ ] = theNodesVector[ *id ];
+ else
+ nodes[ nbNodes++ ] = myXYZIdToNodeMap[ *id ];
+ }
+ // dim of refined elem
+ int elemIndex = iElem / nbNewElemsPerOld; // refined element index
+ if ( onMeshElements ) {
+ is2d = ( theElements[ elemIndex ]->GetType() == SMDSAbs_Face );
}
// add an element
const SMDS_MeshElement* elem = 0;
- if ( myIs2D ) {
+ if ( is2d ) {
switch ( nbNodes ) {
case 3:
elem = aMeshDS->AddFace( nodes[0], nodes[1], nodes[2] ); break;
case 4:
elem = aMeshDS->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break;
- default:;
+ case 6:
+ if ( !onMeshElements ) {// create a quadratic face
+ elem = aMeshDS->AddFace (nodes[0], nodes[1], nodes[2], nodes[3],
+ nodes[4], nodes[5] ); break;
+ } // else do not break but create a polygon
+ case 8:
+ if ( !onMeshElements ) {// create a quadratic face
+ elem = aMeshDS->AddFace (nodes[0], nodes[1], nodes[2], nodes[3],
+ nodes[4], nodes[5], nodes[6], nodes[7] ); break;
+ } // else do not break but create a polygon
+ default:
+ elem = aMeshDS->AddPolygonalFace( nodes );
}
}
else {
case 8:
elem = aMeshDS->AddVolume (nodes[0], nodes[1], nodes[2], nodes[3],
nodes[4], nodes[5], nodes[6], nodes[7] ); break;
- default:;
+ default:
+ elem = aMeshDS->AddPolyhedralVolume( nodes, *quantity++ );
+ }
+ }
+ // set element on a shape
+ if ( elem && onMeshElements ) // applied to mesh elements
+ {
+ int shapeID = shapeIDs[ elemIndex ];
+ if ( shapeID > 0 ) {
+ aMeshDS->SetMeshElementOnShape( elem, shapeID );
+ // set nodes on a shape
+ TopoDS_Shape S = aMeshDS->IndexToShape( shapeID );
+ if ( S.ShapeType() == TopAbs_SOLID ) {
+ TopoDS_Iterator shellIt( S );
+ if ( shellIt.More() )
+ shapeID = aMeshDS->ShapeToIndex( shellIt.Value() );
+ }
+ SMDS_ElemIteratorPtr noIt = elem->nodesIterator();
+ while ( noIt->more() ) {
+ SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>(smdsNode( noIt->next() ));
+ if (!node->GetPosition()->GetShapeId() &&
+ shellNodes.find( node ) == shellNodes.end() ) {
+ if ( S.ShapeType() == TopAbs_FACE )
+ aMeshDS->SetNodeOnFace( node, shapeID );
+ else {
+ aMeshDS->SetNodeInVolume( node, shapeID );
+ shellNodes.insert( node );
+ }
+ }
+ }
}
+ // add elem in groups
+ list< SMESHDS_Group* >::iterator g = groups[ elemIndex ].begin();
+ for ( ; g != groups[ elemIndex ].end(); ++g )
+ (*g)->SMDSGroup().Add( elem );
}
- if ( elem )
+ if ( elem && !myShape.IsNull() ) // applied to shape
aMeshDS->SetMeshElementOnShape( elem, myShape );
}
- return setErrorCode( ERR_OK );
+ // make that SMESH_subMesh::_computeState == COMPUTE_OK
+ // so that operations with hypotheses will erase the mesh being built
+
+ SMESH_subMesh * subMesh;
+ if ( !myShape.IsNull() ) {
+ subMesh = theMesh->GetSubMesh( myShape );
+ if ( subMesh )
+ subMesh->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ }
+ if ( onMeshElements ) {
+ list< int > elemIDs;
+ for ( int i = 0; i < theElements.size(); i++ )
+ {
+ subMesh = theMesh->GetSubMeshContaining( shapeIDs[ i ] );
+ if ( subMesh )
+ subMesh->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+
+ elemIDs.push_back( theElements[ i ]->GetID() );
+ }
+ // remove refined elements
+ editor.Remove( elemIDs, false );
+ }
+}
+
+//=======================================================================
+//function : isReversed
+//purpose : check xyz ids order in theIdsList taking into account
+// theFirstNode on a link
+//=======================================================================
+
+bool SMESH_Pattern::isReversed(const SMDS_MeshNode* theFirstNode,
+ const list< int >& theIdsList) const
+{
+ if ( theIdsList.size() < 2 )
+ return false;
+
+ gp_Pnt Pf ( theFirstNode->X(), theFirstNode->Y(), theFirstNode->Z() );
+ gp_Pnt P[2];
+ list<int>::const_iterator id = theIdsList.begin();
+ for ( int i = 0; i < 2; ++i, ++id ) {
+ if ( *id < myXYZ.size() )
+ P[ i ] = myXYZ[ *id ];
+ else {
+ map< int, const SMDS_MeshNode*>::const_iterator i_n;
+ i_n = myXYZIdToNodeMap.find( *id );
+ ASSERT( i_n != myXYZIdToNodeMap.end() );
+ const SMDS_MeshNode* n = i_n->second;
+ P[ i ].SetCoord( n->X(), n->Y(), n->Z() );
+ }
+ }
+ return Pf.SquareDistance( P[ 1 ] ) < Pf.SquareDistance( P[ 0 ] );
}
MESSAGE(" findBoundaryPoints() ");
+ myNbKeyPntInBoundary.clear();
+
if ( myIs2D )
{
set< TPoint* > pointsInElems;
typedef pair< TPoint*, TPoint*> TLink;
set< TLink > linkSet;
- list<list< int > >::iterator epIt = myElemPointIDs.begin();
+ list<TElemDef >::iterator epIt = myElemPointIDs.begin();
for ( ; epIt != myElemPointIDs.end(); epIt++ )
{
- list< int > & elemPoints = *epIt;
- list< int >::iterator pIt = elemPoints.begin();
+ TElemDef & elemPoints = *epIt;
+ TElemDef::iterator pIt = elemPoints.begin();
int prevP = elemPoints.back();
for ( ; pIt != elemPoints.end(); pIt++ ) {
TPoint* p1 = & myPoints[ prevP ];
double edgeLength = 0;
list< TPoint* >::iterator pIt = boundary->begin();
getShapePoints( edgeID ).push_back( *pIt );
+ getShapePoints( vertexID++ ).push_back( *pIt );
for ( pIt++; pIt != boundary->end(); pIt++)
{
list< TPoint* > & edgePoints = getShapePoints( edgeID );
}
// begin the next edge treatment
edgeLength = 0;
- getShapePoints( vertexID++ ).push_back( point );
edgeID++;
- if ( point != boundary->front() )
+ if ( point != boundary->front() ) { // not the first key-point again
getShapePoints( edgeID ).push_back( point );
+ getShapePoints( vertexID++ ).push_back( point );
+ }
}
}
}
TopTools_IndexedMapOfShape vMap;
TopExp::MapShapes( theShape, TopAbs_VERTEX, vMap );
if ( vMap.Extent() + nbNodeOnSeamEdge != myKeyPointIDs.size() ) {
- MESSAGE( myKeyPointIDs.size() << " != " << vMap.Extent() );
+ MESSAGE( myKeyPointIDs.size() + nbNodeOnSeamEdge << " != " << vMap.Extent() );
return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
}
+ myElements.clear(); // not refine elements
+ myElemXYZIDs.clear();
+
myShapeIDMap.Clear();
myShape = theShape;
return true;
//purpose : Return nodes coordinates computed by Apply() method
//=======================================================================
-bool SMESH_Pattern::GetMappedPoints ( list< const gp_XYZ * > & thePoints )
+bool SMESH_Pattern::GetMappedPoints ( list< const gp_XYZ * > & thePoints ) const
{
thePoints.clear();
if ( !myIsComputed )
return false;
- vector< TPoint >::iterator pVecIt = myPoints.begin();
- for ( ; pVecIt != myPoints.end(); pVecIt++ )
- thePoints.push_back( & (*pVecIt).myXYZ.XYZ() );
-
- return ( thePoints.size() > 0 );
+ if ( myElements.empty() ) { // applied to shape
+ vector< TPoint >::const_iterator pVecIt = myPoints.begin();
+ for ( ; pVecIt != myPoints.end(); pVecIt++ )
+ thePoints.push_back( & (*pVecIt).myXYZ.XYZ() );
+ }
+ else { // applied to mesh elements
+ const gp_XYZ * definedXYZ = & myPoints[ myKeyPointIDs.front() ].myXYZ.XYZ();
+ vector<gp_XYZ>::const_iterator xyz = myXYZ.begin();
+ for ( ; xyz != myXYZ.end(); ++xyz )
+ if ( !isDefined( *xyz ))
+ thePoints.push_back( definedXYZ );
+ else
+ thePoints.push_back( & (*xyz) );
+ }
+ return !thePoints.empty();
}