+namespace
+{
+ // ------------------------------------------------------------------------------
+ /*!
+ * \brief Listener used to mark edges meshed by StdMeshers_RadialQuadrangle_1D2D
+ */
+ class TLinEdgeMarker : public SMESH_subMeshEventListener
+ {
+ TLinEdgeMarker(): SMESH_subMeshEventListener(/*isDeletable=*/false) {}
+ public:
+ static SMESH_subMeshEventListener* getListener()
+ {
+ static TLinEdgeMarker theEdgeMarker;
+ return &theEdgeMarker;
+ }
+ };
+
+ // ------------------------------------------------------------------------------
+ /*!
+ * \brief Mark an edge as computed by StdMeshers_RadialQuadrangle_1D2D
+ */
+ void markLinEdgeAsComputedByMe(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
+ {
+ if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
+ {
+ if ( !edgeSM->GetEventListenerData( TLinEdgeMarker::getListener() ))
+ faceSubMesh->SetEventListener( TLinEdgeMarker::getListener(),
+ SMESH_subMeshEventListenerData::MakeData(faceSubMesh),
+ edgeSM);
+ }
+ }
+ // ------------------------------------------------------------------------------
+ /*!
+ * \brief Return true if a radial edge was meshed with StdMeshers_RadialQuadrangle_1D2D with
+ * the same radial distribution
+ */
+ bool isEdgeCompitaballyMeshed(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
+ {
+ if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
+ {
+ if ( SMESH_subMeshEventListenerData* otherFaceData =
+ edgeSM->GetEventListenerData( TLinEdgeMarker::getListener() ))
+ {
+ // compare hypothesis aplied to two disk faces sharing radial edges
+ SMESH_Mesh& mesh = *faceSubMesh->GetFather();
+ SMESH_Algo* radialQuadAlgo = mesh.GetGen()->GetAlgo(mesh, faceSubMesh->GetSubShape() );
+ SMESH_subMesh* otherFaceSubMesh = otherFaceData->mySubMeshes.front();
+ const list <const SMESHDS_Hypothesis *> & hyps1 =
+ radialQuadAlgo->GetUsedHypothesis( mesh, faceSubMesh->GetSubShape());
+ const list <const SMESHDS_Hypothesis *> & hyps2 =
+ radialQuadAlgo->GetUsedHypothesis( mesh, otherFaceSubMesh->GetSubShape());
+ if( hyps1.empty() && hyps2.empty() )
+ return true; // defaul hyps
+ if ( hyps1.size() != hyps2.size() ||
+ strcmp( hyps1.front()->GetName(), hyps2.front()->GetName() ))
+ return false;
+ ostringstream hypDump1, hypDump2;
+ list <const SMESHDS_Hypothesis*>::const_iterator hyp1 = hyps1.begin();
+ for ( ; hyp1 != hyps1.end(); ++hyp1 )
+ const_cast<SMESHDS_Hypothesis*>(*hyp1)->SaveTo( hypDump1 );
+ list <const SMESHDS_Hypothesis*>::const_iterator hyp2 = hyps2.begin();
+ for ( ; hyp2 != hyps2.end(); ++hyp2 )
+ const_cast<SMESHDS_Hypothesis*>(*hyp2)->SaveTo( hypDump2 );
+ return hypDump1.str() == hypDump2.str();
+ }
+ }
+ return false;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return base curve of the edge and extremum parameters
+ */
+ //================================================================================
+
+ Handle(Geom_Curve) getCurve(const TopoDS_Edge& edge, double* f=0, double* l=0)
+ {
+ Handle(Geom_Curve) C;
+ if ( !edge.IsNull() )
+ {
+ double first = 0., last = 0.;
+ C = BRep_Tool::Curve(edge, first, last);
+ if ( !C.IsNull() )
+ {
+ Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C);
+ while( !tc.IsNull() ) {
+ C = tc->BasisCurve();
+ tc = Handle(Geom_TrimmedCurve)::DownCast(C);
+ }
+ if ( f ) *f = first;
+ if ( l ) *l = last;
+ }
+ }
+ return C;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return edges of the face
+ * \retval int - nb of edges
+ */
+ //================================================================================
+
+ int analyseFace(const TopoDS_Shape& face,
+ TopoDS_Edge& CircEdge,
+ TopoDS_Edge& LinEdge1,
+ TopoDS_Edge& LinEdge2)
+ {
+ CircEdge.Nullify(); LinEdge1.Nullify(); LinEdge2.Nullify();
+ int nbe = 0;
+
+ for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next(), ++nbe )
+ {
+ const TopoDS_Edge& E = TopoDS::Edge( exp.Current() );
+ double f,l;
+ Handle(Geom_Curve) C = getCurve(E,&f,&l);
+ if ( !C.IsNull() )
+ {
+ if ( C->IsKind( STANDARD_TYPE(Geom_Circle)))
+ {
+ if ( CircEdge.IsNull() )
+ CircEdge = E;
+ else
+ return 0;
+ }
+ else if ( LinEdge1.IsNull() )
+ LinEdge1 = E;
+ else
+ LinEdge2 = E;
+ }
+ }
+ return nbe;
+ }
+}
+
+//=======================================================================
+/*!
+ * \brief Allow algo to do something after persistent restoration
+ * \param subMesh - restored submesh
+ *
+ * call markLinEdgeAsComputedByMe()
+ */
+//=======================================================================
+
+void StdMeshers_RadialQuadrangle_1D2D::SubmeshRestored(SMESH_subMesh* faceSubMesh)
+{
+ if ( !faceSubMesh->IsEmpty() )
+ {
+ TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
+ analyseFace( faceSubMesh->GetSubShape(), CircEdge, LinEdge1, LinEdge2 );
+ if ( !LinEdge1.IsNull() ) markLinEdgeAsComputedByMe( LinEdge1, faceSubMesh );
+ if ( !LinEdge2.IsNull() ) markLinEdgeAsComputedByMe( LinEdge2, faceSubMesh );
+ }
+}