1 // Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 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, or (at your option) any later version.
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
23 // SMESH SMESH : implementation of SMESH idl descriptions
24 // File : StdMeshers_Import_1D.cxx
27 #include "StdMeshers_Import_1D.hxx"
28 #include "StdMeshers_ImportSource.hxx"
30 #include "SMDS_MeshElement.hxx"
31 #include "SMDS_MeshNode.hxx"
32 #include "SMESHDS_Group.hxx"
33 #include "SMESHDS_Mesh.hxx"
34 #include "SMESH_Comment.hxx"
35 #include "SMESH_Gen.hxx"
36 #include "SMESH_Group.hxx"
37 #include "SMESH_HypoFilter.hxx"
38 #include "SMESH_Mesh.hxx"
39 #include "SMESH_MeshEditor.hxx"
40 #include "SMESH_MesherHelper.hxx"
41 #include "SMESH_Octree.hxx"
42 #include "SMESH_subMesh.hxx"
43 #include "SMESH_subMeshEventListener.hxx"
45 #include "Utils_SALOME_Exception.hxx"
46 #include "utilities.h"
48 #include <BRepAdaptor_Curve.hxx>
49 #include <BRep_Builder.hxx>
50 #include <BRep_Tool.hxx>
51 #include <BndLib_Add3dCurve.hxx>
52 #include <GCPnts_TangentialDeflection.hxx>
53 #include <ShapeAnalysis_Curve.hxx>
55 #include <TopExp_Explorer.hxx>
57 #include <TopoDS_Compound.hxx>
58 #include <TopoDS_Edge.hxx>
59 #include <TopoDS_Vertex.hxx>
63 //================================================================================
64 namespace // INTERNAL STUFF
65 //================================================================================
68 * \brief Compute point position on a curve. Use octree to fast reject far points
70 class CurveProjector : public SMESH_Octree
73 CurveProjector( const TopoDS_Edge& edge, double enlarge );
75 bool IsOnCurve( const gp_XYZ& point, double & distance2, double & u );
77 bool IsOut( const gp_XYZ& point ) const { return getBox()->IsOut( point ); }
81 SMESH_Octree* newChild() const { return new CurveProjector; }
82 void buildChildrenData();
83 Bnd_B3d* buildRootBox();
86 struct CurveSegment : public Bnd_B3d
88 double _chord, _chord2, _length2;
89 gp_Pnt _pFirst, _pLast;
91 Handle(Geom_Curve) _curve;
94 void Init( const gp_Pnt& pf, const gp_Pnt& pl,
95 double uf, double ul, double tol, Handle(Geom_Curve)& curve );
96 bool IsOn( const gp_XYZ& point, double & distance2, double & u );
97 bool IsInContact( const Bnd_B3d& bb );
99 std::vector< CurveSegment > _segments;
102 //===============================================================================
104 * \brief Create an octree of curve segments
106 //================================================================================
108 CurveProjector::CurveProjector( const TopoDS_Edge& edge, double enlarge )
112 Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l );
113 double curDeflect = 0.3; // Curvature deflection
114 double angDeflect = 1e+100; // Angular deflection - don't control chordal error
115 GCPnts_TangentialDeflection div( BRepAdaptor_Curve( edge ), angDeflect, curDeflect );
116 _segments.resize( div.NbPoints() - 1 );
117 for ( int i = 1; i < div.NbPoints(); ++i )
119 _segments[ i - 1 ].Init( div.Value( i ), div.Value( i+1 ),
120 div.Parameter( i ), div.Parameter( i+1 ),
123 catch ( Standard_Failure ) {
124 _segments.resize( _segments.size() - 1 );
127 if ( _segments.size() < 3 )
132 if ( _segments.size() == 1 )
133 myBox->Enlarge( enlarge );
136 //================================================================================
138 * \brief Return the maximal box
140 //================================================================================
142 Bnd_B3d* CurveProjector::buildRootBox()
144 Bnd_B3d* box = new Bnd_B3d;
145 for ( size_t i = 0; i < _segments.size(); ++i )
146 box->Add( _segments[i] );
150 //================================================================================
152 * \brief Redistribute segments among children
154 //================================================================================
156 void CurveProjector::buildChildrenData()
159 for ( size_t i = 0; i < _segments.size(); ++i )
161 for (int j = 0; j < 8; j++)
163 if ( _segments[i].IsInContact( *myChildren[j]->getBox() ))
164 ((CurveProjector*)myChildren[j])->_segments.push_back( _segments[i]);
169 if ( allIn && _segments.size() < 3 )
172 for (int j = 0; j < 8; j++)
173 static_cast<CurveProjector*>( myChildren[j])->myIsLeaf = true;
177 SMESHUtils::FreeVector( _segments ); // = _segments.clear() + free memory
179 for (int j = 0; j < 8; j++)
181 CurveProjector* child = static_cast<CurveProjector*>( myChildren[j]);
182 if ( child->_segments.size() < 3 )
183 child->myIsLeaf = true;
188 //================================================================================
190 * \brief Return true if a point is close to the curve
191 * \param [in] point - the point
192 * \param [out] distance2 - distance to the curve
193 * \param [out] u - parameter on the curve
194 * \return bool - is the point is close to the curve
196 //================================================================================
198 bool CurveProjector::IsOnCurve( const gp_XYZ& point, double & distance2, double & u )
200 if ( getBox()->IsOut( point ))
205 distance2 = Precision::Infinite();
209 for ( size_t i = 0; i < _segments.size(); ++i )
210 if ( !_segments[i].IsOut( point ) &&
211 _segments[i].IsOn( point, dist2, param ) &&
222 for (int i = 0; i < 8; i++)
223 if (((CurveProjector*) myChildren[i])->IsOnCurve( point, dist2, param ) &&
234 //================================================================================
238 //================================================================================
240 void CurveProjector::CurveSegment::Init(const gp_Pnt& pf,
245 Handle(Geom_Curve)& curve )
250 _length2 = pf.SquareDistance( pl );
251 _line.SetLocation( pf );
252 _line.SetDirection( gp_Vec( pf, pl ));
253 _chord2 = Max( _line. SquareDistance( curve->Value( uf + 0.25 * ( ul - uf ))),
254 Max( _line.SquareDistance( curve->Value( uf + 0.5 * ( ul - uf ))),
255 _line.SquareDistance( curve->Value( uf + 0.75 * ( ul - uf )))));
256 _chord2 *= ( 1.05 * 1.05 ); // +5%
257 _chord2 = Max( tol, _chord2 );
258 _chord = Sqrt( _chord2 );
261 BndLib_Add3dCurve::Add( GeomAdaptor_Curve( curve, uf, ul ), tol, bb );
262 Add( bb.CornerMin() );
263 Add( bb.CornerMax() );
266 //================================================================================
268 * \brief Return true if a point is close to the curve segment
269 * \param [in] point - the point
270 * \param [out] distance2 - distance to the curve
271 * \param [out] u - parameter on the curve
272 * \return bool - is the point is close to the curve segment
274 //================================================================================
276 bool CurveProjector::CurveSegment::IsOn( const gp_XYZ& point, double & distance2, double & u )
278 distance2 = _line.SquareDistance( point );
279 if ( distance2 > _chord2 )
282 // check if the point projection falls into the segment range
284 gp_Vec edge( _pFirst, _pLast );
285 gp_Vec n1p ( _pFirst, point );
286 u = ( edge * n1p ) / _length2; // param [0,1] on the edge
289 if ( _pFirst.SquareDistance( point ) > _chord2 )
294 if ( _pLast.SquareDistance( point ) > _chord2 )
299 distance2 = ShapeAnalysis_Curve().Project( _curve, point, Precision::Confusion(),
301 distance2 *= distance2;
305 //================================================================================
307 * \brief Check if the segment is in contact with a box
309 //================================================================================
311 bool CurveProjector::CurveSegment::IsInContact( const Bnd_B3d& bb )
313 if ( bb.IsOut( _line.Position(), /*isRay=*/true, _chord ))
316 gp_Ax1 axRev = _line.Position().Reversed();
317 axRev.SetLocation( _pLast );
318 return !bb.IsOut( axRev, /*isRay=*/true, _chord );
321 //================================================================================
322 //================================================================================
324 int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS, SMESH_Mesh* tgtMesh);
326 enum _ListenerDataType
328 WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp
329 LISTEN_SRC_MESH, // data storing submesh depending on source mesh state
330 SRC_HYP // data storing ImportSource hyp
332 //================================================================================
334 * \brief _ListenerData holding ImportSource hyp holding in its turn
337 struct _ListenerData : public SMESH_subMeshEventListenerData
339 const StdMeshers_ImportSource1D* _srcHyp;
340 _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP):
341 SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h)
346 //================================================================================
348 * \brief Comparator of sub-meshes
352 bool operator()(const SMESH_subMesh* sm1, const SMESH_subMesh* sm2 ) const
354 if ( sm1 == sm2 ) return false;
355 if ( !sm1 || !sm2 ) return sm1 < sm2;
356 const TopoDS_Shape& s1 = sm1->GetSubShape();
357 const TopoDS_Shape& s2 = sm2->GetSubShape();
358 TopAbs_ShapeEnum t1 = s1.IsNull() ? TopAbs_SHAPE : s1.ShapeType();
359 TopAbs_ShapeEnum t2 = s2.IsNull() ? TopAbs_SHAPE : s2.ShapeType();
362 return t1 < t2; // to have: face < edge
365 //================================================================================
367 * \brief Container of data dedicated to one source mesh
371 const SMESH_Mesh* _srcMesh;
372 StdMeshers_Import_1D::TNodeNodeMap _n2n;
373 StdMeshers_Import_1D::TElemElemMap _e2e;
375 set< SMESH_subMesh*, _SubLess > _subM; // submeshes relating to this srcMesh
376 set< SMESH_subMesh*, _SubLess > _copyMeshSubM; // submeshes requesting mesh copying
377 set< SMESH_subMesh*, _SubLess > _copyGroupSubM; // submeshes requesting group copying
378 set< SMESH_subMesh*, _SubLess > _computedSubM;
380 SMESHDS_SubMesh* _importMeshSubDS; // submesh storing a copy of _srcMesh
381 int _importMeshSubID; // id of _importMeshSubDS
383 _ImportData(const SMESH_Mesh* srcMesh=0):
384 _srcMesh(srcMesh), _importMeshSubDS(0),_importMeshSubID(-1) {}
386 void removeImportedMesh( SMESHDS_Mesh* meshDS )
388 if ( !_importMeshSubDS ) return;
389 SMDS_ElemIteratorPtr eIt = _importMeshSubDS->GetElements();
390 while ( eIt->more() )
391 meshDS->RemoveFreeElement( eIt->next(), 0, /*fromGroups=*/false );
392 SMDS_NodeIteratorPtr nIt = _importMeshSubDS->GetNodes();
393 while ( nIt->more() )
394 meshDS->RemoveFreeNode( nIt->next(), 0, /*fromGroups=*/false );
395 _importMeshSubDS->Clear();
399 void removeGroups( SMESH_subMesh* subM, const StdMeshers_ImportSource1D* srcHyp )
401 if ( !srcHyp ) return;
402 SMESH_Mesh* tgtMesh = subM->GetFather();
403 const SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
404 const SMESHDS_Mesh* srcMeshDS = _srcMesh->GetMeshDS();
405 vector<SMESH_Group*>* groups =
406 const_cast<StdMeshers_ImportSource1D*>(srcHyp)->GetResultGroups(*srcMeshDS,*tgtMeshDS);
409 for ( unsigned i = 0; i < groups->size(); ++i )
410 tgtMesh->RemoveGroup( groups->at(i)->GetGroupDS()->GetID() );
414 void trackHypParams( SMESH_subMesh* sm, const StdMeshers_ImportSource1D* srcHyp )
416 if ( !srcHyp ) return;
417 bool toCopyMesh, toCopyGroups;
418 srcHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
420 if ( toCopyMesh )_copyMeshSubM.insert( sm );
421 else _copyMeshSubM.erase( sm );
423 if ( toCopyGroups ) _copyGroupSubM.insert( sm );
424 else _copyGroupSubM.erase( sm );
426 void addComputed( SMESH_subMesh* sm )
428 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
429 /*complexShapeFirst=*/true);
430 while ( smIt->more() )
433 switch ( sm->GetSubShape().ShapeType() )
436 if ( SMESH_Algo::isDegenerated( TopoDS::Edge( sm->GetSubShape() )))
441 if ( !sm->IsEmpty() )
442 _computedSubM.insert( sm );
450 //================================================================================
452 * Listener notified on events relating to imported submesh
454 class _Listener : public SMESH_subMeshEventListener
456 typedef map< SMESH_Mesh*, list< _ImportData > > TMesh2ImpData;
457 TMesh2ImpData _tgtMesh2ImportData;
459 _Listener():SMESH_subMeshEventListener(/*isDeletable=*/false,
460 "StdMeshers_Import_1D::_Listener") {}
463 // return pointer to a static listener
464 static _Listener* get() { static _Listener theListener; return &theListener; }
466 static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh);
468 static void storeImportSubmesh(SMESH_subMesh* importSub,
469 const SMESH_Mesh* srcMesh,
470 const StdMeshers_ImportSource1D* srcHyp);
472 virtual void ProcessEvent(const int event,
474 SMESH_subMesh* subMesh,
475 SMESH_subMeshEventListenerData* data,
476 const SMESH_Hypothesis* hyp);
477 void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data );
478 void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub );
479 void clearN2N ( SMESH_Mesh* tgtMesh );
481 // mark sm as missing src hyp with valid groups
482 static void waitHypModification(SMESH_subMesh* sm)
485 (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
488 //--------------------------------------------------------------------------------
490 * \brief Find or create ImportData for given meshes
492 _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh,
495 list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
496 list< _ImportData >::iterator d = dList.begin();
497 for ( ; d != dList.end(); ++d )
498 if ( d->_srcMesh == srcMesh )
500 dList.push_back(_ImportData(srcMesh));
501 return &dList.back();
504 //--------------------------------------------------------------------------------
506 * \brief Remember an imported sub-mesh and set needed even listeners
507 * \param importSub - submesh computed by Import algo
508 * \param srcMesh - source mesh
509 * \param srcHyp - ImportSource hypothesis
511 void _Listener::storeImportSubmesh(SMESH_subMesh* importSub,
512 const SMESH_Mesh* srcMesh,
513 const StdMeshers_ImportSource1D* srcHyp)
515 // set listener to hear events of the submesh computed by "Import" algo
516 importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
518 // set listeners to hear events of the source mesh
519 SMESH_subMesh* smToNotify = importSub;
520 vector<SMESH_subMesh*> smToListen = srcHyp->GetSourceSubMeshes( srcMesh );
521 for ( size_t i = 0; i < smToListen.size(); ++i )
523 SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH);
524 data->mySubMeshes.push_back( smToNotify );
525 importSub->SetEventListener( get(), data, smToListen[i] );
527 // remember the submesh importSub and its sub-submeshes
528 _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
529 iData->trackHypParams( importSub, srcHyp );
530 iData->addComputed( importSub );
531 if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
533 SMESH_Mesh* tgtMesh = importSub->GetFather();
534 iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
535 iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
538 //--------------------------------------------------------------------------------
540 * \brief Remove imported mesh and/or groups if needed
541 * \param sm - submesh losing Import algo
542 * \param data - data holding imported groups
544 void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
546 list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ];
547 list< _ImportData >::iterator d = dList.begin();
548 for ( ; d != dList.end(); ++d )
549 if ( (*d)._subM.erase( sm ))
551 d->_computedSubM.erase( sm );
552 bool rmMesh = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
553 bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
555 d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
556 if ( rmGroups && data && data->myType == SRC_HYP )
557 d->removeGroups( sm, data->_srcHyp );
560 //--------------------------------------------------------------------------------
562 * \brief Clear _ImportData::_n2n.
563 * _n2n is useful within one mesh.Compute() only
565 void _Listener::clearN2N( SMESH_Mesh* tgtMesh )
567 list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
568 list< _ImportData >::iterator d = dList.begin();
569 for ( ; d != dList.end(); ++d )
572 //--------------------------------------------------------------------------------
574 * \brief Clear submeshes and remove imported mesh and/or groups if necessary
575 * \param sm - cleared submesh
576 * \param data - data holding imported groups
578 void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub)
580 list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ];
581 list< _ImportData >::iterator d = dList.begin();
582 for ( ; d != dList.end(); ++d )
584 if ( !d->_subM.count( sm )) continue;
585 if ( (*d)._computedSubM.erase( sm ) )
587 bool copyMesh = !d->_copyMeshSubM.empty();
588 if ( copyMesh || clearAllSub )
590 // remove imported mesh and groups
591 d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
593 if ( data && data->myType == SRC_HYP )
594 d->removeGroups( sm, data->_srcHyp );
596 // clear the rest submeshes
597 if ( !d->_computedSubM.empty() )
599 d->_computedSubM.clear();
600 set< SMESH_subMesh*, _SubLess>::iterator sub = d->_subM.begin();
601 for ( ; sub != d->_subM.end(); ++sub )
603 SMESH_subMesh* subM = *sub;
604 _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
605 if ( hypData && hypData->myType == SRC_HYP )
606 d->removeGroups( sm, hypData->_srcHyp );
608 subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
609 if ( subM->GetSubShape().ShapeType() == TopAbs_FACE )
610 subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
614 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
615 if ( sm->GetSubShape().ShapeType() == TopAbs_FACE )
616 sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
618 if ( data && data->myType == SRC_HYP )
619 d->trackHypParams( sm, data->_srcHyp );
624 //--------------------------------------------------------------------------------
626 * \brief Remove imported mesh and/or groups
628 void _Listener::ProcessEvent(const int event,
630 SMESH_subMesh* subMesh,
631 SMESH_subMeshEventListenerData* data,
632 const SMESH_Hypothesis* /*hyp*/)
634 if ( data && data->myType == WAIT_HYP_MODIF )
636 // event of Import submesh
637 if ( SMESH_subMesh::MODIF_HYP == event &&
638 SMESH_subMesh::ALGO_EVENT == eventType )
640 // re-call SetEventListener() to take into account valid parameters
641 // of ImportSource hypothesis
642 if ( SMESH_Algo* algo = subMesh->GetAlgo() )
643 algo->SetEventListener( subMesh );
646 else if ( data && data->myType == LISTEN_SRC_MESH )
648 // event of source mesh
649 if ( SMESH_subMesh::COMPUTE_EVENT == eventType )
652 case SMESH_subMesh::CLEAN:
653 // source mesh cleaned -> clean target mesh
654 clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true );
656 case SMESH_subMesh::SUBMESH_COMPUTED: {
657 // source mesh computed -> reset FAILED state of Import submeshes to
659 SMESH_Mesh* srcMesh = subMesh->GetFather();
660 if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 )
662 SMESH_Mesh* m = data->mySubMeshes.front()->GetFather();
663 if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1))
665 sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED );
666 sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
674 if ( !data->mySubMeshes.empty() )
675 clearN2N( data->mySubMeshes.front()->GetFather() );
677 else // event of Import submesh
679 // find out what happens: import hyp modified or removed
680 bool removeImport = false, modifHyp = false;
681 if ( SMESH_subMesh::ALGO_EVENT == eventType )
683 if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK )
687 else if (( SMESH_subMesh::REMOVE_ALGO == event ||
688 SMESH_subMesh::REMOVE_FATHER_ALGO == event ) &&
689 SMESH_subMesh::ALGO_EVENT == eventType )
691 SMESH_Algo* algo = subMesh->GetAlgo();
692 removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 );
697 // treat removal of Import algo from subMesh
698 removeSubmesh( subMesh, (_ListenerData*) data );
700 else if ( modifHyp ||
701 ( SMESH_subMesh::CLEAN == event &&
702 SMESH_subMesh::COMPUTE_EVENT == eventType))
704 // treat modification of ImportSource hypothesis
705 clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false );
707 else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
708 SMESH_subMesh::COMPUTE_EVENT == eventType )
710 // check compute state of all submeshes impoting from same src mesh;
711 // this is to take into account 1D computed submeshes hidden by 2D import algo;
712 // else source mesh is not copied as _subM.size != _computedSubM.size()
713 list< _ImportData > & dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
714 list< _ImportData >::iterator d = dList.begin();
715 for ( ; d != dList.end(); ++d )
716 if ( d->_subM.count( subMesh ))
718 set<SMESH_subMesh*,_SubLess>::iterator smIt = d->_subM.begin();
719 for( ; smIt != d->_subM.end(); ++smIt )
720 if ( (*smIt)->IsMeshComputed() )
721 d->_computedSubM.insert( *smIt);
724 // Clear _ImportData::_n2n if it isn't useful anymore, i.e. when
725 // the event is not within mesh.Compute()
726 if ( SMESH_subMesh::ALGO_EVENT == eventType )
727 clearN2N( subMesh->GetFather() );
731 //================================================================================
733 * \brief Return an ID of submesh to store nodes and elements of a copied mesh
735 //================================================================================
737 int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
740 // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
741 // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
742 // And this shape must be different from sub-shapes of the main shape.
743 // So we create a compound containing
744 // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
745 // srcMeshDS->GetPersistentId()
746 // 2) the 1-st vertex of the main shape to assure
747 // SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
748 TopoDS_Shape shapeForSrcMesh;
749 TopTools_IndexedMapOfShape pseudoSubShapes;
750 TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
752 // index of pseudoSubShapes corresponding to srcMeshDS
753 int subIndex = 1 + srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
754 int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
756 // try to find already present shapeForSrcMesh
757 SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
758 for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
760 const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
761 if ( s.ShapeType() != TopAbs_COMPOUND ) break;
762 TopoDS_Iterator sSubIt( s );
763 for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
764 if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
765 if ( iSub+1 == nbSubShapes )
771 if ( shapeForSrcMesh.IsNull() )
773 // make a new shapeForSrcMesh
774 BRep_Builder aBuilder;
775 TopoDS_Compound comp;
776 aBuilder.MakeCompound( comp );
777 shapeForSrcMesh = comp;
778 for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
779 if ( subIndex+iSub <= pseudoSubShapes.Extent() )
780 aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
781 TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
782 aBuilder.Add( comp, vExp.Current() );
784 SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
785 SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
787 smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
789 // make ordinary submesh from a complex one
790 if ( smDS->IsComplexSubmesh() )
792 list< const SMESHDS_SubMesh* > subSM;
793 SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
794 while ( smIt->more() ) subSM.push_back( smIt->next() );
795 list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
796 for ( ; sub != subSM.end(); ++sub)
797 smDS->RemoveSubMesh( *sub );
802 //================================================================================
804 * \brief Return a submesh to store nodes and elements of a copied mesh
805 * and set event listeners in order to clear
806 * imported mesh and groups as soon as submesh state requires it
808 //================================================================================
810 SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh* srcMesh,
812 const TopoDS_Shape& tgtShape,
813 StdMeshers_Import_1D::TNodeNodeMap*& n2n,
814 StdMeshers_Import_1D::TElemElemMap*& e2e,
817 StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
819 _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
821 SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
822 iData->addComputed( importedSM );
823 if ( iData->_computedSubM.size() != iData->_subM.size() )
824 return 0; // not all submeshes computed yet
826 toCopyGroups = !iData->_copyGroupSubM.empty();
828 if ( !iData->_copyMeshSubM.empty())
830 // make submesh to store a copied mesh
831 int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
832 SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
834 iData->_importMeshSubID = smID;
835 iData->_importMeshSubDS = subDS;
841 //================================================================================
843 * \brief Return minimal square length of edges of 1D and 2D elements sharing the node
845 //================================================================================
847 double getMinEdgeLength2( const SMDS_MeshNode* n )
850 double minLen2 = Precision::Infinite();
851 for ( SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator(); eIt->more(); )
853 const SMDS_MeshElement* e = eIt->next();
854 const SMDSAbs_ElementType type = e->GetType();
855 if ( type != SMDSAbs_Edge && type != SMDSAbs_Face )
857 int i = e->GetNodeIndex( n );
858 int iNext = SMESH_MesherHelper::WrapIndex( i + 1, e->NbCornerNodes() );
859 minLen2 = Min( minLen2, p.SquareDistance( e->GetNode( iNext )));
860 if ( type != SMDSAbs_Face )
862 int iPrev = SMESH_MesherHelper::WrapIndex( i - 1, e->NbCornerNodes() );
863 minLen2 = Min( minLen2, p.SquareDistance( e->GetNode( iPrev )));
870 //=============================================================================
872 * Creates StdMeshers_Import_1D
874 //=============================================================================
876 StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, SMESH_Gen * gen)
877 :SMESH_1D_Algo(hypId, gen), _sourceHyp(0)
880 _shapeType = (1 << TopAbs_EDGE);
882 _compatibleHypothesis.push_back("ImportSource1D");
885 //=============================================================================
887 * Check presence of a hypothesis
889 //=============================================================================
891 bool StdMeshers_Import_1D::CheckHypothesis
893 const TopoDS_Shape& aShape,
894 SMESH_Hypothesis::Hypothesis_Status& aStatus)
898 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
899 if ( hyps.size() == 0 )
901 aStatus = SMESH_Hypothesis::HYP_MISSING;
902 return false; // can't work with no hypothesis
905 if ( hyps.size() > 1 )
907 aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
911 const SMESHDS_Hypothesis *theHyp = hyps.front();
913 string hypName = theHyp->GetName();
915 if (hypName == _compatibleHypothesis.front())
917 _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
918 aStatus = _sourceHyp->GetGroups().empty() ? HYP_BAD_PARAMETER : HYP_OK;
919 if ( aStatus == HYP_BAD_PARAMETER )
920 _Listener::waitHypModification( aMesh.GetSubMesh( aShape ));
921 return aStatus == HYP_OK;
924 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
928 //=============================================================================
930 * Import elements from the other mesh
932 //=============================================================================
934 bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
936 if ( !_sourceHyp ) return false;
938 //MESSAGE("---------> StdMeshers_Import_1D::Compute");
939 const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups(/*loaded=*/true);
940 if ( srcGroups.empty() )
941 return error("Invalid source groups");
943 SMESH_MesherHelper helper(theMesh);
944 helper.SetSubShape(theShape);
945 SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
947 const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
948 const double edgeTol = helper.MaxTolerance( geomEdge );
949 const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
952 double geomTol = Precision::Confusion();
953 for ( size_t iG = 0; iG < srcGroups.size(); ++iG )
955 const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
956 for ( SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements(); srcElems->more(); )
958 const SMDS_MeshElement* edge = srcElems->next();
959 geomTol = Sqrt( 0.5 * ( getMinEdgeLength2( edge->GetNode(0) ) +
960 getMinEdgeLength2( edge->GetNode(1) ))) / 25;
961 iG = srcGroups.size();
965 CurveProjector curveProjector( geomEdge, geomTol );
967 // get nodes on vertices
969 list < SMESH_TNodeXYZ > vertexNodes;
970 list < SMESH_TNodeXYZ >::iterator vNIt;
971 TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
972 for ( ; vExp.More(); vExp.Next() )
974 const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
975 if ( !vertexIDs.insert( tgtMesh->ShapeToIndex( v )).second )
976 continue; // closed edge
977 const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
980 _gen->Compute(theMesh,v,/*anUpward=*/true);
981 n = SMESH_Algo::VertexNode( v, tgtMesh );
982 //MESSAGE("_gen->Compute " << n);
983 if ( !n ) return false; // very strange
985 vertexNodes.push_back( SMESH_TNodeXYZ( n ));
986 //MESSAGE("SMESH_Algo::VertexNode " << n->GetID() << " " << n->X() << " " << n->Y() << " " << n->Z() );
989 // import edges from groups
992 for ( size_t iG = 0; iG < srcGroups.size(); ++iG )
994 const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
996 const int meshID = srcGroup->GetMesh()->GetPersistentId();
997 const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
998 if ( !srcMesh ) continue;
999 getMaps( srcMesh, &theMesh, n2n, e2e );
1001 SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
1002 vector<const SMDS_MeshNode*> newNodes;
1003 while ( srcElems->more() ) // loop on group contents
1005 const SMDS_MeshElement* edge = srcElems->next();
1006 gp_XYZ middle = 0.5 * ( SMESH_NodeXYZ( edge->GetNode(0)) +
1007 SMESH_NodeXYZ( edge->GetNode(1)));
1008 if ( curveProjector.IsOut( middle ))
1011 // find or create nodes of a new edge
1012 newNodes.resize( edge->NbNodes() );
1013 newNodes.back() = 0;
1014 int nbNodesOnVertex = 0;
1015 SMDS_MeshElement::iterator node = edge->begin_nodes();
1016 for ( size_t i = 0; i < newNodes.size(); ++i, ++node )
1018 TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, nullptr )).first;
1019 if ( n2nIt->second )
1021 int sId = n2nIt->second->getshapeId();
1022 if ( sId != shapeID )
1024 if ( vertexIDs.count( sId ))
1030 else if ( !vertexNodes.empty() )
1032 // find an existing vertex node
1033 double checktol = max(1.E-10, 10*edgeTol*edgeTol);
1034 for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
1035 if ( vNIt->SquareDistance( *node ) < checktol)
1037 (*n2nIt).second = vNIt->_node;
1038 vertexNodes.erase( vNIt );
1043 if ( !n2nIt->second )
1045 // find out if the node lies on theShape
1046 SMESH_NodeXYZ xyz = *node;
1048 if ( curveProjector.IsOnCurve( xyz, dist2, u ))
1050 // tolerance relative to the length of surrounding edges
1051 double mytol2 = getMinEdgeLength2( *node ) / 25 / 25;
1052 if ( dist2 < mytol2 )
1054 SMDS_MeshNode* newNode = tgtMesh->AddNode( xyz.X(), xyz.Y(), xyz.Z() );
1055 n2nIt->second = newNode;
1056 tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
1060 if ( !(newNodes[i] = n2nIt->second ))
1063 if ( !newNodes.back() )
1065 //MESSAGE("not all nodes of edge lie on theShape");
1066 continue; // not all nodes of edge lie on theShape
1070 SMDS_MeshElement * newEdge;
1071 if ( newNodes.size() == 3 )
1072 newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
1074 newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
1075 tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
1076 e2e->insert( make_pair( edge, newEdge ));
1078 if ( nbNodesOnVertex >= 2 ) // EDGE is meshed by a sole segment
1080 iG = srcGroups.size(); // stop looingp on groups
1083 } // loop on group contents
1087 return error("Source groups are empty or mismatching geometry");
1089 // check if the whole geom edge is covered by imported segments;
1090 // the check consist in passing by segments from one vetrex node to another
1091 bool isEdgeMeshed = false;
1092 if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
1094 const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
1095 const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
1096 const SMDS_MeshElement* seg = 0;
1097 SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
1098 while ( segIt->more() && !seg )
1099 if ( !tgtSM->Contains( seg = segIt->next()))
1101 int nbPassedSegs = 0;
1105 const SMDS_MeshNode* n2 = seg->GetNode(0);
1106 n = ( n2 == n ? seg->GetNode(1) : n2 );
1107 if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
1109 const SMDS_MeshElement* seg2 = 0;
1110 segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
1111 while ( segIt->more() && !seg2 )
1112 if ( seg == ( seg2 = segIt->next()))
1116 if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
1117 return error( "Source elements overlap one another");
1119 isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
1120 n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
1122 if ( !isEdgeMeshed )
1123 return error( "Source elements don't cover totally the geometrical edge" );
1126 vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
1127 for ( size_t i = 0; i < srcMeshes.size(); ++i )
1128 importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
1133 //================================================================================
1135 * \brief Copy mesh and groups
1137 //================================================================================
1139 void StdMeshers_Import_1D::importMesh(const SMESH_Mesh* srcMesh,
1140 SMESH_Mesh & tgtMesh,
1141 StdMeshers_ImportSource1D* srcHyp,
1142 const TopoDS_Shape& tgtShape)
1144 // get submesh to store the imported mesh
1148 SMESHDS_SubMesh* tgtSubMesh =
1149 getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
1150 if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
1151 return; // not to copy srcMeshDS twice
1153 SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
1154 SMESH_MeshEditor additor( &tgtMesh );
1158 SMESH_MeshEditor::ElemFeatures elemType;
1159 vector<const SMDS_MeshNode*> newNodes;
1160 const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
1161 SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
1162 while ( eIt->more() )
1164 const SMDS_MeshElement* elem = eIt->next();
1165 TElemElemMap::iterator e2eIt = e2e->insert( make_pair( elem, (SMDS_MeshElement*)0 )).first;
1166 if ( e2eIt->second ) continue; // already copied by Compute()
1167 newNodes.resize( elem->NbNodes() );
1168 SMDS_MeshElement::iterator node = elem->begin_nodes();
1169 for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
1171 TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
1172 if ( !n2nIt->second )
1174 (*n2nIt).second = tgtMeshDS->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
1175 tgtSubMesh->AddNode( n2nIt->second );
1177 newNodes[i] = n2nIt->second;
1179 const SMDS_MeshElement* newElem =
1180 tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
1183 newElem = additor.AddElement( newNodes, elemType.Init( elem, /*basicOnly=*/false ));
1184 tgtSubMesh->AddElement( newElem );
1187 (*e2eIt).second = newElem;
1190 if ( srcMeshDS->NbNodes() > (int) n2n->size() )
1192 SMDS_NodeIteratorPtr nIt = srcMeshDS->nodesIterator();
1193 while( nIt->more() )
1195 const SMDS_MeshNode* node = nIt->next();
1196 if ( node->NbInverseElements() == 0 )
1198 const SMDS_MeshNode* newNode = tgtMeshDS->AddNode( node->X(), node->Y(), node->Z());
1199 n2n->insert( make_pair( node, newNode ));
1200 tgtSubMesh->AddNode( newNode );
1207 vector<SMESH_Group*> resultGroups;
1210 // collect names of existing groups to assure uniqueness of group names within a type
1211 map< SMDSAbs_ElementType, set<string> > namesByType;
1212 SMESH_Mesh::GroupIteratorPtr groupIt = tgtMesh.GetGroups();
1213 while ( groupIt->more() )
1215 SMESH_Group* tgtGroup = groupIt->next();
1216 namesByType[ tgtGroup->GetGroupDS()->GetType() ].insert( tgtGroup->GetName() );
1220 SMESH_Mesh::GroupIteratorPtr groupIt = srcMesh->GetGroups();
1221 while ( groupIt->more() )
1223 SMESH_Group* srcGroup = groupIt->next();
1224 SMESHDS_GroupBase* srcGroupDS = srcGroup->GetGroupDS();
1225 string name = srcGroup->GetName();
1227 while ( !namesByType[ srcGroupDS->GetType() ].insert( name ).second )
1228 name = SMESH_Comment(srcGroup->GetName()) << "_imported_" << nb++;
1229 SMESH_Group* newGroup = tgtMesh.AddGroup( srcGroupDS->GetType(), name.c_str() );
1230 SMESHDS_Group* newGroupDS = (SMESHDS_Group*)newGroup->GetGroupDS();
1231 resultGroups.push_back( newGroup );
1233 eIt = srcGroupDS->GetElements();
1234 if ( srcGroupDS->GetType() == SMDSAbs_Node )
1237 TNodeNodeMap::iterator n2nIt = n2n->find((const SMDS_MeshNode*) eIt->next() );
1238 if ( n2nIt != n2n->end() && n2nIt->second )
1239 newGroupDS->SMDSGroup().Add((*n2nIt).second );
1244 TElemElemMap::iterator e2eIt = e2e->find( eIt->next() );
1245 if ( e2eIt != e2e->end() && e2eIt->second )
1246 newGroupDS->SMDSGroup().Add((*e2eIt).second );
1254 // Remember created groups in order to remove them as soon as the srcHyp is
1255 // modified or something other similar happens. This imformation must be persistent,
1256 // for that store them in a hypothesis as it stores its values in the file anyway
1257 srcHyp->StoreResultGroups( resultGroups, *srcMeshDS, *tgtMeshDS );
1260 //=============================================================================
1262 * \brief Set needed event listeners and create a submesh for a copied mesh
1264 * This method is called only if a submesh has HYP_OK algo_state.
1266 //=============================================================================
1268 void StdMeshers_Import_1D::setEventListener(SMESH_subMesh* subMesh,
1269 StdMeshers_ImportSource1D* sourceHyp)
1273 vector<SMESH_Mesh*> srcMeshes = sourceHyp->GetSourceMeshes();
1274 if ( srcMeshes.empty() )
1275 _Listener::waitHypModification( subMesh );
1276 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
1277 // set a listener to remove the imported mesh and groups
1278 _Listener::storeImportSubmesh( subMesh, srcMeshes[i], sourceHyp );
1281 void StdMeshers_Import_1D::SetEventListener(SMESH_subMesh* subMesh)
1285 const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
1286 SMESH_Mesh* tgtMesh = subMesh->GetFather();
1287 Hypothesis_Status aStatus;
1288 CheckHypothesis( *tgtMesh, tgtShape, aStatus );
1290 setEventListener( subMesh, _sourceHyp );
1293 void StdMeshers_Import_1D::SubmeshRestored(SMESH_subMesh* subMesh)
1295 SetEventListener(subMesh);
1298 //=============================================================================
1300 * Predict nb of mesh entities created by Compute()
1302 //=============================================================================
1304 bool StdMeshers_Import_1D::Evaluate(SMESH_Mesh & theMesh,
1305 const TopoDS_Shape & theShape,
1306 MapShapeNbElems& aResMap)
1308 if ( !_sourceHyp ) return false;
1310 const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
1311 if ( srcGroups.empty() )
1312 return error("Invalid source groups");
1314 vector<smIdType> aVec(SMDSEntity_Last,0);
1316 bool toCopyMesh, toCopyGroups;
1317 _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
1318 if ( toCopyMesh ) // the whole mesh is copied
1320 vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
1321 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
1323 SMESH_subMesh* sm = getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
1324 if ( !sm || aResMap.count( sm )) continue; // already counted
1325 aVec.assign( SMDSEntity_Last, 0);
1326 const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
1327 for (int i = 0; i < SMDSEntity_Last; i++)
1328 aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
1333 SMESH_MesherHelper helper(theMesh);
1335 const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
1336 const double edgeTol = helper.MaxTolerance( geomEdge );
1338 // take into account nodes on vertices
1339 TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
1340 for ( ; vExp.More(); vExp.Next() )
1341 theMesh.GetSubMesh( vExp.Current())->Evaluate( aResMap );
1343 // count edges imported from groups
1344 int nbEdges = 0, nbQuadEdges = 0;
1345 for ( size_t iG = 0; iG < srcGroups.size(); ++iG )
1347 const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
1348 SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
1349 SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
1350 while ( srcElems->more() ) // loop on group contents
1352 const SMDS_MeshElement* edge = srcElems->next();
1353 // find out if edge is located on geomEdge by projecting
1354 // a middle of edge to geomEdge
1355 SMESH_TNodeXYZ p1( edge->GetNode(0));
1356 SMESH_TNodeXYZ p2( edge->GetNode(1));
1357 gp_XYZ middle = ( p1 + p2 ) / 2.;
1358 tmpNode->setXYZ( middle.X(), middle.Y(), middle.Z());
1360 if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
1361 ++( edge->IsQuadratic() ? nbQuadEdges : nbEdges);
1363 helper.GetMeshDS()->RemoveNode(tmpNode);
1366 int nbNodes = nbEdges + 2 * nbQuadEdges - 1;
1368 aVec[SMDSEntity_Node ] = nbNodes;
1369 aVec[SMDSEntity_Edge ] = nbEdges;
1370 aVec[SMDSEntity_Quad_Edge] = nbQuadEdges;
1373 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
1374 aResMap.insert( make_pair( sm, aVec ));
1379 //================================================================================
1381 * \brief Return node-node and element-element maps for import of geiven source mesh
1383 //================================================================================
1385 void StdMeshers_Import_1D::getMaps(const SMESH_Mesh* srcMesh,
1386 SMESH_Mesh* tgtMesh,
1390 _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
1393 if ( iData->_copyMeshSubM.empty() )
1395 // n2n->clear(); -- for sharing nodes on EDGEs
1400 //================================================================================
1402 * \brief Return submesh corresponding to the copied mesh
1404 //================================================================================
1406 SMESH_subMesh* StdMeshers_Import_1D::getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
1407 SMESH_Mesh& srcMesh )
1409 _ImportData* iData = _Listener::getImportData(&srcMesh,&tgtMesh);
1410 if ( iData->_copyMeshSubM.empty() ) return 0;
1411 SMESH_subMesh* sm = tgtMesh.GetSubMeshContaining( iData->_importMeshSubID );