1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 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.
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
24 // File : StdMeshers_Projection_1D.cxx
26 // Created : Fri Oct 20 11:37:07 2006
27 // Author : Edward AGAPOV (eap)
30 #include "StdMeshers_Projection_1D.hxx"
32 #include "StdMeshers_ProjectionSource1D.hxx"
33 #include "StdMeshers_ProjectionUtils.hxx"
35 #include "SMDS_MeshNode.hxx"
36 #include "SMDS_MeshElement.hxx"
37 #include "SMESHDS_Mesh.hxx"
38 #include "SMESHDS_SubMesh.hxx"
39 #include "SMESH_Mesh.hxx"
40 #include "SMESH_MesherHelper.hxx"
41 #include "SMESH_subMesh.hxx"
42 #include "SMESH_subMeshEventListener.hxx"
43 #include "SMESH_Gen.hxx"
45 #include <BRepAdaptor_Curve.hxx>
46 #include <BRep_Tool.hxx>
47 #include <GCPnts_AbscissaPoint.hxx>
51 #include "utilities.h"
56 #define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
58 typedef StdMeshers_ProjectionUtils TAssocTool;
60 //=======================================================================
61 //function : StdMeshers_Projection_1D
63 //=======================================================================
65 StdMeshers_Projection_1D::StdMeshers_Projection_1D(int hypId, int studyId, SMESH_Gen* gen)
66 :SMESH_1D_Algo(hypId, studyId, gen)
68 _name = "Projection_1D";
69 _shapeType = (1 << TopAbs_EDGE); // 1 bit per shape type
71 _compatibleHypothesis.push_back("ProjectionSource1D");
75 //================================================================================
79 //================================================================================
81 StdMeshers_Projection_1D::~StdMeshers_Projection_1D()
84 //=======================================================================
85 //function : CheckHypothesis
87 //=======================================================================
89 bool StdMeshers_Projection_1D::CheckHypothesis(SMESH_Mesh& aMesh,
90 const TopoDS_Shape& aShape,
91 SMESH_Hypothesis::Hypothesis_Status& aStatus)
94 list <const SMESHDS_Hypothesis * >::const_iterator itl;
96 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
97 if ( hyps.size() == 0 )
99 aStatus = SMESH_Hypothesis::HYP_MISSING;
100 return false; // can't work with no hypothesis
103 if ( hyps.size() > 1 )
105 aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
109 const SMESHDS_Hypothesis *theHyp = hyps.front();
111 string hypName = theHyp->GetName();
113 aStatus = SMESH_Hypothesis::HYP_OK;
115 if (hypName == "ProjectionSource1D")
117 _sourceHypo = static_cast<const StdMeshers_ProjectionSource1D *>(theHyp);
119 // Check hypo parameters
121 SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
122 SMESH_Mesh* tgtMesh = & aMesh;
127 if ( _sourceHypo->HasVertexAssociation() )
129 // source and target vertices
130 if ( !TAssocTool::IsSubShape( _sourceHypo->GetSourceVertex(), srcMesh ) ||
131 !TAssocTool::IsSubShape( _sourceHypo->GetTargetVertex(), tgtMesh ) ||
132 !TAssocTool::IsSubShape( _sourceHypo->GetTargetVertex(), aShape ) ||
133 !TAssocTool::IsSubShape( _sourceHypo->GetSourceVertex(),
134 _sourceHypo->GetSourceEdge() ))
136 aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
137 SCRUTE((TAssocTool::IsSubShape( _sourceHypo->GetSourceVertex(), srcMesh )));
138 SCRUTE((TAssocTool::IsSubShape( _sourceHypo->GetTargetVertex(), tgtMesh )));
139 SCRUTE((TAssocTool::IsSubShape( _sourceHypo->GetTargetVertex(), aShape ) ));
140 SCRUTE((TAssocTool::IsSubShape( _sourceHypo->GetSourceVertex(),
141 _sourceHypo->GetSourceEdge() )));
145 if ( !TAssocTool::IsSubShape( _sourceHypo->GetSourceEdge(), srcMesh ) ||
146 ( srcMesh == tgtMesh && aShape == _sourceHypo->GetSourceEdge() ))
148 aStatus = HYP_BAD_PARAMETER;
149 SCRUTE((TAssocTool::IsSubShape( _sourceHypo->GetSourceEdge(), srcMesh )));
150 SCRUTE((srcMesh == tgtMesh));
151 SCRUTE(( aShape == _sourceHypo->GetSourceEdge() ));
156 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
158 return ( aStatus == HYP_OK );
161 //=======================================================================
164 //=======================================================================
166 bool StdMeshers_Projection_1D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
171 TopoDS_Edge tgtEdge = TopoDS::Edge( theShape.Oriented(TopAbs_FORWARD));
172 TopoDS_Edge srcEdge = TopoDS::Edge( _sourceHypo->GetSourceEdge().Oriented(TopAbs_FORWARD));
174 TopoDS_Vertex tgtV[2], srcV[2];
175 TopExp::Vertices( tgtEdge, tgtV[0], tgtV[1] );
176 TopExp::Vertices( srcEdge, srcV[0], srcV[1] );
178 SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
179 SMESH_Mesh * tgtMesh = & theMesh;
183 SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
185 // ---------------------------
186 // Make subshapes association
187 // ---------------------------
189 TAssocTool::TShapeShapeMap shape2ShapeMap;
190 TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
191 if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcEdge, srcMesh,
193 RETURN_BAD_RESULT("FindSubShapeAssociation failed");
195 // ----------------------------------------------
196 // Assure that mesh on a source edge is computed
197 // ----------------------------------------------
199 SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcEdge );
200 //SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtEdge );
202 if ( tgtMesh == srcMesh ) {
203 if ( !TAssocTool::MakeComputed( srcSubMesh ))
204 RETURN_BAD_RESULT("Impossible to compute the source mesh");
207 if ( !srcSubMesh->IsMeshComputed() )
208 RETURN_BAD_RESULT("Source mesh is not computed");
210 // -----------------------------------------------
211 // Find out nodes distribution on the source edge
212 // -----------------------------------------------
214 double srcLength = EdgeLength( srcEdge );
215 double tgtLength = EdgeLength( tgtEdge );
217 vector< double > params; // sorted parameters of nodes on the source edge
218 if ( !SMESH_Algo::GetNodeParamOnEdge( srcMesh->GetMeshDS(), srcEdge, params ))
219 RETURN_BAD_RESULT("Bad node params on the source edge");
221 int i, nbNodes = params.size();
223 vector< double > lengths( nbNodes - 1 ); // lengths of segments of the source edge
226 BRepAdaptor_Curve curveAdaptor( srcEdge );
227 for ( i = 1; i < nbNodes; ++i )
228 lengths[ i-1 ] = GCPnts_AbscissaPoint::Length( curveAdaptor, params[i-1], params[i]);
230 else // degenerated source edge
232 for ( i = 1; i < nbNodes; ++i )
233 lengths[ i-1 ] = params[i] - params[i-1];
234 srcLength = params.back() - params[0];
237 bool reverse = ( srcV[0].IsSame( shape2ShapeMap( tgtV[1] )));
238 if ( shape2ShapeMap.IsBound( tgtEdge )) // case of closed edge
239 reverse = ( shape2ShapeMap( tgtEdge ).Orientation() == TopAbs_REVERSED );
240 if ( reverse ) // reverse lengths of segments
241 std::reverse( lengths.begin(), lengths.end() );
247 // vector of target nodes
248 vector< const SMDS_MeshNode* > nodes ( nbNodes );
250 // Get the first and last nodes
251 // -----------------------------
253 SMESHDS_SubMesh* smV0 = meshDS->MeshElements( tgtV[0] );
254 SMESHDS_SubMesh* smV1 = meshDS->MeshElements( tgtV[1] );
255 if ( !smV0 || !smV1 )
256 RETURN_BAD_RESULT("No submeshes on vertices");
258 SMDS_NodeIteratorPtr nItV0 = smV0->GetNodes();
259 SMDS_NodeIteratorPtr nItV1 = smV1->GetNodes();
260 if ( !nItV0->more() || !nItV1->more() )
261 RETURN_BAD_RESULT("No nodes on vertices");
263 nodes.front() = nItV0->next();
264 nodes.back() = nItV1->next();
266 // Compute parameters on the target edge and make internal nodes
267 // --------------------------------------------------------------
269 vector< double > tgtParams( nbNodes );
271 BRep_Tool::Range( tgtEdge, tgtParams.front(), tgtParams.back() );
272 if ( tgtLength <= 0 )
273 tgtLength = tgtParams.back() - tgtParams.front();
274 double dl = tgtLength / srcLength;
278 BRepAdaptor_Curve curveAdaptor( tgtEdge );
280 // compute params on internal nodes
281 for ( i = 1; i < nbNodes - 1; ++i )
283 // computes a point on a <curveAdaptor> at the given distance
284 // from the point at given parameter.
285 GCPnts_AbscissaPoint Discret( curveAdaptor, dl * lengths[ i-1 ], tgtParams[ i-1 ] );
286 if ( !Discret.IsDone() )
287 RETURN_BAD_RESULT(" GCPnts_AbscissaPoint failed");
288 tgtParams[ i ] = Discret.Parameter();
290 // make internal nodes
291 for ( i = 1; i < nbNodes - 1; ++i )
293 gp_Pnt P = curveAdaptor.Value( tgtParams[ i ]);
294 SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
295 meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
299 else // degenerated target edge
301 // compute params and make internal nodes
302 gp_Pnt P = BRep_Tool::Pnt( tgtV[0] );
304 for ( i = 1; i < nbNodes - 1; ++i )
306 SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
307 tgtParams[ i ] = tgtParams[ i-1 ] + dl * lengths[ i-1 ];
308 meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
316 bool quadratic = false;
317 SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements();
318 if ( elemIt->more() )
319 quadratic = elemIt->next()->IsQuadratic();
321 SMDS_NodeIteratorPtr nodeIt = srcSubMesh->GetSubMeshDS()->GetNodes();
322 while ( nodeIt->more() && !quadratic )
323 quadratic = SMESH_MesherHelper::IsMedium( nodeIt->next() );
325 // enough nodes to make all edges quadratic?
326 if ( quadratic && ( nbNodes < 3 || ( nbNodes % 2 != 1 )))
327 RETURN_BAD_RESULT("Wrong nb nodes to make quadratic mesh");
332 SMDS_MeshElement* edge = 0;
333 int di = quadratic ? 2 : 1;
334 for ( i = di; i < nbNodes; i += di)
337 edge = meshDS->AddEdge( nodes[i-2], nodes[i], nodes[i-1] );
339 edge = meshDS->AddEdge( nodes[i-1], nodes[i] );
340 meshDS->SetMeshElementOnShape(edge, tgtEdge );
346 //=============================================================================
348 * \brief Sets a default event listener to submesh of the source edge
349 * \param subMesh - submesh where algo is set
351 * This method is called when a submesh gets HYP_OK algo_state.
352 * After being set, event listener is notified on each event of a submesh.
353 * Arranges that CLEAN event is translated from source submesh to
356 //=============================================================================
358 void StdMeshers_Projection_1D::SetEventListener(SMESH_subMesh* subMesh)
360 TAssocTool::SetEventListener( subMesh,
361 _sourceHypo->GetSourceEdge(),
362 _sourceHypo->GetSourceMesh() );