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