Salome HOME
Merge with version on tag OCC-V2_1_0d
[modules/smesh.git] / src / StdMeshers / StdMeshers_Hexa_3D.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_Hexa_3D.cxx
25 //           Moved here from SMESH_Hexa_3D.cxx
26 //  Author : Paul RASCLE, EDF
27 //  Module : SMESH
28 //  $Header$
29
30 using namespace std;
31 #include "StdMeshers_Hexa_3D.hxx"
32 #include "StdMeshers_Quadrangle_2D.hxx"
33 #include "SMESH_Gen.hxx"
34 #include "SMESH_Mesh.hxx"
35 #include "SMESH_subMesh.hxx"
36
37 #include "SMDS_MeshElement.hxx"
38 #include "SMDS_MeshNode.hxx"
39 #include "SMDS_FacePosition.hxx"
40
41 #include <TopExp.hxx>
42 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
43 #include <TopTools_ListOfShape.hxx>
44 #include <TopTools_ListIteratorOfListOfShape.hxx>
45 #include <TColStd_ListIteratorOfListOfInteger.hxx>
46
47 #include <BRep_Tool.hxx>
48 #include <Geom_Surface.hxx>
49 #include <Geom_Curve.hxx>
50 #include <Geom2d_Curve.hxx>
51 #include <Handle_Geom2d_Curve.hxx>
52 #include <Handle_Geom_Curve.hxx>
53 #include <gp_Pnt2d.hxx>
54
55 #include "utilities.h"
56 #include "Utils_ExceptHandlers.hxx"
57
58
59 //=============================================================================
60 /*!
61  *  
62  */
63 //=============================================================================
64
65 StdMeshers_Hexa_3D::StdMeshers_Hexa_3D(int hypId, int studyId,
66         SMESH_Gen * gen):SMESH_3D_Algo(hypId, studyId, gen)
67 {
68         MESSAGE("StdMeshers_Hexa_3D::StdMeshers_Hexa_3D");
69         _name = "Hexa_3D";
70 //   _shapeType = TopAbs_SOLID;
71         _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID); // 1 bit /shape type
72 //   MESSAGE("_shapeType octal " << oct << _shapeType);
73         for (int i = 0; i < 6; i++)
74                 _quads[i] = 0;
75 }
76
77 //=============================================================================
78 /*!
79  *  
80  */
81 //=============================================================================
82
83 StdMeshers_Hexa_3D::~StdMeshers_Hexa_3D()
84 {
85         MESSAGE("StdMeshers_Hexa_3D::~StdMeshers_Hexa_3D");
86 }
87
88 //=============================================================================
89 /*!
90  *  
91  */
92 //=============================================================================
93
94 bool StdMeshers_Hexa_3D::CheckHypothesis
95                          (SMESH_Mesh& aMesh,
96                           const TopoDS_Shape& aShape,
97                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
98 {
99         //MESSAGE("StdMeshers_Hexa_3D::CheckHypothesis");
100
101         bool isOk = true;
102         aStatus = SMESH_Hypothesis::HYP_OK;
103
104         // nothing to check
105
106         return isOk;
107 }
108
109 //=======================================================================
110 //function : findIJ
111 //purpose  : return i,j of the node
112 //=======================================================================
113
114 static bool findIJ (const SMDS_MeshNode* node, const FaceQuadStruct * quad, int& I, int& J)
115 {
116   I = J = 0;
117   const SMDS_FacePosition* fpos =
118     static_cast<const SMDS_FacePosition*>(node->GetPosition().get());
119   if ( ! fpos ) return false;
120   gp_Pnt2d uv( fpos->GetUParameter(), fpos->GetVParameter() );
121
122   double minDist = DBL_MAX;
123   int nbhoriz  = Min(quad->nbPts[0], quad->nbPts[2]);
124   int nbvertic = Min(quad->nbPts[1], quad->nbPts[3]);
125   for (int i = 1; i < nbhoriz - 1; i++) {
126     for (int j = 1; j < nbvertic - 1; j++) {
127       int ij = j * nbhoriz + i;
128       gp_Pnt2d uv2( quad->uv_grid[ij].u, quad->uv_grid[ij].v );
129       double dist = uv.SquareDistance( uv2 );
130       if ( dist < minDist ) {
131         minDist = dist;
132         I = i;
133         J = j;
134       }
135     }
136   }
137   return true;
138 }
139
140 //=============================================================================
141 /*!
142  * Hexahedron mesh on hexaedron like form
143  * -0.  - shape and face mesh verification
144  * -1.  - identify faces and vertices of the "cube"
145  * -2.  - Algorithm from:
146  * "Application de l'interpolation transfinie à la création de maillages
147  *  C0 ou G1 continus sur des triangles, quadrangles, tetraedres, pentaedres
148  *  et hexaedres déformés."
149  * Alain PERONNET - 8 janvier 1999
150  */
151 //=============================================================================
152
153 bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
154         const TopoDS_Shape & aShape)throw(SALOME_Exception)
155 {
156   Unexpect aCatch(SalomeException);
157         MESSAGE("StdMeshers_Hexa_3D::Compute");
158
159         bool isOk = false;
160         SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
161         SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
162         //const SMESHDS_SubMesh *& subMeshDS = theSubMesh->GetSubMeshDS();
163
164         // 0.  - shape and face mesh verification
165         // 0.1 - shape must be a solid (or a shell) with 6 faces
166         //MESSAGE("---");
167
168         vector < SMESH_subMesh * >meshFaces;
169         for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next())
170         {
171                 SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
172                 ASSERT(aSubMesh);
173                 meshFaces.push_back(aSubMesh);
174         }
175         if (meshFaces.size() != 6)
176         {
177                 SCRUTE(meshFaces.size());
178 //              ASSERT(0);
179                 return false;
180         }
181
182         // 0.2 - is each face meshed with Quadrangle_2D? (so, with a wire of 4 edges)
183         //MESSAGE("---");
184
185         for (int i = 0; i < 6; i++)
186         {
187                 TopoDS_Shape aShape = meshFaces[i]->GetSubShape();
188                 SMESH_Algo *algo = _gen->GetAlgo(aMesh, aShape);
189                 string algoName = algo->GetName();
190                 if (algoName != "Quadrangle_2D")
191                 {
192                         // *** delete _quads
193                         SCRUTE(algoName);
194 //                      ASSERT(0);
195                         return false;
196                 }
197                 StdMeshers_Quadrangle_2D *quadAlgo =
198                         dynamic_cast < StdMeshers_Quadrangle_2D * >(algo);
199                 ASSERT(quadAlgo);
200                 try
201                 {
202                         _quads[i] = quadAlgo->CheckAnd2Dcompute(aMesh, aShape);
203                         // *** to delete after usage
204                 }
205                 catch(SALOME_Exception & S_ex)
206                 {
207                         // *** delete _quads
208                         // *** throw exception
209 //                      ASSERT(0);
210                         return false;
211                 }
212
213                 // 0.2.1 - number of points on the opposite edges must be the same
214                 if (_quads[i]->nbPts[0] != _quads[i]->nbPts[2] ||
215                     _quads[i]->nbPts[1] != _quads[i]->nbPts[3])
216                 {
217                   MESSAGE("different number of points on the opposite edges of face " << i);
218 //                  ASSERT(0);
219                   return false;
220                 }
221         }
222
223         // 1.  - identify faces and vertices of the "cube"
224         // 1.1 - ancestor maps vertex->edges in the cube
225         //MESSAGE("---");
226
227         TopTools_IndexedDataMapOfShapeListOfShape MS;
228         TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, MS);
229
230         // 1.2 - first face is choosen as face Y=0 of the unit cube
231         //MESSAGE("---");
232
233         const TopoDS_Shape & aFace = meshFaces[0]->GetSubShape();
234         const TopoDS_Face & F = TopoDS::Face(aFace);
235
236         // 1.3 - identify the 4 vertices of the face Y=0: V000, V100, V101, V001
237         //MESSAGE("---");
238
239         int i = 0;
240         TopoDS_Edge E = _quads[0]->edge[i];     //edge will be Y=0,Z=0 on unit cube
241         double f, l;
242         Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
243         TopoDS_Vertex VFirst, VLast;
244         TopExp::Vertices(E, VFirst, VLast);     // corresponds to f and l
245         bool isForward =
246                 (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
247
248         if (isForward)
249         {
250                 _cube.V000 = VFirst;    // will be (0,0,0) on the unit cube
251                 _cube.V100 = VLast;             // will be (1,0,0) on the unit cube
252         }
253         else
254         {
255                 _cube.V000 = VLast;
256                 _cube.V100 = VFirst;
257         }
258
259         i = 1;
260         E = _quads[0]->edge[i];
261         C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
262         TopExp::Vertices(E, VFirst, VLast);
263         isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
264         if (isForward)
265                 _cube.V101 = VLast;             // will be (1,0,1) on the unit cube
266         else
267                 _cube.V101 = VFirst;
268
269         i = 2;
270         E = _quads[0]->edge[i];
271         C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
272         TopExp::Vertices(E, VFirst, VLast);
273         isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
274         if (isForward)
275                 _cube.V001 = VLast;             // will be (0,0,1) on the unit cube
276         else
277                 _cube.V001 = VFirst;
278
279         // 1.4 - find edge X=0, Z=0 (ancestor of V000 not in face Y=0)
280         //     - find edge X=1, Z=0 (ancestor of V100 not in face Y=0)
281         //     - find edge X=1, Z=1 (ancestor of V101 not in face Y=0) 
282         //     - find edge X=0, Z=1 (ancestor of V001 not in face Y=0)
283         //MESSAGE("---");
284
285         TopoDS_Edge E_0Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V000, MS);
286         ASSERT(!E_0Y0.IsNull());
287
288         TopoDS_Edge E_1Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V100, MS);
289         ASSERT(!E_1Y0.IsNull());
290
291         TopoDS_Edge E_1Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V101, MS);
292         ASSERT(!E_1Y1.IsNull());
293
294         TopoDS_Edge E_0Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V001, MS);
295         ASSERT(!E_0Y1.IsNull());
296
297         // 1.5 - identify the 4 vertices in face Y=1: V010, V110, V111, V011
298         //MESSAGE("---");
299
300         TopExp::Vertices(E_0Y0, VFirst, VLast);
301         if (VFirst.IsSame(_cube.V000))
302                 _cube.V010 = VLast;
303         else
304                 _cube.V010 = VFirst;
305
306         TopExp::Vertices(E_1Y0, VFirst, VLast);
307         if (VFirst.IsSame(_cube.V100))
308                 _cube.V110 = VLast;
309         else
310                 _cube.V110 = VFirst;
311
312         TopExp::Vertices(E_1Y1, VFirst, VLast);
313         if (VFirst.IsSame(_cube.V101))
314                 _cube.V111 = VLast;
315         else
316                 _cube.V111 = VFirst;
317
318         TopExp::Vertices(E_0Y1, VFirst, VLast);
319         if (VFirst.IsSame(_cube.V001))
320                 _cube.V011 = VLast;
321         else
322                 _cube.V011 = VFirst;
323
324         // 1.6 - find remaining faces given 4 vertices
325         //MESSAGE("---");
326
327         _indY0 = 0;
328         _cube.quad_Y0 = _quads[_indY0];
329
330         _indY1 = GetFaceIndex(aMesh, aShape, meshFaces,
331                 _cube.V010, _cube.V011, _cube.V110, _cube.V111);
332         _cube.quad_Y1 = _quads[_indY1];
333
334         _indZ0 = GetFaceIndex(aMesh, aShape, meshFaces,
335                 _cube.V000, _cube.V010, _cube.V100, _cube.V110);
336         _cube.quad_Z0 = _quads[_indZ0];
337
338         _indZ1 = GetFaceIndex(aMesh, aShape, meshFaces,
339                 _cube.V001, _cube.V011, _cube.V101, _cube.V111);
340         _cube.quad_Z1 = _quads[_indZ1];
341
342         _indX0 = GetFaceIndex(aMesh, aShape, meshFaces,
343                 _cube.V000, _cube.V001, _cube.V010, _cube.V011);
344         _cube.quad_X0 = _quads[_indX0];
345
346         _indX1 = GetFaceIndex(aMesh, aShape, meshFaces,
347                 _cube.V100, _cube.V101, _cube.V110, _cube.V111);
348         _cube.quad_X1 = _quads[_indX1];
349
350         //MESSAGE("---");
351
352         // 1.7 - get convertion coefs from face 2D normalized to 3D normalized
353
354         Conv2DStruct cx0;                       // for face X=0
355         Conv2DStruct cx1;                       // for face X=1
356         Conv2DStruct cy0;
357         Conv2DStruct cy1;
358         Conv2DStruct cz0;
359         Conv2DStruct cz1;
360
361         GetConv2DCoefs(*_cube.quad_X0, meshFaces[_indX0]->GetSubShape(),
362                 _cube.V000, _cube.V010, _cube.V011, _cube.V001, cx0);
363         GetConv2DCoefs(*_cube.quad_X1, meshFaces[_indX1]->GetSubShape(),
364                 _cube.V100, _cube.V110, _cube.V111, _cube.V101, cx1);
365         GetConv2DCoefs(*_cube.quad_Y0, meshFaces[_indY0]->GetSubShape(),
366                 _cube.V000, _cube.V100, _cube.V101, _cube.V001, cy0);
367         GetConv2DCoefs(*_cube.quad_Y1, meshFaces[_indY1]->GetSubShape(),
368                 _cube.V010, _cube.V110, _cube.V111, _cube.V011, cy1);
369         GetConv2DCoefs(*_cube.quad_Z0, meshFaces[_indZ0]->GetSubShape(),
370                 _cube.V000, _cube.V100, _cube.V110, _cube.V010, cz0);
371         GetConv2DCoefs(*_cube.quad_Z1, meshFaces[_indZ1]->GetSubShape(),
372                 _cube.V001, _cube.V101, _cube.V111, _cube.V011, cz1);
373
374         // 1.8 - create a 3D structure for normalized values
375
376         //MESSAGE("---");
377         int nbx = _cube.quad_Z0->nbPts[0];
378         if (cz0.a1 == 0.) nbx = _cube.quad_Z0->nbPts[1];
379  
380         int nby = _cube.quad_X0->nbPts[0];
381         if (cx0.a1 == 0.) nby = _cube.quad_X0->nbPts[1];
382  
383         int nbz = _cube.quad_Y0->nbPts[0];
384         if (cy0.a1 != 0.) nbz = _cube.quad_Y0->nbPts[1];
385 //      int nbx = _cube.quad_Y0->nbPts[0];
386 //      int nby = _cube.quad_Y0->nbPts[1];
387 //      int nbz;
388 //      if (cx0.a1 != 0)
389 //              nbz = _cube.quad_X0->nbPts[1];
390 //      else
391 //              nbz = _cube.quad_X0->nbPts[0];
392         //SCRUTE(nbx);
393         //SCRUTE(nby);
394         //SCRUTE(nbz);
395         int i1, j1, nbxyz = nbx * nby * nbz;
396         Point3DStruct *np = new Point3DStruct[nbxyz];
397
398         // 1.9 - store node indexes of faces
399
400         {
401                 const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX0]->GetSubShape());
402
403                 faceQuadStruct *quad = _cube.quad_X0;
404                 int i = 0;                              // j = x/face , k = y/face
405                 int nbdown = quad->nbPts[0];
406                 int nbright = quad->nbPts[1];
407
408
409                 SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
410                         
411                 while(itf->more())
412                 {
413                         const SMDS_MeshNode * node = itf->next();
414                         findIJ( node, quad, i1, j1 );
415                         int ij1 = j1 * nbdown + i1;
416                         quad->uv_grid[ij1].node = node;
417                 }
418
419                 for (int i1 = 0; i1 < nbdown; i1++)
420                         for (int j1 = 0; j1 < nbright; j1++)
421                         {
422                                 int ij1 = j1 * nbdown + i1;
423                                 int j = cx0.ia * i1 + cx0.ib * j1 + cx0.ic;     // j = x/face
424                                 int k = cx0.ja * i1 + cx0.jb * j1 + cx0.jc;     // k = y/face
425                                 int ijk = k * nbx * nby + j * nbx + i;
426                                 //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
427                                 np[ijk].node = quad->uv_grid[ij1].node;
428                                 //SCRUTE(np[ijk].nodeId);
429                         }
430         }
431
432         {
433                 const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX1]->GetSubShape());
434
435                 SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
436
437                 faceQuadStruct *quad = _cube.quad_X1;
438                 int i = nbx - 1;                // j = x/face , k = y/face
439                 int nbdown = quad->nbPts[0];
440                 int nbright = quad->nbPts[1];
441
442                 while(itf->more())
443                 {
444                         const SMDS_MeshNode * node = itf->next();
445                         findIJ( node, quad, i1, j1 );
446                         int ij1 = j1 * nbdown + i1;
447                         quad->uv_grid[ij1].node = node;
448                 }
449
450                 for (int i1 = 0; i1 < nbdown; i1++)
451                         for (int j1 = 0; j1 < nbright; j1++)
452                         {
453                                 int ij1 = j1 * nbdown + i1;
454                                 int j = cx1.ia * i1 + cx1.ib * j1 + cx1.ic;     // j = x/face
455                                 int k = cx1.ja * i1 + cx1.jb * j1 + cx1.jc;     // k = y/face
456                                 int ijk = k * nbx * nby + j * nbx + i;
457                                 //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
458                                 np[ijk].node = quad->uv_grid[ij1].node;
459                                 //SCRUTE(np[ijk].nodeId);
460                         }
461         }
462
463         {
464                 const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY0]->GetSubShape());
465
466                 SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
467
468                 faceQuadStruct *quad = _cube.quad_Y0;
469                 int j = 0;                              // i = x/face , k = y/face
470                 int nbdown = quad->nbPts[0];
471                 int nbright = quad->nbPts[1];
472
473                 while(itf->more())
474                 {
475                         const SMDS_MeshNode * node = itf->next();
476                         findIJ( node, quad, i1, j1 );
477                         int ij1 = j1 * nbdown + i1;
478                         quad->uv_grid[ij1].node = node;
479                 }
480
481                 for (int i1 = 0; i1 < nbdown; i1++)
482                         for (int j1 = 0; j1 < nbright; j1++)
483                         {
484                                 int ij1 = j1 * nbdown + i1;
485                                 int i = cy0.ia * i1 + cy0.ib * j1 + cy0.ic;     // i = x/face
486                                 int k = cy0.ja * i1 + cy0.jb * j1 + cy0.jc;     // k = y/face
487                                 int ijk = k * nbx * nby + j * nbx + i;
488                                 //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
489                                 np[ijk].node = quad->uv_grid[ij1].node;
490                                 //SCRUTE(np[ijk].nodeId);
491                         }
492         }
493
494         {
495                 const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY1]->GetSubShape());
496
497                 SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
498
499                 faceQuadStruct *quad = _cube.quad_Y1;
500                 int j = nby - 1;                // i = x/face , k = y/face
501                 int nbdown = quad->nbPts[0];
502                 int nbright = quad->nbPts[1];
503
504                 while(itf->more())
505                 {
506                         const SMDS_MeshNode * node = itf->next();
507                         findIJ( node, quad, i1, j1 );
508                         int ij1 = j1 * nbdown + i1;
509                         quad->uv_grid[ij1].node = node;
510                 }
511
512                 for (int i1 = 0; i1 < nbdown; i1++)
513                         for (int j1 = 0; j1 < nbright; j1++)
514                         {
515                                 int ij1 = j1 * nbdown + i1;
516                                 int i = cy1.ia * i1 + cy1.ib * j1 + cy1.ic;     // i = x/face
517                                 int k = cy1.ja * i1 + cy1.jb * j1 + cy1.jc;     // k = y/face
518                                 int ijk = k * nbx * nby + j * nbx + i;
519                                 //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
520                                 np[ijk].node = quad->uv_grid[ij1].node;
521                                 //SCRUTE(np[ijk].nodeId);
522                         }
523         }
524
525         {
526                 const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ0]->GetSubShape());
527
528                 SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
529
530                 faceQuadStruct *quad = _cube.quad_Z0;
531                 int k = 0;                              // i = x/face , j = y/face
532                 int nbdown = quad->nbPts[0];
533                 int nbright = quad->nbPts[1];
534
535                 while(itf->more())
536                 {
537                         const SMDS_MeshNode * node = itf->next();
538                         findIJ( node, quad, i1, j1 );
539                         int ij1 = j1 * nbdown + i1;
540                         quad->uv_grid[ij1].node = node;
541                 }
542
543                 for (int i1 = 0; i1 < nbdown; i1++)
544                         for (int j1 = 0; j1 < nbright; j1++)
545                         {
546                                 int ij1 = j1 * nbdown + i1;
547                                 int i = cz0.ia * i1 + cz0.ib * j1 + cz0.ic;     // i = x/face
548                                 int j = cz0.ja * i1 + cz0.jb * j1 + cz0.jc;     // j = y/face
549                                 int ijk = k * nbx * nby + j * nbx + i;
550                                 //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
551                                 np[ijk].node = quad->uv_grid[ij1].node;
552                                 //SCRUTE(np[ijk].nodeId);
553                         }
554         }
555
556         {
557                 const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ1]->GetSubShape());
558
559                 SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
560
561                 faceQuadStruct *quad = _cube.quad_Z1;
562                 int k = nbz - 1;                // i = x/face , j = y/face
563                 int nbdown = quad->nbPts[0];
564                 int nbright = quad->nbPts[1];
565
566                 while(itf->more())
567                 {
568                         const SMDS_MeshNode * node = itf->next();
569                         findIJ( node, quad, i1, j1 );
570                         int ij1 = j1 * nbdown + i1;
571                         quad->uv_grid[ij1].node = node;
572                 }
573
574                 for (int i1 = 0; i1 < nbdown; i1++)
575                         for (int j1 = 0; j1 < nbright; j1++)
576                         {
577                                 int ij1 = j1 * nbdown + i1;
578                                 int i = cz1.ia * i1 + cz1.ib * j1 + cz1.ic;     // i = x/face
579                                 int j = cz1.ja * i1 + cz1.jb * j1 + cz1.jc;     // j = y/face
580                                 int ijk = k * nbx * nby + j * nbx + i;
581                                 //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
582                                 np[ijk].node = quad->uv_grid[ij1].node;
583                                 //SCRUTE(np[ijk].nodeId);
584                         }
585         }
586
587         // 2.0 - for each node of the cube:
588         //       - get the 8 points 3D = 8 vertices of the cube
589         //       - get the 12 points 3D on the 12 edges of the cube
590         //       - get the 6 points 3D on the 6 faces with their ID
591         //       - compute the point 3D
592         //       - store the point 3D in SMESHDS, store its ID in 3D structure
593
594         TopoDS_Shell aShell;
595         TopExp_Explorer exp(aShape, TopAbs_SHELL);
596         if (exp.More())
597         {
598                 aShell = TopoDS::Shell(exp.Current());
599         }
600         else
601         {
602                 MESSAGE("no shell...");
603                 ASSERT(0);
604         }
605
606         Pt3 p000, p001, p010, p011, p100, p101, p110, p111;
607         Pt3 px00, px01, px10, px11;
608         Pt3 p0y0, p0y1, p1y0, p1y1;
609         Pt3 p00z, p01z, p10z, p11z;
610         Pt3 pxy0, pxy1, px0z, px1z, p0yz, p1yz;
611
612         GetPoint(p000, 0, 0, 0, nbx, nby, nbz, np, meshDS);
613         GetPoint(p001, 0, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
614         GetPoint(p010, 0, nby - 1, 0, nbx, nby, nbz, np, meshDS);
615         GetPoint(p011, 0, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
616         GetPoint(p100, nbx - 1, 0, 0, nbx, nby, nbz, np, meshDS);
617         GetPoint(p101, nbx - 1, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
618         GetPoint(p110, nbx - 1, nby - 1, 0, nbx, nby, nbz, np, meshDS);
619         GetPoint(p111, nbx - 1, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
620
621         for (int i = 1; i < nbx - 1; i++)
622         {
623                 for (int j = 1; j < nby - 1; j++)
624                 {
625                         for (int k = 1; k < nbz - 1; k++)
626                         {
627                                 // *** seulement maillage regulier
628                                 // 12 points on edges
629                                 GetPoint(px00, i, 0, 0, nbx, nby, nbz, np, meshDS);
630                                 GetPoint(px01, i, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
631                                 GetPoint(px10, i, nby - 1, 0, nbx, nby, nbz, np, meshDS);
632                                 GetPoint(px11, i, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
633
634                                 GetPoint(p0y0, 0, j, 0, nbx, nby, nbz, np, meshDS);
635                                 GetPoint(p0y1, 0, j, nbz - 1, nbx, nby, nbz, np, meshDS);
636                                 GetPoint(p1y0, nbx - 1, j, 0, nbx, nby, nbz, np, meshDS);
637                                 GetPoint(p1y1, nbx - 1, j, nbz - 1, nbx, nby, nbz, np, meshDS);
638
639                                 GetPoint(p00z, 0, 0, k, nbx, nby, nbz, np, meshDS);
640                                 GetPoint(p01z, 0, nby - 1, k, nbx, nby, nbz, np, meshDS);
641                                 GetPoint(p10z, nbx - 1, 0, k, nbx, nby, nbz, np, meshDS);
642                                 GetPoint(p11z, nbx - 1, nby - 1, k, nbx, nby, nbz, np, meshDS);
643
644                                 // 12 points on faces
645                                 GetPoint(pxy0, i, j, 0, nbx, nby, nbz, np, meshDS);
646                                 GetPoint(pxy1, i, j, nbz - 1, nbx, nby, nbz, np, meshDS);
647                                 GetPoint(px0z, i, 0, k, nbx, nby, nbz, np, meshDS);
648                                 GetPoint(px1z, i, nby - 1, k, nbx, nby, nbz, np, meshDS);
649                                 GetPoint(p0yz, 0, j, k, nbx, nby, nbz, np, meshDS);
650                                 GetPoint(p1yz, nbx - 1, j, k, nbx, nby, nbz, np, meshDS);
651
652                                 int ijk = k * nbx * nby + j * nbx + i;
653                                 double x = double (i) / double (nbx - 1);       // *** seulement
654                                 double y = double (j) / double (nby - 1);       // *** maillage
655                                 double z = double (k) / double (nbz - 1);       // *** regulier
656
657                                 Pt3 X;
658                                 for (int i = 0; i < 3; i++)
659                                 {
660                                         X[i] =
661                                                 (1 - x) * p0yz[i] + x * p1yz[i]
662                                                 + (1 - y) * px0z[i] + y * px1z[i]
663                                                 + (1 - z) * pxy0[i] + z * pxy1[i]
664                                                 - (1 - x) * ((1 - y) * p00z[i] + y * p01z[i])
665                                                 - x * ((1 - y) * p10z[i] + y * p11z[i])
666                                                 - (1 - y) * ((1 - z) * px00[i] + z * px01[i])
667                                                 - y * ((1 - z) * px10[i] + z * px11[i])
668                                                 - (1 - z) * ((1 - x) * p0y0[i] + x * p1y0[i])
669                                                 - z * ((1 - x) * p0y1[i] + x * p1y1[i])
670                                                 + (1 - x) * ((1 - y) * ((1 - z) * p000[i] + z * p001[i])
671                                                 + y * ((1 - z) * p010[i] + z * p011[i]))
672                                                 + x * ((1 - y) * ((1 - z) * p100[i] + z * p101[i])
673                                                 + y * ((1 - z) * p110[i] + z * p111[i]));
674                                 }
675
676                                 SMDS_MeshNode * node = meshDS->AddNode(X[0], X[1], X[2]);
677                                 np[ijk].node = node;
678                                 //meshDS->SetNodeInVolume(node, TopoDS::Solid(aShape));
679                                 meshDS->SetNodeInVolume(node, aShell);
680                         }
681                 }
682         }
683
684         //2.1 - for each node of the cube (less 3 *1 Faces):
685         //      - store hexahedron in SMESHDS
686         MESSAGE("Storing hexahedron into the DS");
687         for (int i = 0; i < nbx - 1; i++)
688                 for (int j = 0; j < nby - 1; j++)
689                         for (int k = 0; k < nbz - 1; k++)
690                         {
691                                 int n1 = k * nbx * nby + j * nbx + i;
692                                 int n2 = k * nbx * nby + j * nbx + i + 1;
693                                 int n3 = k * nbx * nby + (j + 1) * nbx + i + 1;
694                                 int n4 = k * nbx * nby + (j + 1) * nbx + i;
695                                 int n5 = (k + 1) * nbx * nby + j * nbx + i;
696                                 int n6 = (k + 1) * nbx * nby + j * nbx + i + 1;
697                                 int n7 = (k + 1) * nbx * nby + (j + 1) * nbx + i + 1;
698                                 int n8 = (k + 1) * nbx * nby + (j + 1) * nbx + i;
699
700 //    MESSAGE(" "<<n1<<" "<<n2<<" "<<n3<<" "<<n4<<" "<<n5<<" "<<n6<<" "<<n7<<" "<<n8);
701                                 //MESSAGE(" "<<np[n1].nodeId<<" "<<np[n2].nodeId<<" "<<np[n3].nodeId<<" "<<np[n4].nodeId<<" "<<np[n5].nodeId<<" "<<np[n6].nodeId<<" "<<np[n7].nodeId<<" "<<np[n8].nodeId);
702
703                                 SMDS_MeshVolume * elt = meshDS->AddVolume(np[n1].node,
704                                         np[n2].node,
705                                         np[n3].node,
706                                         np[n4].node,
707                                         np[n5].node,
708                                         np[n6].node,
709                                         np[n7].node,
710                                         np[n8].node);
711                                  ;
712                                 meshDS->SetMeshElementOnShape(elt, aShell);
713
714                                 // *** 5 tetrahedres ... verifier orientations,
715                                 //     mettre en coherence &vec quadrangles-> triangles
716                                 //     choisir afficher 1 parmi edges, face et volumes
717 //    int tetra1 = meshDS->AddVolume(np[n1].nodeId,
718 //                   np[n2].nodeId,
719 //                   np[n4].nodeId,
720 //                   np[n5].nodeId);
721 //    int tetra2 = meshDS->AddVolume(np[n2].nodeId,
722 //                   np[n3].nodeId,
723 //                   np[n4].nodeId,
724 //                   np[n7].nodeId);
725 //    int tetra3 = meshDS->AddVolume(np[n5].nodeId,
726 //                   np[n6].nodeId,
727 //                   np[n7].nodeId,
728 //                   np[n2].nodeId);
729 //    int tetra4 = meshDS->AddVolume(np[n5].nodeId,
730 //                   np[n7].nodeId,
731 //                   np[n8].nodeId,
732 //                   np[n4].nodeId);
733 //    int tetra5 = meshDS->AddVolume(np[n5].nodeId,
734 //                   np[n7].nodeId,
735 //                   np[n2].nodeId,
736 //                   np[n4].nodeId);
737
738                         }
739
740         //MESSAGE("End of StdMeshers_Hexa_3D::Compute()");
741         return true;
742 }
743
744 //=============================================================================
745 /*!
746  *  
747  */
748 //=============================================================================
749
750 void StdMeshers_Hexa_3D::GetPoint(Pt3 p, int i, int j, int k, int nbx, int nby,
751         int nbz, Point3DStruct * np, const SMESHDS_Mesh * meshDS)
752 {
753         int ijk = k * nbx * nby + j * nbx + i;
754         const SMDS_MeshNode * node = np[ijk].node;
755         p[0] = node->X();
756         p[1] = node->Y();
757         p[2] = node->Z();
758         //MESSAGE(" "<<i<<" "<<j<<" "<<k<<" "<<p[0]<<" "<<p[1]<<" "<<p[2]);
759 }
760
761 //=============================================================================
762 /*!
763  *  
764  */
765 //=============================================================================
766
767 int StdMeshers_Hexa_3D::GetFaceIndex(SMESH_Mesh & aMesh,
768         const TopoDS_Shape & aShape,
769         const vector < SMESH_subMesh * >&meshFaces,
770         const TopoDS_Vertex & V0,
771         const TopoDS_Vertex & V1,
772         const TopoDS_Vertex & V2, const TopoDS_Vertex & V3)
773 {
774         //MESSAGE("StdMeshers_Hexa_3D::GetFaceIndex");
775         int faceIndex = -1;
776         for (int i = 1; i < 6; i++)
777         {
778                 const TopoDS_Shape & aFace = meshFaces[i]->GetSubShape();
779                 //const TopoDS_Face& F = TopoDS::Face(aFace);
780                 TopTools_IndexedMapOfShape M;
781                 TopExp::MapShapes(aFace, TopAbs_VERTEX, M);
782                 bool verticesInShape = false;
783                 if (M.Contains(V0))
784                         if (M.Contains(V1))
785                                 if (M.Contains(V2))
786                                         if (M.Contains(V3))
787                                                 verticesInShape = true;
788                 if (verticesInShape)
789                 {
790                         faceIndex = i;
791                         break;
792                 }
793         }
794         ASSERT(faceIndex > 0);
795         //SCRUTE(faceIndex);
796         return faceIndex;
797 }
798
799 //=============================================================================
800 /*!
801  *  
802  */
803 //=============================================================================
804
805 TopoDS_Edge
806         StdMeshers_Hexa_3D::EdgeNotInFace(SMESH_Mesh & aMesh,
807         const TopoDS_Shape & aShape,
808         const TopoDS_Face & aFace,
809         const TopoDS_Vertex & aVertex,
810         const TopTools_IndexedDataMapOfShapeListOfShape & MS)
811 {
812         //MESSAGE("StdMeshers_Hexa_3D::EdgeNotInFace");
813         TopTools_IndexedDataMapOfShapeListOfShape MF;
814         TopExp::MapShapesAndAncestors(aFace, TopAbs_VERTEX, TopAbs_EDGE, MF);
815         const TopTools_ListOfShape & ancestorsInSolid = MS.FindFromKey(aVertex);
816         const TopTools_ListOfShape & ancestorsInFace = MF.FindFromKey(aVertex);
817 //      SCRUTE(ancestorsInSolid.Extent());
818 //      SCRUTE(ancestorsInFace.Extent());
819         ASSERT(ancestorsInSolid.Extent() == 6); // 6 (edges doublees)
820         ASSERT(ancestorsInFace.Extent() == 2);
821
822         TopoDS_Edge E;
823         E.Nullify();
824         TopTools_ListIteratorOfListOfShape its(ancestorsInSolid);
825         for (; its.More(); its.Next())
826         {
827                 TopoDS_Shape ancestor = its.Value();
828                 TopTools_ListIteratorOfListOfShape itf(ancestorsInFace);
829                 bool isInFace = false;
830                 for (; itf.More(); itf.Next())
831                 {
832                         TopoDS_Shape ancestorInFace = itf.Value();
833                         if (ancestorInFace.IsSame(ancestor))
834                         {
835                                 isInFace = true;
836                                 break;
837                         }
838                 }
839                 if (!isInFace)
840                 {
841                         E = TopoDS::Edge(ancestor);
842                         break;
843                 }
844         }
845         return E;
846 }
847
848 //=============================================================================
849 /*!
850  *  
851  */
852 //=============================================================================
853
854 void StdMeshers_Hexa_3D::GetConv2DCoefs(const faceQuadStruct & quad,
855         const TopoDS_Shape & aShape,
856         const TopoDS_Vertex & V0,
857         const TopoDS_Vertex & V1,
858         const TopoDS_Vertex & V2, const TopoDS_Vertex & V3, Conv2DStruct & conv)
859 {
860 //      MESSAGE("StdMeshers_Hexa_3D::GetConv2DCoefs");
861         const TopoDS_Face & F = TopoDS::Face(aShape);
862         TopoDS_Edge E = quad.edge[0];
863         double f, l;
864         Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
865         TopoDS_Vertex VFirst, VLast;
866         TopExp::Vertices(E, VFirst, VLast);     // corresponds to f and l
867         bool isForward = (((l - f) * (quad.last[0] - quad.first[0])) > 0);
868         TopoDS_Vertex VA, VB;
869         if (isForward)
870         {
871                 VA = VFirst;
872                 VB = VLast;
873         }
874         else
875         {
876                 VA = VLast;
877                 VB = VFirst;
878         }
879         int a1, b1, c1, a2, b2, c2;
880         if (VA.IsSame(V0))
881                 if (VB.IsSame(V1))
882                 {
883                         a1 = 1;
884                         b1 = 0;
885                         c1 = 0;                         // x
886                         a2 = 0;
887                         b2 = 1;
888                         c2 = 0;                         // y
889                 }
890                 else
891                 {
892                         ASSERT(VB.IsSame(V3));
893                         a1 = 0;
894                         b1 = 1;
895                         c1 = 0;                         // y
896                         a2 = 1;
897                         b2 = 0;
898                         c2 = 0;                         // x
899                 }
900         if (VA.IsSame(V1))
901                 if (VB.IsSame(V2))
902                 {
903                         a1 = 0;
904                         b1 = -1;
905                         c1 = 1;                         // 1-y
906                         a2 = 1;
907                         b2 = 0;
908                         c2 = 0;                         // x
909                 }
910                 else
911                 {
912                         ASSERT(VB.IsSame(V0));
913                         a1 = -1;
914                         b1 = 0;
915                         c1 = 1;                         // 1-x
916                         a2 = 0;
917                         b2 = 1;
918                         c2 = 0;                         // y
919                 }
920         if (VA.IsSame(V2))
921                 if (VB.IsSame(V3))
922                 {
923                         a1 = -1;
924                         b1 = 0;
925                         c1 = 1;                         // 1-x
926                         a2 = 0;
927                         b2 = -1;
928                         c2 = 1;                         // 1-y
929                 }
930                 else
931                 {
932                         ASSERT(VB.IsSame(V1));
933                         a1 = 0;
934                         b1 = -1;
935                         c1 = 1;                         // 1-y
936                         a2 = -1;
937                         b2 = 0;
938                         c2 = 1;                         // 1-x
939                 }
940         if (VA.IsSame(V3))
941                 if (VB.IsSame(V0))
942                 {
943                         a1 = 0;
944                         b1 = 1;
945                         c1 = 0;                         // y
946                         a2 = -1;
947                         b2 = 0;
948                         c2 = 1;                         // 1-x
949                 }
950                 else
951                 {
952                         ASSERT(VB.IsSame(V2));
953                         a1 = 1;
954                         b1 = 0;
955                         c1 = 0;                         // x
956                         a2 = 0;
957                         b2 = -1;
958                         c2 = 1;                         // 1-y
959                 }
960 //      MESSAGE("X = " << c1 << "+ " << a1 << "*x + " << b1 << "*y");
961 //      MESSAGE("Y = " << c2 << "+ " << a2 << "*x + " << b2 << "*y");
962         conv.a1 = a1;
963         conv.b1 = b1;
964         conv.c1 = c1;
965         conv.a2 = a2;
966         conv.b2 = b2;
967         conv.c2 = c2;
968
969         int nbdown = quad.nbPts[0];
970         int nbright = quad.nbPts[1];
971         conv.ia = int (a1);
972         conv.ib = int (b1);
973         conv.ic =
974                 int (c1 * a1 * a1) * (nbdown - 1) + int (c1 * b1 * b1) * (nbright - 1);
975         conv.ja = int (a2);
976         conv.jb = int (b2);
977         conv.jc =
978                 int (c2 * a2 * a2) * (nbdown - 1) + int (c2 * b2 * b2) * (nbright - 1);
979 //      MESSAGE("I " << conv.ia << " " << conv.ib << " " << conv.ic);
980 //      MESSAGE("J " << conv.ja << " " << conv.jb << " " << conv.jc);
981 }
982
983 //=============================================================================
984 /*!
985  *  
986  */
987 //=============================================================================
988
989 ostream & StdMeshers_Hexa_3D::SaveTo(ostream & save)
990 {
991   return save;
992 }
993
994 //=============================================================================
995 /*!
996  *  
997  */
998 //=============================================================================
999
1000 istream & StdMeshers_Hexa_3D::LoadFrom(istream & load)
1001 {
1002   return load;
1003 }
1004
1005 //=============================================================================
1006 /*!
1007  *  
1008  */
1009 //=============================================================================
1010
1011 ostream & operator <<(ostream & save, StdMeshers_Hexa_3D & hyp)
1012 {
1013   return hyp.SaveTo( save );
1014 }
1015
1016 //=============================================================================
1017 /*!
1018  *  
1019  */
1020 //=============================================================================
1021
1022 istream & operator >>(istream & load, StdMeshers_Hexa_3D & hyp)
1023 {
1024   return hyp.LoadFrom( load );
1025 }