1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 CEA
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : StdMeshers_Propagation.cxx
27 #include "StdMeshers_Propagation.hxx"
29 #include "utilities.h"
31 #include "SMESH_Mesh.hxx"
32 #include "SMESH_subMesh.hxx"
33 #include "SMESH_HypoFilter.hxx"
34 #include "SMDS_SetIterator.hxx"
40 // =======================================================================
42 * \brief Listener managing propagation of 1D hypotheses
44 // =======================================================================
46 class PropagationMgr: public SMESH_subMeshEventListener
49 static PropagationMgr* GetListener();
51 * \brief Set listener on edge submesh
53 static void Set(SMESH_subMesh * submesh);
55 * \brief Return an edge from which hypotheses are propagated from
57 static TopoDS_Edge GetSource(SMESH_subMesh * submesh) { return TopoDS_Edge(); };
59 * \brief Does it's main job
61 void ProcessEvent(const int event,
63 SMESH_subMesh* subMesh,
64 SMESH_subMeshEventListenerData* data,
65 const SMESH_Hypothesis* hyp = 0);
71 //=============================================================================
73 * StdMeshers_Propagation Implementation
75 //=============================================================================
77 StdMeshers_Propagation::StdMeshers_Propagation (int hypId, int studyId, SMESH_Gen * gen)
78 : SMESH_Hypothesis(hypId, studyId, gen)
81 _param_algo_dim = -1; // 1D auxiliary
83 StdMeshers_Propagation::~StdMeshers_Propagation() {}
84 string StdMeshers_Propagation::GetName () { return "Propagation"; }
85 ostream & StdMeshers_Propagation::SaveTo (ostream & save) { return save; }
86 istream & StdMeshers_Propagation::LoadFrom (istream & load) { return load; }
87 ostream & operator << (ostream & save, StdMeshers_Propagation & hyp) { return hyp.SaveTo(save); }
88 istream & operator >> (istream & load, StdMeshers_Propagation & hyp) { return hyp.LoadFrom(load); }
89 bool StdMeshers_Propagation::SetParametersByMesh(const SMESH_Mesh*,
90 const TopoDS_Shape& ) { return false; }
91 void StdMeshers_Propagation::SetPropagationMgr(SMESH_subMesh* subMesh) { PropagationMgr::Set( subMesh ); }
93 * \brief Return an edge from which hypotheses are propagated from
95 TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh& theMesh,
96 const TopoDS_Shape& theEdge)
98 return PropagationMgr::GetSource(theMesh.GetSubMeshContaining( theEdge ));
101 //=============================================================================
102 //=============================================================================
103 // PROPAGATION MANAGEMENT
104 //=============================================================================
105 //=============================================================================
109 enum SubMeshState { WAIT_PROPAG_HYP, // no propagation hyp in chain
110 HAS_PROPAG_HYP, // propag hyp on this submesh
111 IN_CHAIN, // submesh is in propagation chain
112 LAST_IN_CHAIN, // submesh with local 1D hyp breaking a chain
113 MEANINGLESS_LAST }; // meaningless
115 struct PropagationMgrData : public EventListenerData
117 bool myForward; //!< true if a curve of edge in chain is codirected with one of source edge
118 PropagationMgrData( SubMeshState state ): EventListenerData(true) {
121 SubMeshState State() const {
122 return (SubMeshState) myType;
124 void SetSource(SMESH_subMesh* sm ) {
125 mySubMeshes.clear(); if ( sm ) mySubMeshes.push_back( sm );
127 void SetChain(list< SMESH_subMesh* >& chain ) {
128 mySubMeshes.clear(); mySubMeshes.splice( mySubMeshes.end(), chain );
130 SMESH_subMeshIteratorPtr GetChain() const;
131 SMESH_subMesh* GetSource() const;
134 //=============================================================================
136 * \brief return filter to find Propagation hypothesis
138 SMESH_HypoFilter & propagHypFilter()
140 static SMESH_HypoFilter propagHypFilter
141 ( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ()));
142 return propagHypFilter;
144 //=============================================================================
146 * \brief return static PropagationMgr
148 PropagationMgr* PropagationMgr::GetListener()
150 static PropagationMgr theListener;
153 PropagationMgr* getListener()
155 return PropagationMgr::GetListener();
157 //=============================================================================
159 * \brief return PropagationMgrData
161 PropagationMgrData* getData(SMESH_subMesh* sm)
164 return static_cast< PropagationMgrData* >( sm->GetEventListenerData( getListener() ));
167 //=============================================================================
169 * \brief return PropagationMgrData
171 PropagationMgrData* getData(SMESH_Mesh& theMesh, const TopoDS_Shape& theEdge)
173 if ( theEdge.ShapeType() == TopAbs_EDGE )
174 return getData( theMesh.GetSubMeshContaining( theEdge ) );
177 //================================================================================
179 * \brief Return an iterator on a chain
181 SMESH_subMeshIteratorPtr PropagationMgrData::GetChain() const
183 typedef SMESH_subMesh* TsubMesh;
184 typedef SMDS_SetIterator< TsubMesh, list< TsubMesh >::const_iterator > TIterator;
187 return SMESH_subMeshIteratorPtr
188 ( new TIterator( mySubMeshes.begin(), mySubMeshes.end() ));
191 if ( mySubMeshes.empty() ) break;
192 return getData( mySubMeshes.front() )->GetChain();
195 return SMESH_subMeshIteratorPtr
196 ( new TIterator( mySubMeshes.end(), mySubMeshes.end() ));
198 //================================================================================
200 * \brief Return a propagation source submesh
202 SMESH_subMesh* PropagationMgrData::GetSource() const
204 if ( myType == IN_CHAIN || myType == LAST_IN_CHAIN )
205 if ( !mySubMeshes.empty() )
206 return mySubMeshes.front();
209 //=============================================================================
211 * \brief Returns a local 1D hypothesis used for theEdge
213 const SMESH_Hypothesis* isLocal1DHypothesis (SMESH_Mesh& theMesh,
214 const TopoDS_Shape& theEdge)
216 static SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 ));
217 hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( theMesh.GetMeshDS()->ShapeToMesh() ));
219 return theMesh.GetHypothesis( theEdge, hypo, true );
221 //================================================================================
223 * \brief Build propagation chain
224 * \param theMainSubMesh - the submesh with Propagation hypothesis
226 bool buildPropagationChain ( SMESH_subMesh* theMainSubMesh )
228 // const TopoDS_Shape& theMainEdge = theMainSubMesh->GetSubShape();
229 // if (theMainEdge.ShapeType() != TopAbs_EDGE) return true;
231 // SMESH_Mesh* mesh = theMainSubMesh->GetFather();
233 // EventListenerData* chainData = new PropagationMgrData(HAS_PROPAG_HYP);
234 // theMainSubMesh->SetEventListener( getListener(), chainData, theMainSubMesh );
236 // // Edges submeshes, on which the 1D hypothesis will be propagated from <theMainEdge>
237 // list<SMESH_subMesh*> & chain = chainData->mySubMeshes;
239 // // List of edges, added to chain on the previous cycle pass
240 // TopTools_ListOfShape listPrevEdges;
241 // listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD ));
243 // // 4____3____2____3____4____5
244 // // | | | | | | Number in the each knot of
245 // // | | | | | | grid indicates cycle pass,
246 // // 3____2____1____2____3____4 on which corresponding edge
247 // // | | | | | | (perpendicular to the plane
248 // // | | | | | | of view) will be found.
249 // // 2____1____0____1____2____3
252 // // 3____2____1____2____3____4
254 // // Collect all edges pass by pass
255 // while (listPrevEdges.Extent() > 0) {
256 // // List of edges, added to chain on this cycle pass
257 // TopTools_ListOfShape listCurEdges;
259 // // Find the next portion of edges
260 // TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
261 // for (; itE.More(); itE.Next()) {
262 // TopoDS_Shape anE = itE.Value();
264 // // Iterate on faces, having edge <anE>
265 // TopTools_ListIteratorOfListOfShape itA (mesh->GetAncestors(anE));
266 // for (; itA.More(); itA.Next()) {
267 // TopoDS_Shape aW = itA.Value();
269 // // There are objects of different type among the ancestors of edge
270 // if (aW.ShapeType() == TopAbs_WIRE) {
271 // TopoDS_Shape anOppE;
273 // BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
274 // Standard_Integer nb = 1, found = 0;
275 // TopTools_Array1OfShape anEdges (1,4);
276 // for (; aWE.More(); aWE.Next(), nb++) {
281 // anEdges(nb) = aWE.Current();
282 // if (!_mapAncestors.Contains(anEdges(nb))) {
283 // MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!");
286 // if (anEdges(nb).IsSame(anE)) found = nb;
289 // if (nb == 5 && found > 0) {
290 // // Quadrangle face found, get an opposite edge
291 // Standard_Integer opp = ( found + 2 ) % 4;
292 // anOppE = anEdges(opp);
294 // // add anOppE to aChain if ...
295 // PropagationMgrData* data = getData( *mesh, anOppE );
296 // if ( !data || data->State() == WAIT_PROPAG_HYP ) { // ... anOppE is not in any chain
297 // if ( !isLocal1DHypothesis( *mesh, anOppE )) { // ... no other 1d hyp on anOppE
298 // // Add found edge to the chain oriented so that to
299 // // have it co-directed with a forward MainEdge
300 // TopAbs_Orientation ori = anE.Orientation();
301 // if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
302 // ori = TopAbs::Reverse( ori );
303 // anOppE.Orientation( ori );
304 // aChain.Add(anOppE);
305 // listCurEdges.Append(anOppE);
309 // MESSAGE("Error: Collision between propagated hypotheses");
310 // CleanMeshOnPropagationChain(theMainEdge);
312 // return ( aMainHyp == isLocal1DHypothesis(aMainEdgeForOppEdge) );
316 // } // if (nb == 5 && found > 0)
317 // } // if (aF.ShapeType() == TopAbs_WIRE)
318 // } // for (; itF.More(); itF.Next())
319 // } // for (; itE.More(); itE.Next())
321 // listPrevEdges = listCurEdges;
322 // } // while (listPrevEdges.Extent() > 0)
324 // CleanMeshOnPropagationChain(theMainEdge);
327 //================================================================================
329 * \brief Clear propagation chain
331 //================================================================================
333 bool clearPropagationChain( SMESH_subMesh* subMesh )
335 if ( PropagationMgrData* data = getData( subMesh )) {
336 if ( data->State() == IN_CHAIN )
337 return clearPropagationChain( data->GetSource() );
344 //================================================================================
348 PropagationMgr::PropagationMgr()
349 : SMESH_subMeshEventListener( false ) // won't be deleted by submesh
351 //================================================================================
353 * \brief Set PropagationMgr on a submesh
355 void PropagationMgr::Set(SMESH_subMesh * submesh)
357 EventListenerData* data = EventListenerData::MakeData(submesh,WAIT_PROPAG_HYP);
359 submesh->SetEventListener( getListener(), data, submesh );
361 const SMESH_Hypothesis * propagHyp =
362 submesh->GetFather()->GetHypothesis( submesh->GetSubShape(), propagHypFilter(), true );
364 getListener()->ProcessEvent( SMESH_subMesh::ADD_HYP,
365 SMESH_subMesh::ALGO_EVENT,
371 //================================================================================
373 * \brief React on events on 1D submeshes
375 //================================================================================
377 void PropagationMgr::ProcessEvent(const int event,
379 SMESH_subMesh* subMesh,
380 SMESH_subMeshEventListenerData* data,
381 const SMESH_Hypothesis* hyp)
385 if ( !hyp || hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO || hyp->GetDim() != 1 )
387 if ( eventType != SMESH_subMesh::ALGO_EVENT )
390 bool isPropagHyp = ( StdMeshers_Propagation::GetName() != hyp->GetName() );
392 switch ( data->myType ) {
394 case WAIT_PROPAG_HYP: { // no propagation hyp in chain
395 // --------------------------------------------------------
398 if ( !isLocal1DHypothesis( *subMesh->GetFather(), subMesh->GetSubShape()))
400 if ( event == SMESH_subMesh::ADD_HYP ||
401 event == SMESH_subMesh::ADD_FATHER_HYP ) // add propagation hyp
403 // build propagation chain
404 clearPropagationChain( subMesh );
405 buildPropagationChain( subMesh );
409 case HAS_PROPAG_HYP: { // propag hyp on this submesh
410 // --------------------------------------------------------
412 case SMESH_subMesh::REMOVE_HYP:
413 case SMESH_subMesh::REMOVE_FATHER_HYP: // remove propagation hyp
416 // clear propagation chain
419 case SMESH_subMesh::MODIF_HYP: // hyp modif
420 // clear mesh in a chain
425 case IN_CHAIN: { // submesh is in propagation chain
426 // --------------------------------------------------------
427 if ( event == SMESH_subMesh::ADD_HYP ) // add local hypothesis
431 ; // rebuild propagation chain
434 case LAST_IN_CHAIN: { // submesh with local 1D hyp, breaking a chain
435 // --------------------------------------------------------
436 if ( event == SMESH_subMesh::REMOVE_HYP ) // remove local hyp
437 ; // rebuild propagation chain
440 } // switch by SubMeshState