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