00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "StdMeshers_CompositeSegment_1D.hxx"
00028 #include "StdMeshers_FaceSide.hxx"
00029 #include "StdMeshers_AutomaticLength.hxx"
00030
00031 #include "SMESH_Gen.hxx"
00032 #include "SMESH_Mesh.hxx"
00033 #include "SMESH_HypoFilter.hxx"
00034 #include "SMESH_subMesh.hxx"
00035 #include "SMESH_subMeshEventListener.hxx"
00036 #include "SMESH_Comment.hxx"
00037
00038 #include "SMDS_MeshElement.hxx"
00039 #include "SMDS_MeshNode.hxx"
00040
00041 #include "utilities.h"
00042
00043 #include <BRepAdaptor_CompCurve.hxx>
00044 #include <BRep_Builder.hxx>
00045 #include <GCPnts_AbscissaPoint.hxx>
00046 #include <TopExp.hxx>
00047 #include <TopExp_Explorer.hxx>
00048 #include <TopTools_ListIteratorOfListOfShape.hxx>
00049 #include <TopTools_MapOfShape.hxx>
00050 #include <TopoDS.hxx>
00051 #include <TopoDS_Edge.hxx>
00052 #include <TopoDS_Vertex.hxx>
00053 #include <TopoDS_Wire.hxx>
00054 #include <gp_Pnt.hxx>
00055
00056 #include <Standard_ErrorHandler.hxx>
00057 #include <Standard_Failure.hxx>
00058
00059 typedef SMESH_Comment TComm;
00060
00061 using namespace std;
00062
00063
00064 namespace {
00065
00066
00072
00073
00074 TopoDS_Edge nextC1Edge(TopoDS_Edge edge,
00075 SMESH_Mesh & aMesh,
00076 const bool forward)
00077 {
00078 if (edge.Orientation() > TopAbs_REVERSED)
00079 edge.Orientation( TopAbs_FORWARD );
00080 TopoDS_Edge eNext;
00081 TopTools_MapOfShape edgeCounter;
00082 edgeCounter.Add( edge );
00083 TopoDS_Vertex v = forward ? TopExp::LastVertex(edge,true) : TopExp::FirstVertex(edge,true);
00084 TopTools_ListIteratorOfListOfShape ancestIt = aMesh.GetAncestors( v );
00085 for ( ; ancestIt.More(); ancestIt.Next() )
00086 {
00087 const TopoDS_Shape & ancestor = ancestIt.Value();
00088 if ( ancestor.ShapeType() == TopAbs_EDGE && edgeCounter.Add( ancestor ))
00089 eNext = TopoDS::Edge( ancestor );
00090 }
00091 if ( edgeCounter.Extent() < 3 && !eNext.IsNull() ) {
00092 if ( SMESH_Algo::IsContinuous( edge, eNext )) {
00093
00094 if (eNext.Orientation() > TopAbs_REVERSED)
00095 eNext.Orientation( TopAbs_FORWARD );
00096 TopoDS_Vertex vn =
00097 forward ? TopExp::FirstVertex(eNext,true) : TopExp::LastVertex(eNext,true);
00098 bool reverse = (!v.IsSame(vn));
00099 if ( reverse )
00100 eNext.Reverse();
00101 return eNext;
00102 }
00103 }
00104 return TopoDS_Edge();
00105 }
00106
00107
00112
00113
00114 void careOfSubMeshes( StdMeshers_FaceSide& side, EventListener* eListener)
00115 {
00116 if ( side.NbEdges() < 2)
00117 return;
00118 for ( int iE = 0; iE < side.NbEdges(); ++iE )
00119 {
00120
00121 EventListenerData * listenerData = new EventListenerData(true);
00122 const TopoDS_Edge& edge = side.Edge( iE );
00123 SMESH_subMesh * sm = side.GetMesh()->GetSubMesh( edge );
00124 sm->SetEventListener( eListener, listenerData, sm );
00125
00126 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
00127 if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK ) {
00128 sm->SetIsAlwaysComputed( true );
00129 listenerData->mySubMeshes.push_back( sm );
00130 }
00131
00132 if ( iE )
00133 {
00134 TopoDS_Vertex V = side.FirstVertex( iE );
00135 sm = side.GetMesh()->GetSubMesh( V );
00136 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
00137 if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK )
00138 sm->SetIsAlwaysComputed( true );
00139 listenerData->mySubMeshes.push_back( sm );
00140 }
00141 }
00142 }
00143
00144
00149
00150
00151 struct VertexNodesRestoringListener : public SMESH_subMeshEventListener
00152 {
00153 VertexNodesRestoringListener():SMESH_subMeshEventListener(0)
00154 {}
00163 void ProcessEvent(const int event,
00164 const int eventType,
00165 SMESH_subMesh* subMesh,
00166 EventListenerData* data,
00167 const SMESH_Hypothesis* )
00168 {
00169 bool hypRemoved = ( eventType == SMESH_subMesh::ALGO_EVENT &&
00170 subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK );
00171 if ( hypRemoved && data )
00172 {
00173 list<SMESH_subMesh*>::iterator smIt = data->mySubMeshes.begin();
00174 for ( ; smIt != data->mySubMeshes.end(); ++smIt )
00175 {
00176 if ( SMESH_subMesh* sm = *smIt ) {
00177 sm->SetIsAlwaysComputed( false );
00178 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
00179 }
00180 }
00181 }
00182
00183
00184 else if ( event == SMESH_subMesh::SUBMESH_RESTORED &&
00185 eventType == SMESH_subMesh::COMPUTE_EVENT )
00186 {
00187 if ( !subMesh->GetEventListenerData( this )) {
00188 SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
00189 if ( meshDS->NbNodes() > 0 ) {
00190
00191 bool hasNodesOnVerext = true;
00192 SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
00193 while ( hasNodesOnVerext && smIt->more() ) {
00194 SMESH_subMesh* sm = smIt->next();
00195 hasNodesOnVerext = ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->NbNodes() );
00196 }
00197 if ( !hasNodesOnVerext ) {
00198
00199 TopoDS_Face face;
00200 TopoDS_Edge edge = TopoDS::Edge( subMesh->GetSubShape() );
00201 auto_ptr< StdMeshers_FaceSide > side
00202 ( StdMeshers_CompositeSegment_1D::GetFaceSide(*subMesh->GetFather(),
00203 edge, face, false ));
00204 if ( side->NbEdges() > 1 && side->NbSegments() )
00205 careOfSubMeshes( *side, this );
00206 }
00207 }
00208 }
00209 }
00210 }
00211 };
00212 }
00213
00214
00218
00219
00220 StdMeshers_CompositeSegment_1D::StdMeshers_CompositeSegment_1D(int hypId,
00221 int studyId,
00222 SMESH_Gen * gen)
00223 :StdMeshers_Regular_1D(hypId, studyId, gen)
00224 {
00225 MESSAGE("StdMeshers_CompositeSegment_1D::StdMeshers_CompositeSegment_1D");
00226 _name = "CompositeSegment_1D";
00227 _EventListener = new VertexNodesRestoringListener();
00228 }
00229
00230
00234
00235
00236 StdMeshers_CompositeSegment_1D::~StdMeshers_CompositeSegment_1D()
00237 {
00238 delete _EventListener;
00239 }
00240
00241
00249
00250
00251 void StdMeshers_CompositeSegment_1D::SetEventListener(SMESH_subMesh* subMesh)
00252 {
00253
00254
00255
00256
00257
00258 bool isAlwaysComputed = false;
00259 SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
00260 while ( !isAlwaysComputed && smIt->more() )
00261 isAlwaysComputed = smIt->next()->IsAlwaysComputed();
00262
00263 if ( !isAlwaysComputed )
00264 {
00265
00266 TopoDS_Face face;
00267 TopoDS_Edge edge = TopoDS::Edge( subMesh->GetSubShape() );
00268 auto_ptr< StdMeshers_FaceSide > side
00269 ( StdMeshers_CompositeSegment_1D::GetFaceSide(*subMesh->GetFather(),edge, face, false ));
00270 if ( side->NbEdges() > 1 ) {
00271
00272
00273 for ( int iE = 1; iE < side->NbEdges(); ++iE )
00274 {
00275 TopoDS_Vertex V = side->FirstVertex( iE );
00276 SMESH_subMesh* sm = side->GetMesh()->GetSubMesh( V );
00277 sm->SetIsAlwaysComputed( true );
00278 }
00279 }
00280 }
00281
00282 subMesh->SetEventListener( _EventListener, 0, subMesh);
00283 StdMeshers_Regular_1D::SetEventListener( subMesh );
00284 }
00285
00286
00290
00291
00292 StdMeshers_FaceSide *
00293 StdMeshers_CompositeSegment_1D::GetFaceSide(SMESH_Mesh& aMesh,
00294 const TopoDS_Edge& anEdge,
00295 const TopoDS_Face& aFace,
00296 const bool ignoreMeshed)
00297 {
00298 list< TopoDS_Edge > edges;
00299 if ( anEdge.Orientation() <= TopAbs_REVERSED )
00300 edges.push_back( anEdge );
00301 else
00302 edges.push_back( TopoDS::Edge( anEdge.Oriented( TopAbs_FORWARD )));
00303
00304 list <const SMESHDS_Hypothesis *> hypList;
00305 SMESH_Algo* theAlgo = aMesh.GetGen()->GetAlgo( aMesh, anEdge );
00306 if ( theAlgo ) hypList = theAlgo->GetUsedHypothesis(aMesh, anEdge, false);
00307 for ( int forward = 0; forward < 2; ++forward )
00308 {
00309 TopoDS_Edge eNext = nextC1Edge( edges.back(), aMesh, forward );
00310 while ( !eNext.IsNull() ) {
00311 if ( ignoreMeshed ) {
00312
00313 if ( SMESHDS_SubMesh* sm = aMesh.GetMeshDS()->MeshElements(eNext) )
00314 if ( sm->NbNodes() || sm->NbElements() )
00315 break;
00316 }
00317
00318 SMESH_Algo* algo = aMesh.GetGen()->GetAlgo( aMesh, eNext );
00319 if ( !algo ||
00320 string(theAlgo->GetName()) != algo->GetName() ||
00321 hypList != algo->GetUsedHypothesis(aMesh, eNext, false))
00322 break;
00323 if ( std::find( edges.begin(), edges.end(), eNext ) != edges.end() )
00324 break;
00325 if ( forward )
00326 edges.push_back( eNext );
00327 else
00328 edges.push_front( eNext );
00329 eNext = nextC1Edge( eNext, aMesh, forward );
00330 }
00331 }
00332 return new StdMeshers_FaceSide( aFace, edges, &aMesh, true, false );
00333 }
00334
00335
00339
00340
00341 bool StdMeshers_CompositeSegment_1D::Compute(SMESH_Mesh & aMesh,
00342 const TopoDS_Shape & aShape)
00343 {
00344 TopoDS_Edge edge = TopoDS::Edge( aShape );
00345 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
00346
00347
00348 TopoDS_Face nullFace;
00349 auto_ptr< StdMeshers_FaceSide > side( GetFaceSide(aMesh, edge, nullFace, true ));
00350
00351
00352 if ( side->NbEdges() < 2 )
00353 return StdMeshers_Regular_1D::Compute( aMesh, aShape );
00354
00355
00356 const list <const SMESHDS_Hypothesis * > & hyps = GetUsedHypothesis(aMesh, aShape);
00357 if ( !hyps.empty() ) {
00358 StdMeshers_AutomaticLength * autoLenHyp = const_cast<StdMeshers_AutomaticLength *>
00359 (dynamic_cast <const StdMeshers_AutomaticLength * >(hyps.front()));
00360 if ( autoLenHyp )
00361 _value[ BEG_LENGTH_IND ]= autoLenHyp->GetLength( &aMesh, side->Length() );
00362 }
00363
00364
00365 auto_ptr< BRepAdaptor_CompCurve > C3d ( side->GetCurve3d() );
00366 double f = C3d->FirstParameter(), l = C3d->LastParameter();
00367 list< double > params;
00368 if ( !computeInternalParameters ( aMesh, *C3d, side->Length(), f, l, params, false ))
00369 return false;
00370
00371
00372 TopoDS_Vertex VFirst = side->FirstVertex();
00373 TopoDS_Vertex VLast = side->LastVertex();
00374 redistributeNearVertices( aMesh, *C3d, side->Length(), params, VFirst, VLast );
00375
00376 params.push_front(f);
00377 params.push_back(l);
00378 int nbNodes = params.size();
00379
00380
00381
00382 const SMDS_MeshNode * nFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
00383 const SMDS_MeshNode * nLast = SMESH_Algo::VertexNode( VLast, meshDS );
00384 if (!nFirst)
00385 return error(COMPERR_BAD_INPUT_MESH, TComm("No node on vertex ")
00386 <<meshDS->ShapeToIndex(VFirst));
00387 if (!nLast)
00388 return error(COMPERR_BAD_INPUT_MESH, TComm("No node on vertex ")
00389 <<meshDS->ShapeToIndex(VLast));
00390
00391 vector<const SMDS_MeshNode*> nodes( nbNodes, (const SMDS_MeshNode*)0 );
00392 nodes.front() = nFirst;
00393 nodes.back() = nLast;
00394
00395
00396 list< double >::iterator parIt = params.begin();
00397 double prevPar = *parIt;
00398 Standard_Real u;
00399 for ( int iN = 0; parIt != params.end(); ++iN, ++parIt)
00400 {
00401 if ( !nodes[ iN ] ) {
00402 gp_Pnt p = C3d->Value( *parIt );
00403 SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z());
00404 C3d->Edge( *parIt, edge, u );
00405 meshDS->SetNodeOnEdge( n, edge, u );
00406
00407
00408 nodes[ iN ] = n;
00409 }
00410
00411 if ( iN ) {
00412 double mPar = ( prevPar + *parIt )/2;
00413 if ( _quadraticMesh ) {
00414
00415 double segLen = GCPnts_AbscissaPoint::Length(*C3d, prevPar, *parIt);
00416 GCPnts_AbscissaPoint ruler( *C3d, segLen/2., prevPar );
00417 if ( ruler.IsDone() )
00418 mPar = ruler.Parameter();
00419 gp_Pnt p = C3d->Value( mPar );
00420 SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z());
00421
00422 meshDS->SetNodeOnEdge( n, edge, u );
00423 SMDS_MeshEdge * seg = meshDS->AddEdge(nodes[ iN-1 ], nodes[ iN ], n);
00424 meshDS->SetMeshElementOnShape(seg, edge);
00425 }
00426 else {
00427 C3d->Edge( mPar, edge, u );
00428 SMDS_MeshEdge * seg = meshDS->AddEdge(nodes[ iN-1 ], nodes[ iN ]);
00429 meshDS->SetMeshElementOnShape(seg, edge);
00430 }
00431 }
00432 prevPar = *parIt;
00433 }
00434
00435
00436 for ( int iE = 1; iE < side->NbEdges(); ++iE )
00437 {
00438 TopoDS_Vertex V = side->FirstVertex( iE );
00439 while ( const SMDS_MeshNode * n = SMESH_Algo::VertexNode( V, meshDS ))
00440 meshDS->RemoveNode( n );
00441 }
00442
00443
00444
00445 careOfSubMeshes( *side, _EventListener );
00446
00447 return true;
00448 }