1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : StdMeshers_Projection_2D.cxx
26 // Created : Fri Oct 20 11:37:07 2006
27 // Author : Edward AGAPOV (eap)
30 #include "StdMeshers_Projection_2D.hxx"
32 #include "StdMeshers_ProjectionSource2D.hxx"
33 #include "StdMeshers_ProjectionUtils.hxx"
35 #include "SMESHDS_Hypothesis.hxx"
36 #include "SMESHDS_SubMesh.hxx"
37 #include "SMESH_Block.hxx"
38 #include "SMESH_Gen.hxx"
39 #include "SMESH_Mesh.hxx"
40 #include "SMESH_MeshEditor.hxx"
41 #include "SMESH_Pattern.hxx"
42 #include "SMESH_subMesh.hxx"
43 #include "SMESH_subMeshEventListener.hxx"
44 #include "SMESH_Comment.hxx"
45 #include "SMDS_EdgePosition.hxx"
47 #include "utilities.h"
49 #include <BRep_Tool.hxx>
50 #include <Bnd_B2d.hxx>
52 #include <TopExp_Explorer.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
59 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
61 typedef StdMeshers_ProjectionUtils TAssocTool;
63 //=======================================================================
64 //function : StdMeshers_Projection_2D
66 //=======================================================================
68 StdMeshers_Projection_2D::StdMeshers_Projection_2D(int hypId, int studyId, SMESH_Gen* gen)
69 :SMESH_2D_Algo(hypId, studyId, gen)
71 _name = "Projection_2D";
72 _shapeType = (1 << TopAbs_FACE); // 1 bit per shape type
74 _compatibleHypothesis.push_back("ProjectionSource2D");
78 //================================================================================
82 //================================================================================
84 StdMeshers_Projection_2D::~StdMeshers_Projection_2D()
87 //=======================================================================
88 //function : CheckHypothesis
90 //=======================================================================
92 bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh& theMesh,
93 const TopoDS_Shape& theShape,
94 SMESH_Hypothesis::Hypothesis_Status& theStatus)
96 list <const SMESHDS_Hypothesis * >::const_iterator itl;
98 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(theMesh, theShape);
99 if ( hyps.size() == 0 )
101 theStatus = HYP_MISSING;
102 return false; // can't work with no hypothesis
105 if ( hyps.size() > 1 )
107 theStatus = HYP_ALREADY_EXIST;
111 const SMESHDS_Hypothesis *theHyp = hyps.front();
113 string hypName = theHyp->GetName();
117 if (hypName == "ProjectionSource2D")
119 _sourceHypo = static_cast<const StdMeshers_ProjectionSource2D *>(theHyp);
121 // Check hypo parameters
123 SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
124 SMESH_Mesh* tgtMesh = & theMesh;
129 if ( _sourceHypo->HasVertexAssociation() )
132 TopoDS_Shape edge = TAssocTool::GetEdgeByVertices
133 ( srcMesh, _sourceHypo->GetSourceVertex(1), _sourceHypo->GetSourceVertex(2) );
134 if ( edge.IsNull() ||
135 !TAssocTool::IsSubShape( edge, srcMesh ) ||
136 !TAssocTool::IsSubShape( edge, _sourceHypo->GetSourceFace() ))
138 theStatus = HYP_BAD_PARAMETER;
139 SCRUTE((edge.IsNull()));
140 SCRUTE((TAssocTool::IsSubShape( edge, srcMesh )));
141 SCRUTE((TAssocTool::IsSubShape( edge, _sourceHypo->GetSourceFace() )));
146 edge = TAssocTool::GetEdgeByVertices
147 ( tgtMesh, _sourceHypo->GetTargetVertex(1), _sourceHypo->GetTargetVertex(2) );
148 if ( edge.IsNull() || !TAssocTool::IsSubShape( edge, tgtMesh ))
150 theStatus = HYP_BAD_PARAMETER;
151 SCRUTE((edge.IsNull()));
152 SCRUTE((TAssocTool::IsSubShape( edge, tgtMesh )));
155 else if ( !_sourceHypo->IsCompoundSource() &&
156 !TAssocTool::IsSubShape( edge, theShape ))
158 theStatus = HYP_BAD_PARAMETER;
159 SCRUTE((TAssocTool::IsSubShape( edge, theShape )));
163 // check a source face
164 if ( !TAssocTool::IsSubShape( _sourceHypo->GetSourceFace(), srcMesh ) ||
165 ( srcMesh == tgtMesh && theShape == _sourceHypo->GetSourceFace() ))
167 theStatus = HYP_BAD_PARAMETER;
168 SCRUTE((TAssocTool::IsSubShape( _sourceHypo->GetSourceFace(), srcMesh )));
169 SCRUTE((srcMesh == tgtMesh));
170 SCRUTE(( theShape == _sourceHypo->GetSourceFace() ));
175 theStatus = HYP_INCOMPATIBLE;
177 return ( theStatus == HYP_OK );
183 //================================================================================
185 * \brief define if a node is new or old
186 * \param node - node to check
187 * \retval bool - true if the node existed before Compute() is called
189 //================================================================================
191 bool isOldNode( const SMDS_MeshNode* node )
193 // old nodes are shared by edges and new ones are shared
194 // only by faces created by mapper
195 SMDS_ElemIteratorPtr invEdge = node->GetInverseElementIterator(SMDSAbs_Edge);
196 bool isOld = invEdge->more();
200 //================================================================================
202 * \brief Class to remove mesh built by pattern mapper on edges
203 * and vertices in the case of failure of projection algo.
204 * It does it's job at destruction
206 //================================================================================
211 MeshCleaner( SMESH_subMesh* faceSubMesh ): sm(faceSubMesh) {}
212 ~MeshCleaner() { Clean(sm); }
213 void Release() { sm = 0; } // mesh will not be removed
214 static void Clean( SMESH_subMesh* sm, bool withSub=true )
217 // PAL16567, 18920. Remove face nodes as well
218 // switch ( sm->GetSubShape().ShapeType() ) {
219 // case TopAbs_VERTEX:
220 // case TopAbs_EDGE: {
221 SMDS_NodeIteratorPtr nIt = sm->GetSubMeshDS()->GetNodes();
222 SMESHDS_Mesh* mesh = sm->GetFather()->GetMeshDS();
223 while ( nIt->more() ) {
224 const SMDS_MeshNode* node = nIt->next();
225 if ( !isOldNode( node ) )
226 mesh->RemoveNode( node );
228 // do not break but iterate over DependsOn()
231 if ( !withSub ) return;
232 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
233 while ( smIt->more() )
234 Clean( smIt->next(), false );
239 //================================================================================
241 * \brief find new nodes belonging to one free border of mesh on face
242 * \param sm - submesh on edge or vertex containg nodes to choose from
243 * \param face - the face bound the submesh
244 * \param u2nodes - map to fill with nodes
245 * \param seamNodes - set of found nodes
246 * \retval bool - is a success
248 //================================================================================
250 bool getBoundaryNodes ( SMESH_subMesh* sm,
251 const TopoDS_Face& face,
252 map< double, const SMDS_MeshNode* > & u2nodes,
253 set< const SMDS_MeshNode* > & seamNodes)
257 if ( !sm || !sm->GetSubMeshDS() )
258 RETURN_BAD_RESULT("Null submesh");
260 SMDS_NodeIteratorPtr nIt = sm->GetSubMeshDS()->GetNodes();
261 switch ( sm->GetSubShape().ShapeType() ) {
263 case TopAbs_VERTEX: {
264 while ( nIt->more() ) {
265 const SMDS_MeshNode* node = nIt->next();
266 if ( isOldNode( node ) ) continue;
267 u2nodes.insert( make_pair( 0., node ));
268 seamNodes.insert( node );
275 // Get submeshes of sub-vertices
276 const map< int, SMESH_subMesh * >& subSM = sm->DependsOn();
277 if ( subSM.size() != 2 )
278 RETURN_BAD_RESULT("there must be 2 submeshes of sub-vertices"
279 " but we have " << subSM.size());
280 SMESH_subMesh* smV1 = subSM.begin()->second;
281 SMESH_subMesh* smV2 = subSM.rbegin()->second;
282 if ( !smV1->IsMeshComputed() || !smV2->IsMeshComputed() )
283 RETURN_BAD_RESULT("Empty vertex submeshes");
285 // Look for a new node on V1
286 nIt = smV1->GetSubMeshDS()->GetNodes();
287 const SMDS_MeshNode* nV1 = 0;
288 while ( nIt->more() && !nV1 ) {
289 const SMDS_MeshNode* node = nIt->next();
290 if ( !isOldNode( node ) ) nV1 = node;
293 RETURN_BAD_RESULT("No new node found on V1");
295 // Find a new node connected to nV1 and belonging to edge submesh;
296 const SMDS_MeshNode* nE = 0;
297 SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
298 SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator();
299 while ( vElems->more() && !nE ) {
300 const SMDS_MeshElement* elem = vElems->next();
301 if ( elem->GetType() != SMDSAbs_Face )
302 continue; // new nodes are shared by faces
303 int nbNodes = elem->NbNodes();
304 if ( elem->IsQuadratic() )
306 int iV1 = elem->GetNodeIndex( nV1 );
307 // try next aftre nV1
308 int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
309 if ( smDS->Contains( elem->GetNode( iE ) ))
310 nE = elem->GetNode( iE );
312 // try node before nV1
313 iE = SMESH_MesherHelper::WrapIndex( iV1 - 1, nbNodes );
314 if ( smDS->Contains( elem->GetNode( iE )))
315 nE = elem->GetNode( iE );
317 if ( nE && elem->IsQuadratic() ) { // find medium node between nV1 and nE
318 if ( Abs( iV1 - iE ) == 1 )
319 nE = elem->GetNode( Min ( iV1, iE ) + nbNodes );
321 nE = elem->GetNode( elem->NbNodes() - 1 );
325 RETURN_BAD_RESULT("new node on edge not found");
327 // Get the whole free border of a face
328 list< const SMDS_MeshNode* > bordNodes;
329 list< const SMDS_MeshElement* > bordFaces;
330 if ( !SMESH_MeshEditor::FindFreeBorder (nV1, nE, nV1, bordNodes, bordFaces ))
331 RETURN_BAD_RESULT("free border of a face not found by nodes " <<
332 nV1->GetID() << " " << nE->GetID() );
334 // Insert nodes of the free border to the map until node on V2 encountered
335 SMESHDS_SubMesh* v2smDS = smV2->GetSubMeshDS();
336 list< const SMDS_MeshNode* >::iterator bordIt = bordNodes.begin();
337 bordIt++; // skip nV1
338 for ( ; bordIt != bordNodes.end(); ++bordIt ) {
339 const SMDS_MeshNode* node = *bordIt;
340 if ( v2smDS->Contains( node ))
342 if ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_EDGE )
343 RETURN_BAD_RESULT("Bad node position type: node " << node->GetID() <<
344 " pos type " << node->GetPosition()->GetTypeOfPosition());
345 const SMDS_EdgePosition* pos =
346 static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
347 u2nodes.insert( make_pair( pos->GetUParameter(), node ));
348 seamNodes.insert( node );
350 if ( u2nodes.size() != seamNodes.size() )
351 RETURN_BAD_RESULT("Bad node params on edge " << sm->GetId() <<
352 ", " << u2nodes.size() << " != " << seamNodes.size() );
357 RETURN_BAD_RESULT ("Unexpected submesh type");
359 } // bool getBoundaryNodes()
363 //=======================================================================
366 //=======================================================================
368 bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
373 SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
374 SMESH_Mesh * tgtMesh = & theMesh;
378 SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
380 // ---------------------------
381 // Make subshapes association
382 // ---------------------------
384 TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
385 TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD);
387 TAssocTool::TShapeShapeMap shape2ShapeMap;
388 TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace );
389 if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh,
391 !shape2ShapeMap.IsBound( tgtFace ))
392 return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
394 TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD));
396 // ----------------------------------------------
397 // Assure that mesh on a source Face is computed
398 // ----------------------------------------------
400 SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace );
401 SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtFace );
403 if ( tgtMesh == srcMesh ) {
404 if ( !TAssocTool::MakeComputed( srcSubMesh ))
405 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
408 if ( !srcSubMesh->IsMeshComputed() )
409 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
412 // --------------------
413 // Prepare to mapping
414 // --------------------
416 SMESH_MesherHelper helper( theMesh );
417 helper.SetSubShape( tgtFace );
419 // Check if node projection to a face is needed
421 SMDS_ElemIteratorPtr faceIt = srcSubMesh->GetSubMeshDS()->GetElements();
422 for ( int nbN = 0; nbN < 3 && faceIt->more(); ) {
423 const SMDS_MeshElement* face = faceIt->next();
424 SMDS_ElemIteratorPtr nodeIt = face->nodesIterator();
425 while ( nodeIt->more() ) {
426 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
427 if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
429 uvBox.Add( helper.GetNodeUV( srcFace, node ));
433 const bool toProjectNodes = ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN );
435 // Load pattern from the source face
436 SMESH_Pattern mapper;
437 mapper.Load( srcMesh, srcFace, toProjectNodes );
438 if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
439 return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face");
441 // Find the first target vertex corresponding to first vertex of the <mapper>
442 // and <theReverse> flag needed to call mapper.Apply()
444 TopoDS_Vertex srcV1 = TopoDS::Vertex( mapper.GetSubShape( 1 ));
445 if ( srcV1.IsNull() )
446 RETURN_BAD_RESULT("Mesh is not bound to the face");
447 if ( !shape2ShapeMap.IsBound( srcV1 ))
448 RETURN_BAD_RESULT("Not associated vertices, srcV1 " << srcV1.TShape().operator->() );
449 TopoDS_Vertex tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1 ));
451 if ( !TAssocTool::IsSubShape( srcV1, srcFace ))
452 RETURN_BAD_RESULT("Wrong srcV1 " << srcV1.TShape().operator->());
453 if ( !TAssocTool::IsSubShape( tgtV1, tgtFace ))
454 RETURN_BAD_RESULT("Wrong tgtV1 " << tgtV1.TShape().operator->());
456 // try to find out orientation by order of edges
457 bool reverse = false;
458 list< TopoDS_Edge > tgtEdges, srcEdges;
459 list< int > nbEdgesInWires;
460 SMESH_Block::GetOrderedEdges( tgtFace, tgtV1, tgtEdges, nbEdgesInWires);
461 SMESH_Block::GetOrderedEdges( srcFace, srcV1, srcEdges, nbEdgesInWires);
462 if ( nbEdgesInWires.front() > 1 ) // possible to find out
464 TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front();
465 TopoDS_Shape srcE1bis = shape2ShapeMap( tgtE1 );
466 reverse = ( ! srcE1.IsSame( srcE1bis ));
468 else if ( nbEdgesInWires.front() == 1 )
470 // TODO::Compare orientation of curves in a sole edge
471 //RETURN_BAD_RESULT("Not implemented case");
475 RETURN_BAD_RESULT("Bad result from SMESH_Block::GetOrderedEdges()");
478 // --------------------
479 // Perform 2D mapping
480 // --------------------
482 // Compute mesh on a target face
484 mapper.Apply( tgtFace, tgtV1, reverse );
485 if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
486 return error("Can't apply source mesh pattern to the face");
490 const bool toCreatePolygons = false, toCreatePolyedrs = false;
491 mapper.MakeMesh( tgtMesh, toCreatePolygons, toCreatePolyedrs );
492 if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
493 return error("Can't make mesh by source mesh pattern");
495 // it will remove mesh built by pattern mapper on edges and vertices
497 MeshCleaner cleaner( tgtSubMesh );
499 // -------------------------------------------------------------------------
500 // mapper doesn't take care of nodes already existing on edges and vertices,
501 // so we must merge nodes created by it with existing ones
502 // -------------------------------------------------------------------------
504 SMESH_MeshEditor editor( tgtMesh );
505 SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
507 // Make groups of nodes to merge
509 // loop on edge and vertex submeshes of a target face
510 SMESH_subMeshIteratorPtr smIt = tgtSubMesh->getDependsOnIterator(false,false);
511 while ( smIt->more() )
513 SMESH_subMesh* sm = smIt->next();
514 SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
516 // Sort new and old nodes of a submesh separately
518 bool isSeam = helper.IsSeamShape( sm->GetId() );
520 enum { NEW_NODES = 0, OLD_NODES };
521 map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam;
522 map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
523 set< const SMDS_MeshNode* > seamNodes;
525 // mapper puts on a seam edge nodes from 2 edges
526 if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
527 RETURN_BAD_RESULT("getBoundaryNodes() failed");
529 SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
530 while ( nIt->more() )
532 const SMDS_MeshNode* node = nIt->next();
533 bool isOld = isOldNode( node );
535 if ( !isOld && isSeam ) { // new node on a seam edge
536 if ( seamNodes.find( node ) != seamNodes.end())
537 continue; // node is already in the map
540 // sort nodes on edges by its position
541 map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[isOld ? OLD_NODES : NEW_NODES];
542 switch ( node->GetPosition()->GetTypeOfPosition() )
544 case SMDS_TOP_VERTEX: {
545 pos2nodes.insert( make_pair( 0, node ));
548 case SMDS_TOP_EDGE: {
549 const SMDS_EdgePosition* pos =
550 static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
551 pos2nodes.insert( make_pair( pos->GetUParameter(), node ));
555 RETURN_BAD_RESULT("Wrong node position type: "<<
556 node->GetPosition()->GetTypeOfPosition());
559 if ( u2nodesMaps[ NEW_NODES ].size() != u2nodesMaps[ OLD_NODES ].size() )
561 if ( u2nodesMaps[ NEW_NODES ].size() == 0 &&
562 sm->GetSubShape().ShapeType() == TopAbs_EDGE &&
563 BRep_Tool::Degenerated( TopoDS::Edge( sm->GetSubShape() )))
564 // NPAL15894 (tt88bis.py) - project mesh built by NETGEN_1d_2D that
565 // does not make segments/nodes on degenerated edges
567 RETURN_BAD_RESULT("Different nb of old and new nodes on shape #"<< sm->GetId() <<" "<<
568 u2nodesMaps[ OLD_NODES ].size() << " != " <<
569 u2nodesMaps[ NEW_NODES ].size());
571 if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() ) {
572 RETURN_BAD_RESULT("Different nb of old and seam nodes " <<
573 u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size());
575 // Make groups of nodes to merge
576 u_oldNode = u2nodesMaps[ OLD_NODES ].begin();
577 u_newNode = u2nodesMaps[ NEW_NODES ].begin();
578 newEnd = u2nodesMaps[ NEW_NODES ].end();
579 u_newOnSeam = u2nodesOnSeam.begin();
580 for ( ; u_newNode != newEnd; ++u_newNode, ++u_oldNode ) {
581 groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
582 groupsOfNodes.back().push_back( u_oldNode->second );
583 groupsOfNodes.back().push_back( u_newNode->second );
585 groupsOfNodes.back().push_back( (u_newOnSeam++)->second );
591 int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
592 editor.MergeNodes( groupsOfNodes );
593 int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
594 if ( nbFaceBeforeMerge != nbFaceAtferMerge )
595 return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
597 // ---------------------------
598 // Check elements orientation
599 // ---------------------------
601 TopoDS_Face face = tgtFace;
602 if ( !theMesh.IsMainShape( tgtFace ))
604 // find the main shape
605 TopoDS_Shape mainShape = meshDS->ShapeToMesh();
606 switch ( mainShape.ShapeType() ) {
608 case TopAbs_SOLID: break;
610 TopTools_ListIteratorOfListOfShape ancestIt = theMesh.GetAncestors( face );
611 for ( ; ancestIt.More(); ancestIt.Next() ) {
612 TopAbs_ShapeEnum type = ancestIt.Value().ShapeType();
613 if ( type == TopAbs_SOLID ) {
614 mainShape = ancestIt.Value();
616 } else if ( type == TopAbs_SHELL ) {
617 mainShape = ancestIt.Value();
621 // find tgtFace in the main solid or shell to know it's true orientation.
622 TopExp_Explorer exp( mainShape, TopAbs_FACE );
623 for ( ; exp.More(); exp.Next() ) {
624 if ( tgtFace.IsSame( exp.Current() )) {
625 face = TopoDS::Face( exp.Current() );
631 if ( SMESH_Algo::IsReversedSubMesh( face, meshDS ))
633 SMDS_ElemIteratorPtr eIt = meshDS->MeshElements( face )->GetElements();
634 while ( eIt->more() ) {
635 const SMDS_MeshElement* e = eIt->next();
636 if ( e->GetType() == SMDSAbs_Face && !editor.Reorient( e ))
637 RETURN_BAD_RESULT("Pb of SMESH_MeshEditor::Reorient()");
641 cleaner.Release(); // do not remove mesh
646 //=============================================================================
648 * \brief Sets a default event listener to submesh of the source face
649 * \param subMesh - submesh where algo is set
651 * This method is called when a submesh gets HYP_OK algo_state.
652 * After being set, event listener is notified on each event of a submesh.
653 * Arranges that CLEAN event is translated from source submesh to
656 //=============================================================================
658 void StdMeshers_Projection_2D::SetEventListener(SMESH_subMesh* subMesh)
660 TAssocTool::SetEventListener( subMesh,
661 _sourceHypo->GetSourceFace(),
662 _sourceHypo->GetSourceMesh() );