Salome HOME
SALOME PAL V1_4_1
[modules/smesh.git] / src / StdMeshers / StdMeshers_Regular_1D.cxx
1 //  SMESH SMESH : implementaion of SMESH idl descriptions
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : StdMeshers_Regular_1D.cxx
25 //           Moved here from SMESH_Regular_1D.cxx
26 //  Author : Paul RASCLE, EDF
27 //  Module : SMESH
28 //  $Header$
29
30 using namespace std;
31
32 #include "StdMeshers_Regular_1D.hxx"
33 #include "SMESH_Gen.hxx"
34 #include "SMESH_Mesh.hxx"
35
36 #include "StdMeshers_LocalLength.hxx"
37 #include "StdMeshers_NumberOfSegments.hxx"
38
39 #include "SMDS_MeshElement.hxx"
40 #include "SMDS_MeshNode.hxx"
41 #include "SMDS_EdgePosition.hxx"
42
43 #include "utilities.h"
44
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Shape.hxx>
47 #include <GeomAdaptor_Curve.hxx>
48 #include <BRep_Tool.hxx>
49 #include <GCPnts_AbscissaPoint.hxx>
50 #include <GCPnts_UniformAbscissa.hxx>
51
52 #include <string>
53 #include <algorithm>
54
55 //=============================================================================
56 /*!
57  *  
58  */
59 //=============================================================================
60
61 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
62         SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
63 {
64         MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
65         _name = "Regular_1D";
66         //  _shapeType = TopAbs_EDGE;
67         _shapeType = (1 << TopAbs_EDGE);
68         _compatibleHypothesis.push_back("LocalLength");
69         _compatibleHypothesis.push_back("NumberOfSegments");
70
71         _localLength = 0;
72         _numberOfSegments = 0;
73         _hypLocalLength = NULL;
74         _hypNumberOfSegments = NULL;
75 }
76
77 //=============================================================================
78 /*!
79  *  
80  */
81 //=============================================================================
82
83 StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
84 {
85 }
86
87 //=============================================================================
88 /*!
89  *  
90  */
91 //=============================================================================
92
93 bool StdMeshers_Regular_1D::CheckHypothesis
94                          (SMESH_Mesh& aMesh,
95                           const TopoDS_Shape& aShape,
96                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
97 {
98         //MESSAGE("StdMeshers_Regular_1D::CheckHypothesis");
99
100         list <const SMESHDS_Hypothesis * >::const_iterator itl;
101         const SMESHDS_Hypothesis *theHyp;
102
103         const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
104         int nbHyp = hyps.size();
105         if (!nbHyp)
106         {
107           aStatus = SMESH_Hypothesis::HYP_MISSING;
108           return false;  // can't work with no hypothesis
109         }
110
111         itl = hyps.begin();
112         theHyp = (*itl); // use only the first hypothesis
113
114         string hypName = theHyp->GetName();
115         int hypId = theHyp->GetID();
116         //SCRUTE(hypName);
117
118         bool isOk = false;
119
120         if (hypName == "LocalLength")
121         {
122                 _hypLocalLength = dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
123                 ASSERT(_hypLocalLength);
124                 _localLength = _hypLocalLength->GetLength();
125                 _numberOfSegments = 0;
126                 isOk = true;
127                 aStatus = SMESH_Hypothesis::HYP_OK;
128         }
129
130         else if (hypName == "NumberOfSegments")
131         {
132                 _hypNumberOfSegments =
133                         dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
134                 ASSERT(_hypNumberOfSegments);
135                 _numberOfSegments = _hypNumberOfSegments->GetNumberOfSegments();
136                 _scaleFactor = _hypNumberOfSegments->GetScaleFactor();
137                 _localLength = 0;
138                 isOk = true;
139                 aStatus = SMESH_Hypothesis::HYP_OK;
140         }
141         else
142           aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
143
144         //SCRUTE(_localLength);
145         //SCRUTE(_numberOfSegments);
146
147         return isOk;
148 }
149
150 //=============================================================================
151 /*!
152  *  
153  */
154 //=============================================================================
155
156 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
157 {
158         MESSAGE("StdMeshers_Regular_1D::Compute");
159
160         SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
161         SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
162
163         const TopoDS_Edge & EE = TopoDS::Edge(aShape);
164         TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
165
166         double f, l;
167         Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
168
169         TopoDS_Vertex VFirst, VLast;
170         TopExp::Vertices(E, VFirst, VLast);     // Vfirst corresponds to f and Vlast to l
171
172         double length = EdgeLength(E);
173         //SCRUTE(length);
174
175         double eltSize = 1;
176 //   if (_localLength > 0) eltSize = _localLength;
177         if (_localLength > 0)
178         {
179                 double nbseg = ceil(length / _localLength);     // integer sup
180                 if (nbseg <= 0)
181                         nbseg = 1;                      // degenerated edge
182                 eltSize = length / nbseg;
183         }
184         else
185         {
186                 ASSERT(_numberOfSegments > 0);
187                 eltSize = length / _numberOfSegments;
188         }
189
190         ASSERT(!VFirst.IsNull());
191         SMDS_NodeIteratorPtr lid= aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
192         const SMDS_MeshNode * idFirst = lid->next();
193
194         ASSERT(!VLast.IsNull());
195         lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
196         const SMDS_MeshNode * idLast = lid->next();
197
198         if (!Curve.IsNull())
199         {
200                 GeomAdaptor_Curve C3d(Curve);
201                 GCPnts_UniformAbscissa Discret(C3d, eltSize, f, l);
202                 int NbPoints = Discret.NbPoints();
203                 //MESSAGE("nb points on edge : "<<NbPoints);
204
205                 // edge extrema (indexes : 1 & NbPoints) already in SMDS (TopoDS_Vertex)
206                 // only internal nodes receive an edge position with param on curve
207
208                 const SMDS_MeshNode * idPrev = idFirst;
209                 for (int i = 2; i < NbPoints; i++)
210                 {
211                         double param = Discret.Parameter(i);
212
213                         if (_numberOfSegments > 1)
214                         {
215                                 double epsilon = 0.001;
216                                 if (fabs(_scaleFactor - 1.0) > epsilon)
217                                 {
218                                         double alpha =
219                                                 pow(_scaleFactor, 1.0 / (_numberOfSegments - 1));
220                                         double d =
221                                                 length * (1 - pow(alpha, i - 1)) / (1 - pow(alpha,
222                                                         _numberOfSegments));
223                                         param = d;
224                                 }
225                         }
226
227                         gp_Pnt P = Curve->Value(param);
228
229                         //Add the Node in the DataStructure
230                         //MESSAGE("point "<<nodeId<<" "<<P.X()<<" "<<P.Y()<<" "<<P.Z()<<" - "<<i<<" "<<param);
231                         SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
232                         meshDS->SetNodeOnEdge(node, E);
233
234                         // **** edgePosition associe au point = param. 
235                         SMDS_EdgePosition* epos =
236                           dynamic_cast<SMDS_EdgePosition *>(node->GetPosition().get());
237                         epos->SetUParameter(param);
238
239                         SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
240                         meshDS->SetMeshElementOnShape(edge, E);
241                         idPrev = node;
242                 }
243                 SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
244                 meshDS->SetMeshElementOnShape(edge, E);
245         }
246         else
247         {
248 //       MESSAGE ("Edge Degeneree non traitee --- arret");
249 //       ASSERT(0);
250                 if (BRep_Tool::Degenerated(E))
251                 {
252                         // Edge is a degenerated Edge : We put n = 5 points on the edge.
253                         int NbPoints = 5;
254                         BRep_Tool::Range(E, f, l);
255                         double du = (l - f) / (NbPoints - 1);
256                         MESSAGE("************* Degenerated edge! *****************");
257
258                         TopoDS_Vertex V1, V2;
259                         TopExp::Vertices(E, V1, V2);
260                         gp_Pnt P = BRep_Tool::Pnt(V1);
261
262                         const SMDS_MeshNode * idPrev = idFirst;
263                         for (int i = 2; i < NbPoints; i++)
264                         {
265                                 double param = f + (i - 1) * du;
266                                 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
267                                 meshDS->SetNodeOnEdge(node, E);
268
269 //        Handle (SMDS_EdgePosition) epos
270 //      = new SMDS_EdgePosition(theSubMesh->GetId(),param);
271 //        node->SetPosition(epos);
272                                 SMDS_EdgePosition* epos =
273                                   dynamic_cast<SMDS_EdgePosition*>(node->GetPosition().get());
274                                 epos->SetUParameter(param);
275
276                                 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
277                                 meshDS->SetMeshElementOnShape(edge, E);
278                                 idPrev = node;
279                         }
280                         SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
281                         meshDS->SetMeshElementOnShape(edge, E);
282                 }
283                 else
284                         ASSERT(0);
285         }
286         return true;
287 }
288
289 //=============================================================================
290 /*!
291  *  
292  */
293 //=============================================================================
294
295 ostream & StdMeshers_Regular_1D::SaveTo(ostream & save)
296 {
297   return save;
298 }
299
300 //=============================================================================
301 /*!
302  *  
303  */
304 //=============================================================================
305
306 istream & StdMeshers_Regular_1D::LoadFrom(istream & load)
307 {
308   return load;
309 }
310
311 //=============================================================================
312 /*!
313  *  
314  */
315 //=============================================================================
316
317 ostream & operator <<(ostream & save, StdMeshers_Regular_1D & hyp)
318 {
319   return hyp.SaveTo( save );
320 }
321
322 //=============================================================================
323 /*!
324  *  
325  */
326 //=============================================================================
327
328 istream & operator >>(istream & load, StdMeshers_Regular_1D & hyp)
329 {
330   return hyp.LoadFrom( load );
331 }