Salome HOME
0021096: EDF 1729 SMESH: Create a Projection 1D-2D algorithm
[modules/smesh.git] / src / StdMeshers / StdMeshers_Projection_1D2D.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File      : StdMeshers_Projection_1D2D.cxx
23 // Module    : SMESH
24 // Author    : Edward AGAPOV (eap)
25 //
26 #include "StdMeshers_Projection_1D2D.hxx"
27
28 #include "SMESH_Gen.hxx"
29 #include "SMESH_MesherHelper.hxx"
30 #include "SMESH_subMeshEventListener.hxx"
31 #include "StdMeshers_FaceSide.hxx"
32 #include "StdMeshers_ProjectionSource2D.hxx"
33 #include "StdMeshers_ProjectionUtils.hxx"
34
35 #include <TopoDS.hxx>
36 #include <TopExp_Explorer.hxx>
37
38 using namespace std;
39
40 //#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
41
42 //=======================================================================
43 //function : StdMeshers_Projection_1D2D
44 //purpose  : 
45 //=======================================================================
46
47 StdMeshers_Projection_1D2D::StdMeshers_Projection_1D2D(int hypId, int studyId, SMESH_Gen* gen)
48   :StdMeshers_Projection_2D(hypId, studyId, gen)
49 {
50   _name = "Projection_1D2D";
51   _requireDescretBoundary = false;
52 }
53
54 //=======================================================================
55 //function : Compute
56 //purpose  : 
57 //=======================================================================
58
59 bool StdMeshers_Projection_1D2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
60 {
61   if ( !StdMeshers_Projection_2D::Compute(theMesh, theShape))
62     return false;
63
64   SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
65
66   SMESHDS_SubMesh * faceSubMesh = meshDS->MeshElements( theShape );
67   if ( !faceSubMesh || faceSubMesh->NbElements() == 0 ) return false;
68   _quadraticMesh = faceSubMesh->GetElements()->next()->IsQuadratic();
69
70   SMESH_MesherHelper helper( theMesh );
71   helper.SetSubShape( theShape );
72
73   TopoDS_Face F = TopoDS::Face( theShape );
74   TError err;
75   TSideVector wires = StdMeshers_FaceSide::GetFaceWires( F, theMesh,
76                                                          /*ignoreMediumNodes=*/false, err);
77   if ( err && !err->IsOK() )
78     return error( err );
79
80   for ( size_t iWire = 0; iWire < wires.size(); ++iWire )
81   {
82     vector<const SMDS_MeshNode*> nodes = wires[ iWire ]->GetOrderedNodes();
83     if ( nodes.empty() )
84       return error("No nodes found on a wire");
85
86     const bool checkExisting = wires[ iWire ]->NbSegments();
87
88     if ( _quadraticMesh )
89     {
90       for ( size_t i = 2; i < nodes.size(); i += 2 )
91       {
92         if ( checkExisting && meshDS->FindEdge( nodes[i-2], nodes[i], nodes[i-1]))
93           continue;
94         SMDS_MeshElement* e = meshDS->AddEdge( nodes[i-2], nodes[i], nodes[i-1] );
95         meshDS->SetMeshElementOnShape( e, nodes[i-1]->getshapeId() );
96       }
97     }
98     else
99     {
100       int edgeID = meshDS->ShapeToIndex( wires[ iWire ]->Edge(0) );
101       for ( size_t i = 1; i < nodes.size(); ++i )
102       {
103         if ( checkExisting && meshDS->FindEdge( nodes[i-1], nodes[i])
104              continue;
105         SMDS_MeshElement* e = meshDS->AddEdge( nodes[i-1], nodes[i] );
106         if ( nodes[i-1]->getshapeId() != edgeID &&
107              nodes[i  ]->getshapeId() != edgeID )
108         {
109           edgeID = helper.GetMediumPos( nodes[i-1], nodes[i] ).first;
110           if ( edgeID < 1 ) edgeID = helper.GetSubShapeID();
111         }
112         meshDS->SetMeshElementOnShape( e, edgeID );
113       }
114     }
115   }   
116
117   return true;
118 }
119
120 //=======================================================================
121 //function : Evaluate
122 //purpose  : 
123 //=======================================================================
124
125 bool StdMeshers_Projection_1D2D::Evaluate(SMESH_Mesh&         theMesh,
126                                           const TopoDS_Shape& theShape,
127                                           MapShapeNbElems&    aResMap)
128 {
129   if ( !StdMeshers_Projection_2D::Evaluate(theMesh,theShape,aResMap))
130     return false;
131
132   TopoDS_Shape srcFace = _sourceHypo->GetSourceFace();
133   SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
134   if ( !srcMesh ) srcMesh = & theMesh;
135   SMESH_subMesh* srcFaceSM = srcMesh->GetSubMesh( srcFace );
136
137   typedef StdMeshers_ProjectionUtils SPU;
138   SPU::TShapeShapeMap shape2ShapeMap;
139   SPU::InitVertexAssociation( _sourceHypo, shape2ShapeMap, theShape );
140   if ( !SPU::FindSubShapeAssociation( theShape, &theMesh, srcFace, srcMesh, shape2ShapeMap))
141     return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
142
143   MapShapeNbElems srcResMap;
144   if ( !srcFaceSM->IsMeshComputed() )
145     _gen->Evaluate( *srcMesh, srcFace, srcResMap);
146
147   SMESH_subMeshIteratorPtr smIt = srcFaceSM->getDependsOnIterator(/*includeSelf=*/false,
148                                                                   /*complexShapeFirst=*/true);
149   while ( smIt->more() )
150   {
151     SMESH_subMesh* srcSM = smIt->next();
152     TopAbs_ShapeEnum shapeType = srcSM->GetSubShape().ShapeType();
153     if ( shapeType == TopAbs_EDGE )
154     {
155       std::vector<int> aVec;
156       SMESHDS_SubMesh* srcSubMeshDS = srcSM->GetSubMeshDS();
157       if ( srcSubMeshDS && srcSubMeshDS->NbElements() )
158       {
159         aVec.resize(SMDSEntity_Last, 0);
160         SMDS_ElemIteratorPtr eIt = srcSubMeshDS->GetElements();
161         _quadraticMesh = ( eIt->more() && eIt->next()->IsQuadratic() );
162
163         aVec[SMDSEntity_Node] = srcSubMeshDS->NbNodes();
164         aVec[_quadraticMesh ? SMDSEntity_Quad_Edge : SMDSEntity_Edge] = srcSubMeshDS->NbElements();
165       }
166       else
167       {
168         if ( srcResMap.empty() )
169           if ( !_gen->Evaluate( *srcMesh, srcSM->GetSubShape(), srcResMap ))
170             return error(COMPERR_BAD_INPUT_MESH,"Source mesh not evaluatable");
171         aVec = srcResMap[ srcSM ];
172         if ( aVec.empty() )
173           return error(COMPERR_BAD_INPUT_MESH,"Source mesh is wrongly evaluated");
174       }
175       TopoDS_Shape tgtEdge = shape2ShapeMap( srcSM->GetSubShape() );
176       SMESH_subMesh* tgtSM = theMesh.GetSubMesh( tgtEdge );
177       aResMap.insert(std::make_pair(tgtSM,aVec));
178     }
179     if ( shapeType == TopAbs_VERTEX ) break;
180   }
181
182   return true;
183 }
184
185 //=======================================================================
186 //function : SetEventListener
187 //purpose  : Sets a default event listener to submesh of the source face.
188 //           whenSetToFaceSubMesh - submesh where algo is set
189 // After being set, event listener is notified on each event of a submesh.
190 // This method is called when a submesh gets HYP_OK algo_state.
191 // Arranges that CLEAN event is translated from source submesh to
192 // the whenSetToFaceSubMesh submesh.
193 //=======================================================================
194
195 void StdMeshers_Projection_1D2D::SetEventListener(SMESH_subMesh* whenSetToFaceSubMesh)
196 {
197   // set a listener of events on a source submesh
198   StdMeshers_Projection_2D::SetEventListener(whenSetToFaceSubMesh);
199
200   // set a listener to the target FACE submesh in order to update submehses
201   // of EDGEs according to events on the target FACE submesh
202
203   // fill a listener data with submeshes of EDGEs
204   SMESH_subMeshEventListenerData* data =
205     new SMESH_subMeshEventListenerData(/*isDeletable=*/true);
206   SMESH_Mesh* mesh = whenSetToFaceSubMesh->GetFather();
207   TopExp_Explorer eExp( whenSetToFaceSubMesh->GetSubShape(), TopAbs_EDGE );
208   for ( ; eExp.More(); eExp.Next() )
209     data->mySubMeshes.push_back( mesh->GetSubMesh( eExp.Current() ));
210
211   // set a listener
212   SMESH_subMeshEventListener* listener =
213     new SMESH_subMeshEventListener(/*isDeletable=*/true);
214   whenSetToFaceSubMesh->SetEventListener( listener, data, whenSetToFaceSubMesh );
215 }
216