Salome HOME
0020279: [CEA 334] control the "random" use when using mesh algorithms
[modules/smesh.git] / src / StdMeshers / StdMeshers_QuadToTriaAdaptor.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH SMESH : implementaion of SMESH idl descriptions
23 // File      : StdMeshers_QuadToTriaAdaptor.cxx
24 // Module    : SMESH
25 // Created   : Wen May 07 16:37:07 2008
26 // Author    : Sergey KUUL (skl)
27 //
28 #include "StdMeshers_QuadToTriaAdaptor.hxx"
29
30 #include <SMDS_FaceOfNodes.hxx>
31 #include <SMESH_Algo.hxx>
32 #include <SMESH_MesherHelper.hxx>
33
34 #include <IntAna_IntConicQuad.hxx>
35 #include <IntAna_Quadric.hxx>
36 #include <TColStd_SequenceOfInteger.hxx>
37 #include <TColgp_HSequenceOfPnt.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopoDS.hxx>
40 #include <gp_Lin.hxx>
41 #include <gp_Pln.hxx>
42
43 #include <NCollection_Array1.hxx>
44 typedef NCollection_Array1<TColStd_SequenceOfInteger> StdMeshers_Array1OfSequenceOfInteger;
45
46
47 //=======================================================================
48 //function : StdMeshers_QuadToTriaAdaptor
49 //purpose  : 
50 //=======================================================================
51
52 StdMeshers_QuadToTriaAdaptor::StdMeshers_QuadToTriaAdaptor()
53 {
54 }
55
56
57 //================================================================================
58 /*!
59  * \brief Destructor
60  */
61 //================================================================================
62
63 StdMeshers_QuadToTriaAdaptor::~StdMeshers_QuadToTriaAdaptor()
64 {
65   // delete temporary faces
66   map< const SMDS_MeshElement*, list<const SMDS_FaceOfNodes*> >::iterator
67     f_f = myResMap.begin(), ffEnd = myResMap.end();
68   for ( ; f_f != ffEnd; ++f_f )
69   {
70     list<const SMDS_FaceOfNodes*>& fList = f_f->second;
71     list<const SMDS_FaceOfNodes*>::iterator f = fList.begin(), fEnd = fList.end();
72     for ( ; f != fEnd; ++f )
73       delete *f;
74   }
75   myResMap.clear();
76
77 //   TF2PyramMap::iterator itp = myMapFPyram.begin();
78 //   for(; itp!=myMapFPyram.end(); itp++)
79 //     cout << itp->second << endl;
80 }
81
82
83 //=======================================================================
84 //function : FindBestPoint
85 //purpose  : Auxilare for Compute()
86 //           V - normal to (P1,P2,PC)
87 //=======================================================================
88 static gp_Pnt FindBestPoint(const gp_Pnt& P1, const gp_Pnt& P2,
89                             const gp_Pnt& PC, const gp_Vec& V)
90 {
91   double a = P1.Distance(P2);
92   double b = P1.Distance(PC);
93   double c = P2.Distance(PC);
94   if( a < (b+c)/2 )
95     return PC;
96   else {
97     // find shift along V in order to a became equal to (b+c)/2
98     double shift = sqrt( a*a + (b*b-c*c)*(b*b-c*c)/16/a/a - (b*b+c*c)/2 );
99     gp_Dir aDir(V);
100     gp_Pnt Pbest( PC.X() + aDir.X()*shift,  PC.Y() + aDir.Y()*shift,
101                   PC.Z() + aDir.Z()*shift );
102     return Pbest;
103   }
104 }
105
106
107 //=======================================================================
108 //function : HasIntersection3
109 //purpose  : Auxilare for HasIntersection()
110 //           find intersection point between triangle (P1,P2,P3)
111 //           and segment [PC,P]
112 //=======================================================================
113 static bool HasIntersection3(const gp_Pnt& P, const gp_Pnt& PC, gp_Pnt& Pint,
114                              const gp_Pnt& P1, const gp_Pnt& P2, const gp_Pnt& P3)
115 {
116   //cout<<"HasIntersection3"<<endl;
117   //cout<<"  PC("<<PC.X()<<","<<PC.Y()<<","<<PC.Z()<<")"<<endl;
118   //cout<<"  P("<<P.X()<<","<<P.Y()<<","<<P.Z()<<")"<<endl;
119   //cout<<"  P1("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
120   //cout<<"  P2("<<P2.X()<<","<<P2.Y()<<","<<P2.Z()<<")"<<endl;
121   //cout<<"  P3("<<P3.X()<<","<<P3.Y()<<","<<P3.Z()<<")"<<endl;
122   gp_Vec VP1(P1,P2);
123   gp_Vec VP2(P1,P3);
124   IntAna_Quadric IAQ(gp_Pln(P1,VP1.Crossed(VP2)));
125   IntAna_IntConicQuad IAICQ(gp_Lin(PC,gp_Dir(gp_Vec(PC,P))),IAQ);
126   if(IAICQ.IsDone()) {
127     if( IAICQ.IsInQuadric() )
128       return false;
129     if( IAICQ.NbPoints() == 1 ) {
130       gp_Pnt PIn = IAICQ.Point(1);
131       double preci = 1.e-6;
132       // check if this point is internal for segment [PC,P]
133       bool IsExternal =
134         ( (PC.X()-PIn.X())*(P.X()-PIn.X()) > preci ) ||
135         ( (PC.Y()-PIn.Y())*(P.Y()-PIn.Y()) > preci ) ||
136         ( (PC.Z()-PIn.Z())*(P.Z()-PIn.Z()) > preci );
137       if(IsExternal) {
138         return false;
139       }
140       // check if this point is internal for triangle (P1,P2,P3)
141       gp_Vec V1(PIn,P1);
142       gp_Vec V2(PIn,P2);
143       gp_Vec V3(PIn,P3);
144       if( V1.Magnitude()<preci || V2.Magnitude()<preci ||
145           V3.Magnitude()<preci ) {
146         Pint = PIn;
147         return true;
148       }
149       gp_Vec VC1 = V1.Crossed(V2);
150       gp_Vec VC2 = V2.Crossed(V3);
151       gp_Vec VC3 = V3.Crossed(V1);
152       if(VC1.Magnitude()<preci) {
153         if(VC2.IsOpposite(VC3,preci)) {
154           return false;
155         }
156       }
157       else if(VC2.Magnitude()<preci) {
158         if(VC1.IsOpposite(VC3,preci)) {
159           return false;
160         }
161       }
162       else if(VC3.Magnitude()<preci) {
163         if(VC1.IsOpposite(VC2,preci)) {
164           return false;
165         }
166       }
167       else {
168         if( VC1.IsOpposite(VC2,preci) || VC1.IsOpposite(VC3,preci) ||
169             VC2.IsOpposite(VC3,preci) ) {
170           return false;
171         }
172       }
173       Pint = PIn;
174       return true;
175     }
176   }
177
178   return false;
179 }
180
181
182 //=======================================================================
183 //function : HasIntersection
184 //purpose  : Auxilare for CheckIntersection()
185 //=======================================================================
186 static bool HasIntersection(const gp_Pnt& P, const gp_Pnt& PC, gp_Pnt& Pint,
187                             Handle(TColgp_HSequenceOfPnt)& aContour)
188 {
189   if(aContour->Length()==3) {
190     return HasIntersection3( P, PC, Pint, aContour->Value(1),
191                              aContour->Value(2), aContour->Value(3) );
192   }
193   else {
194     bool check = false;
195     if( (aContour->Value(1).Distance(aContour->Value(2)) > 1.e-6) &&
196         (aContour->Value(1).Distance(aContour->Value(3)) > 1.e-6) &&
197         (aContour->Value(2).Distance(aContour->Value(3)) > 1.e-6) ) {
198       check = HasIntersection3( P, PC, Pint, aContour->Value(1),
199                                 aContour->Value(2), aContour->Value(3) );
200     }
201     if(check) return true;
202     if( (aContour->Value(1).Distance(aContour->Value(4)) > 1.e-6) &&
203         (aContour->Value(1).Distance(aContour->Value(3)) > 1.e-6) &&
204         (aContour->Value(4).Distance(aContour->Value(3)) > 1.e-6) ) {
205       check = HasIntersection3( P, PC, Pint, aContour->Value(1),
206                                 aContour->Value(3), aContour->Value(4) );
207     }
208     if(check) return true;
209   }
210
211   return false;
212 }
213
214
215 //=======================================================================
216 //function : CheckIntersection
217 //purpose  : Auxilare for Compute()
218 //           NotCheckedFace - for optimization
219 //=======================================================================
220 bool StdMeshers_QuadToTriaAdaptor::CheckIntersection
221                        (const gp_Pnt& P, const gp_Pnt& PC,
222                         gp_Pnt& Pint, SMESH_Mesh& aMesh,
223                         const TopoDS_Shape& aShape,
224                         const TopoDS_Shape& NotCheckedFace)
225 {
226   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
227   //cout<<"    CheckIntersection: meshDS->NbFaces() = "<<meshDS->NbFaces()<<endl;
228   bool res = false;
229   double dist = RealLast();
230   gp_Pnt Pres;
231   for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
232     const TopoDS_Shape& aShapeFace = exp.Current();
233     if(aShapeFace==NotCheckedFace)
234       continue;
235     const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements(aShapeFace);
236     if ( aSubMeshDSFace ) {
237       SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
238       while ( iteratorElem->more() ) { // loop on elements on a face
239         const SMDS_MeshElement* face = iteratorElem->next();
240         Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
241         SMDS_ElemIteratorPtr nodeIt = face->nodesIterator();
242         if( !face->IsQuadratic() ) {
243           while ( nodeIt->more() ) {
244             const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
245             aContour->Append(gp_Pnt(node->X(), node->Y(), node->Z()));
246           }
247         }
248         else {
249           int nn = 0;
250           while ( nodeIt->more() ) {
251             nn++;
252             const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
253             aContour->Append(gp_Pnt(node->X(), node->Y(), node->Z()));
254             if(nn==face->NbNodes()/2) break;
255           }
256         }
257         if( HasIntersection(P, PC, Pres, aContour) ) {
258           res = true;
259           double tmp = PC.Distance(Pres);
260           if(tmp<dist) {
261             Pint = Pres;
262             dist = tmp;
263           }
264         }
265       }
266     }
267   }
268   return res;
269 }
270
271
272 //=======================================================================
273 //function : CompareTrias
274 //purpose  : Auxilare for Compute()
275 //=======================================================================
276 static bool CompareTrias(const SMDS_MeshElement* F1,const SMDS_MeshElement* F2)
277 {
278   SMDS_ElemIteratorPtr nIt = F1->nodesIterator();
279   const SMDS_MeshNode* Ns1[3];
280   int k = 0;
281   while( nIt->more() ) {
282     Ns1[k] = static_cast<const SMDS_MeshNode*>( nIt->next() );
283     k++;
284   }
285   nIt = F2->nodesIterator();
286   const SMDS_MeshNode* Ns2[3];
287   k = 0;
288   while( nIt->more() ) {
289     Ns2[k] = static_cast<const SMDS_MeshNode*>( nIt->next() );
290     k++;
291   }
292   if( ( Ns1[1]==Ns2[1] && Ns1[2]==Ns2[2] ) ||
293       ( Ns1[1]==Ns2[2] && Ns1[2]==Ns2[1] ) )
294     return true;
295   return false;
296 }
297
298
299 //=======================================================================
300 //function : IsDegenarate
301 //purpose  : Auxilare for Preparation()
302 //=======================================================================
303 // static int IsDegenarate(const Handle(TColgp_HArray1OfPnt)& PN)
304 // {
305 //   int i = 1;
306 //   for(; i<4; i++) {
307 //     int j = i+1;
308 //     for(; j<=4; j++) {
309 //       if( PN->Value(i).Distance(PN->Value(j)) < 1.e-6 )
310 //         return j;
311 //     }
312 //   }
313 //   return 0;
314 // }
315
316
317 //=======================================================================
318 //function : Preparation
319 //purpose  : Auxilare for Compute()
320 //         : Return 0 if given face is not quad,
321 //                  1 if given face is quad,
322 //                  2 if given face is degenerate quad (two nodes are coincided)
323 //=======================================================================
324 int StdMeshers_QuadToTriaAdaptor::Preparation(const SMDS_MeshElement* face,
325                                               Handle(TColgp_HArray1OfPnt)& PN,
326                                               Handle(TColgp_HArray1OfVec)& VN,
327                                               std::vector<const SMDS_MeshNode*>& FNodes,
328                                               gp_Pnt& PC, gp_Vec& VNorm)
329 {
330   int i = 0;
331   double xc=0., yc=0., zc=0.;
332   SMDS_ElemIteratorPtr nodeIt = face->nodesIterator();
333   if( !face->IsQuadratic() ) {
334     if( face->NbNodes() != 4 )
335       return 0;
336     while ( nodeIt->more() ) {
337       i++;
338       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
339       FNodes[i-1] = node;
340       PN->SetValue( i, gp_Pnt(node->X(), node->Y(), node->Z()) );
341       xc += node->X();
342       yc += node->Y();
343       zc += node->Z();
344     }
345   }
346   else {
347     if( face->NbNodes() != 8)
348       return 0;
349     while ( nodeIt->more() ) {
350       i++;
351       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
352       FNodes[i-1] = node;
353       PN->SetValue( i, gp_Pnt(node->X(), node->Y(), node->Z()) );
354       xc += node->X();
355       yc += node->Y();
356       zc += node->Z();
357       if(i==4) break;
358     }
359   }
360
361   int nbp = 4;
362
363   int j = 0;
364   for(i=1; i<4; i++) {
365     j = i+1;
366     for(; j<=4; j++) {
367       if( PN->Value(i).Distance(PN->Value(j)) < 1.e-6 )
368         break;
369     }
370     if(j<=4) break;
371   }
372   //int deg_num = IsDegenarate(PN);
373   //if(deg_num>0) {
374   bool hasdeg = false;
375   if(i<4) {
376     //cout<<"find degeneration"<<endl;
377     hasdeg = true;
378     gp_Pnt Pdeg = PN->Value(i);
379
380     std::list< const SMDS_MeshNode* >::iterator itdg = myDegNodes.begin();
381     const SMDS_MeshNode* DegNode = 0;
382     for(; itdg!=myDegNodes.end(); itdg++) {
383       const SMDS_MeshNode* N = (*itdg);
384       gp_Pnt Ptmp(N->X(),N->Y(),N->Z());
385       if(Pdeg.Distance(Ptmp)<1.e-6) {
386         DegNode = N;
387         //DegNode = const_cast<SMDS_MeshNode*>(N);
388         break;
389       }
390     }
391     if(!DegNode) {
392       DegNode = FNodes[i-1];
393       myDegNodes.push_back(DegNode);
394     }
395     else {
396       FNodes[i-1] = DegNode;
397     }
398     for(i=j; i<4; i++) {
399       PN->SetValue(i,PN->Value(i+1));
400       FNodes[i-1] = FNodes[i];
401     }
402     nbp = 3;
403     //PC = gp_Pnt( PN->Value(1).X() + PN.Value
404   }
405
406   PC = gp_Pnt(xc/4., yc/4., zc/4.);
407   //cout<<"  PC("<<PC.X()<<","<<PC.Y()<<","<<PC.Z()<<")"<<endl;
408
409   //PN->SetValue(5,PN->Value(1));
410   PN->SetValue(nbp+1,PN->Value(1));
411   //FNodes[4] = FNodes[0];
412   FNodes[nbp] = FNodes[0];
413   // find normal direction
414   //gp_Vec V1(PC,PN->Value(4));
415   gp_Vec V1(PC,PN->Value(nbp));
416   gp_Vec V2(PC,PN->Value(1));
417   VNorm = V1.Crossed(V2);
418   //VN->SetValue(4,VNorm);
419   VN->SetValue(nbp,VNorm);
420   //for(i=1; i<4; i++) {
421   for(i=1; i<nbp; i++) {
422     V1 = gp_Vec(PC,PN->Value(i));
423     V2 = gp_Vec(PC,PN->Value(i+1));
424     gp_Vec Vtmp = V1.Crossed(V2);
425     VN->SetValue(i,Vtmp);
426     VNorm += Vtmp;
427   }
428   //cout<<"  VNorm("<<VNorm.X()<<","<<VNorm.Y()<<","<<VNorm.Z()<<")"<<endl;
429   if(hasdeg) return 2;
430   return 1;
431 }
432
433
434 //=======================================================================
435 //function : Compute
436 //purpose  : 
437 //=======================================================================
438
439 bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape)
440 {
441   myResMap.clear();
442   myMapFPyram.clear();
443
444   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
445   SMESH_MesherHelper helper(aMesh);
446   helper.IsQuadraticSubMesh(aShape);
447   helper.SetElementsOnShape( true );
448
449   for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
450     const TopoDS_Shape& aShapeFace = exp.Current();
451     const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace );
452     if ( aSubMeshDSFace ) {
453       bool isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );
454
455       SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
456       while ( iteratorElem->more() ) { // loop on elements on a face
457         const SMDS_MeshElement* face = iteratorElem->next();
458         //cout<<endl<<"================= face->GetID() = "<<face->GetID()<<endl;
459         // preparation step using face info
460         Handle(TColgp_HArray1OfPnt) PN = new TColgp_HArray1OfPnt(1,5);
461         Handle(TColgp_HArray1OfVec) VN = new TColgp_HArray1OfVec(1,4);
462         std::vector<const SMDS_MeshNode*> FNodes(5);
463         gp_Pnt PC;
464         gp_Vec VNorm;
465         int stat =  Preparation(face, PN, VN, FNodes, PC, VNorm);
466         if(stat==0)
467           continue;
468
469         if(stat==2) {
470           // degenerate face
471           // add triangles to result map
472           std::list<const SMDS_FaceOfNodes*> aList;
473           SMDS_FaceOfNodes* NewFace;
474           if(!isRev)
475             NewFace = new SMDS_FaceOfNodes( FNodes[0], FNodes[1], FNodes[2] );
476           else
477             NewFace = new SMDS_FaceOfNodes( FNodes[0], FNodes[2], FNodes[1] );
478           aList.push_back(NewFace);
479           myResMap.insert(make_pair(face,aList));
480           continue;
481         }
482
483         if(!isRev) VNorm.Reverse();
484         double xc = 0., yc = 0., zc = 0.;
485         int i = 1;
486         for(; i<=4; i++) {
487           gp_Pnt Pbest;
488           if(!isRev)
489             Pbest = FindBestPoint(PN->Value(i), PN->Value(i+1), PC, VN->Value(i).Reversed());
490           else
491             Pbest = FindBestPoint(PN->Value(i), PN->Value(i+1), PC, VN->Value(i));
492           xc += Pbest.X();
493           yc += Pbest.Y();
494           zc += Pbest.Z();
495         }
496         gp_Pnt PCbest(xc/4., yc/4., zc/4.);
497
498         // check PCbest
499         double height = PCbest.Distance(PC);
500         if(height<1.e-6) {
501           // create new PCbest using a bit shift along VNorm
502           PCbest = PC.XYZ() + VNorm.XYZ() * 0.001;
503         }
504         else {
505           // check possible intersection with other faces
506           gp_Pnt Pint;
507           bool check = CheckIntersection(PCbest, PC, Pint, aMesh, aShape, aShapeFace);
508           if(check) {
509             //cout<<"--PC("<<PC.X()<<","<<PC.Y()<<","<<PC.Z()<<")"<<endl;
510             //cout<<"  PCbest("<<PCbest.X()<<","<<PCbest.Y()<<","<<PCbest.Z()<<")"<<endl;
511             double dist = PC.Distance(Pint)/3.;
512             gp_Dir aDir(gp_Vec(PC,PCbest));
513             PCbest = PC.XYZ() + aDir.XYZ() * dist;
514           }
515           else {
516             gp_Vec VB(PC,PCbest);
517             gp_Pnt PCbestTmp = PC.XYZ() + VB.XYZ() * 3.0;
518             bool check = CheckIntersection(PCbestTmp, PC, Pint, aMesh, aShape, aShapeFace);
519             if(check) {
520               double dist = PC.Distance(Pint)/3.;
521               if(dist<height) {
522                 gp_Dir aDir(gp_Vec(PC,PCbest));
523                 PCbest = PC.XYZ() + aDir.XYZ() * dist;
524               }
525             }
526           }
527         }
528         // create node for PCbest
529         SMDS_MeshNode* NewNode = helper.AddNode( PCbest.X(), PCbest.Y(), PCbest.Z() );
530         // add triangles to result map
531         std::list<const SMDS_FaceOfNodes*> aList;
532         for(i=0; i<4; i++) {
533           SMDS_FaceOfNodes* NewFace = new SMDS_FaceOfNodes( NewNode, FNodes[i], FNodes[i+1] );
534           aList.push_back(NewFace);
535         }
536         myResMap.insert(make_pair(face,aList));
537         // create pyramid
538         SMDS_MeshVolume* aPyram =
539           helper.AddVolume( FNodes[0], FNodes[1], FNodes[2], FNodes[3], NewNode );
540         myMapFPyram.insert(make_pair(face,aPyram));
541       } // end loop on elements on a face
542     }
543   } // end for(TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next()) {
544
545   return Compute2ndPart(aMesh);
546 }
547
548
549 //=======================================================================
550 //function : Compute
551 //purpose  : 
552 //=======================================================================
553
554 bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh)
555 {
556   myResMap.clear();
557   myMapFPyram.clear();
558   SMESH_MesherHelper helper(aMesh);
559   helper.IsQuadraticSubMesh(aMesh.GetShapeToMesh());
560   helper.SetElementsOnShape( true );
561
562   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
563
564   SMDS_FaceIteratorPtr fIt = meshDS->facesIterator();
565   TIDSortedElemSet sortedFaces; //  0020279: control the "random" use when using mesh algorithms
566   while( fIt->more()) sortedFaces.insert( fIt->next() );
567
568   TIDSortedElemSet::iterator itFace = sortedFaces.begin(), fEnd = sortedFaces.end();
569   for ( ; itFace != fEnd; ++itFace )
570   {
571     const SMDS_MeshElement* face = *itFace;
572     if ( !face ) continue;
573     //cout<<endl<<"================= face->GetID() = "<<face->GetID()<<endl;
574     // preparation step using face info
575     Handle(TColgp_HArray1OfPnt) PN = new TColgp_HArray1OfPnt(1,5);
576     Handle(TColgp_HArray1OfVec) VN = new TColgp_HArray1OfVec(1,4);
577     std::vector<const SMDS_MeshNode*> FNodes(5);
578     gp_Pnt PC;
579     gp_Vec VNorm;
580
581     int stat =  Preparation(face, PN, VN, FNodes, PC, VNorm);
582     if(stat==0)
583       continue;
584
585     if(stat==2) {
586       // degenerate face
587       // add triangles to result map
588       std::list<const SMDS_FaceOfNodes*> aList;
589       SMDS_FaceOfNodes* NewFace;
590       // check orientation
591
592       double tmp = PN->Value(1).Distance(PN->Value(2)) +
593         PN->Value(2).Distance(PN->Value(3));
594       gp_Pnt Ptmp1 = PC.XYZ() + VNorm.XYZ() * tmp * 1.e6;
595       gp_Pnt Ptmp2 = PC.XYZ() - VNorm.XYZ() * tmp * 1.e6;
596       // check intersection for Ptmp1 and Ptmp2
597       bool IsRev = false;
598       bool IsOK1 = false;
599       bool IsOK2 = false;
600       double dist1 = RealLast();
601       double dist2 = RealLast();
602       gp_Pnt Pres1,Pres2;
603       for (TIDSortedElemSet::iterator itF = sortedFaces.begin(); itF != fEnd; ++itF ) {
604         const SMDS_MeshElement* F = *itF;
605         if(F==face) continue;
606         Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
607         SMDS_ElemIteratorPtr nodeIt = F->nodesIterator();
608         if( !F->IsQuadratic() ) {
609           while ( nodeIt->more() ) {
610             const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
611             aContour->Append(gp_Pnt(node->X(), node->Y(), node->Z()));
612           }
613         }
614         else {
615           int nn = 0;
616           while ( nodeIt->more() ) {
617             nn++;
618             const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
619             aContour->Append(gp_Pnt(node->X(), node->Y(), node->Z()));
620             if(nn==face->NbNodes()/2) break;
621           }
622         }
623         gp_Pnt PPP;
624         if( HasIntersection(Ptmp1, PC, PPP, aContour) ) {
625           IsOK1 = true;
626           double tmp = PC.Distance(PPP);
627           if(tmp<dist1) {
628             Pres1 = PPP;
629             dist1 = tmp;
630           }
631         }
632         if( HasIntersection(Ptmp2, PC, PPP, aContour) ) {
633           IsOK2 = true;
634           double tmp = PC.Distance(PPP);
635           if(tmp<dist2) {
636             Pres2 = PPP;
637             dist2 = tmp;
638           }
639         }
640       }
641
642       if( IsOK1 && !IsOK2 ) {
643         // using existed direction
644       }
645       else if( !IsOK1 && IsOK2 ) {
646         // using opposite direction
647         IsRev = true;
648       }
649       else { // IsOK1 && IsOK2
650         double tmp1 = PC.Distance(Pres1)/3.;
651         double tmp2 = PC.Distance(Pres2)/3.;
652         if(tmp1<tmp2) {
653           // using existed direction
654         }
655         else {
656           // using opposite direction
657           IsRev = true;
658         }
659       }
660       if(!IsRev)
661         NewFace = new SMDS_FaceOfNodes( FNodes[0], FNodes[1], FNodes[2] );
662       else
663         NewFace = new SMDS_FaceOfNodes( FNodes[0], FNodes[2], FNodes[1] );
664       aList.push_back(NewFace);
665       myResMap.insert(make_pair(face,aList));
666       continue;
667     }
668     
669     double xc = 0., yc = 0., zc = 0.;
670     int i = 1;
671     for(; i<=4; i++) {
672       gp_Pnt Pbest = FindBestPoint(PN->Value(i), PN->Value(i+1), PC, VN->Value(i));
673       xc += Pbest.X();
674       yc += Pbest.Y();
675       zc += Pbest.Z();
676     }
677     gp_Pnt PCbest(xc/4., yc/4., zc/4.);
678     double height = PCbest.Distance(PC);
679     if(height<1.e-6) {
680       // create new PCbest using a bit shift along VNorm
681       PCbest = PC.XYZ() + VNorm.XYZ() * 0.001;
682       height = PCbest.Distance(PC);
683     }
684     //cout<<"  PCbest("<<PCbest.X()<<","<<PCbest.Y()<<","<<PCbest.Z()<<")"<<endl;
685
686     gp_Vec V1(PC,PCbest);
687     double tmp = PN->Value(1).Distance(PN->Value(3)) +
688       PN->Value(2).Distance(PN->Value(4));
689     gp_Dir tmpDir(V1);
690     gp_Pnt Ptmp1 = PC.XYZ() + tmpDir.XYZ() * tmp * 1.e6;
691     gp_Pnt Ptmp2 = PC.XYZ() - tmpDir.XYZ() * tmp * 1.e6;
692     // check intersection for Ptmp1 and Ptmp2
693     bool IsRev = false;
694     bool IsOK1 = false;
695     bool IsOK2 = false;
696     double dist1 = RealLast();
697     double dist2 = RealLast();
698     gp_Pnt Pres1,Pres2;
699     for (TIDSortedElemSet::iterator itF = sortedFaces.begin(); itF != fEnd; ++itF ) {
700       const SMDS_MeshElement* F = *itF;
701       if(F==face) continue;
702       Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt;
703       SMDS_ElemIteratorPtr nodeIt = F->nodesIterator();
704       if( !F->IsQuadratic() ) {
705         while ( nodeIt->more() ) {
706           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
707           aContour->Append(gp_Pnt(node->X(), node->Y(), node->Z()));
708         }
709       }
710       else {
711         int nn = 0;
712         while ( nodeIt->more() ) {
713           nn++;
714           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
715           aContour->Append(gp_Pnt(node->X(), node->Y(), node->Z()));
716           if(nn==face->NbNodes()/2) break;
717         }
718       }
719       gp_Pnt PPP;
720       if( HasIntersection(Ptmp1, PC, PPP, aContour) ) {
721         IsOK1 = true;
722         double tmp = PC.Distance(PPP);
723         if(tmp<dist1) {
724           Pres1 = PPP;
725           dist1 = tmp;
726         }
727       }
728       if( HasIntersection(Ptmp2, PC, PPP, aContour) ) {
729         IsOK2 = true;
730         double tmp = PC.Distance(PPP);
731         if(tmp<dist2) {
732           Pres2 = PPP;
733           dist2 = tmp;
734         }
735       }
736     }
737
738     if( IsOK1 && !IsOK2 ) {
739       // using existed direction
740       double tmp = PC.Distance(Pres1)/3.;
741       if( height > tmp ) {
742         height = tmp;
743         PCbest = PC.XYZ() + tmpDir.XYZ() * height;
744       }
745     }
746     else if( !IsOK1 && IsOK2 ) {
747       // using opposite direction
748       IsRev = true;
749       double tmp = PC.Distance(Pres2)/3.;
750       if( height > tmp ) height = tmp;
751       PCbest = PC.XYZ() - tmpDir.XYZ() * height;
752     }
753     else { // IsOK1 && IsOK2
754       double tmp1 = PC.Distance(Pres1)/3.;
755       double tmp2 = PC.Distance(Pres2)/3.;
756       if(tmp1<tmp2) {
757         // using existed direction
758         if( height > tmp1 ) {
759           height = tmp1;
760           PCbest = PC.XYZ() + tmpDir.XYZ() * height;
761         }
762       }
763       else {
764         // using opposite direction
765         IsRev = true;
766         if( height > tmp2 ) height = tmp2;
767         PCbest = PC.XYZ() - tmpDir.XYZ() * height;
768       }
769     }
770
771     // create node for PCbest
772     SMDS_MeshNode* NewNode = helper.AddNode( PCbest.X(), PCbest.Y(), PCbest.Z() );
773     // add triangles to result map
774     std::list<const SMDS_FaceOfNodes*> aList;
775     for(i=0; i<4; i++) {
776       SMDS_FaceOfNodes* NewFace;
777       if(IsRev)
778         NewFace = new SMDS_FaceOfNodes( NewNode, FNodes[i], FNodes[i+1] );
779       else
780         NewFace = new SMDS_FaceOfNodes( NewNode, FNodes[i+1], FNodes[i] );
781       aList.push_back(NewFace);
782     }
783     myResMap.insert(make_pair(face,aList));
784     // create pyramid
785     SMDS_MeshVolume* aPyram;
786     if(IsRev)
787      aPyram = helper.AddVolume( FNodes[0], FNodes[1], FNodes[2], FNodes[3], NewNode );
788     else
789      aPyram = helper.AddVolume( FNodes[0], FNodes[3], FNodes[2], FNodes[1], NewNode );
790     myMapFPyram.insert(make_pair(face,aPyram));
791   } // end loop on elements on a face
792
793   return Compute2ndPart(aMesh);
794 }
795
796
797 //=======================================================================
798 //function : Compute2ndPart
799 //purpose  : 
800 //=======================================================================
801
802 bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh)
803 {
804   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
805
806   // check intersections between created pyramids
807   int NbPyram = myMapFPyram.size();
808   //cout<<"NbPyram = "<<NbPyram<<endl;
809   if(NbPyram==0)
810     return true;
811
812   vector< const SMDS_MeshElement* > Pyrams(NbPyram);
813   vector< const SMDS_MeshElement* > Faces(NbPyram);
814   TF2PyramMap::iterator itp = myMapFPyram.begin();
815   int i = 0;
816   for(; itp!=myMapFPyram.end(); itp++, i++) {
817     Faces[i] = (*itp).first;
818     Pyrams[i] = (*itp).second;
819   }
820   StdMeshers_Array1OfSequenceOfInteger MergesInfo(0,NbPyram-1);
821   for(i=0; i<NbPyram; i++) {
822     TColStd_SequenceOfInteger aMerges;
823     aMerges.Append(i);
824     MergesInfo.SetValue(i,aMerges);
825   }
826   for(i=0; i<NbPyram-1; i++) {
827     const SMDS_MeshElement* Prm1 = Pyrams[i];
828     SMDS_ElemIteratorPtr nIt = Prm1->nodesIterator();
829     std::vector<gp_Pnt> Ps1(5);
830     const SMDS_MeshNode* Ns1[5];
831     int k = 0;
832     while( nIt->more() ) {
833       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nIt->next() );
834       Ns1[k] = node;
835       Ps1[k] = gp_Pnt(node->X(), node->Y(), node->Z());
836       k++;
837     }
838     bool NeedMove = false;
839     for(int j=i+1; j<NbPyram; j++) {
840       //cout<<"  i="<<i<<" j="<<j<<endl;
841       const TColStd_SequenceOfInteger& aMergesI = MergesInfo.Value(i);
842       int nbI = aMergesI.Length();
843       const TColStd_SequenceOfInteger& aMergesJ = MergesInfo.Value(j);
844       int nbJ = aMergesJ.Length();
845       // check if two pyramids already merged
846       int k = 2;
847       bool NeedCont = false;
848       for(; k<=nbI; k++) {
849         if(aMergesI.Value(k)==j) {
850           NeedCont = true;
851           break;
852         }
853       }
854       if(NeedCont) continue; // already merged
855
856       const SMDS_MeshElement* Prm2 = Pyrams[j];
857       nIt = Prm2->nodesIterator();
858       std::vector<gp_Pnt> Ps2(5);
859       const SMDS_MeshNode* Ns2[5];
860       k = 0;
861       while( nIt->more() ) {
862         const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nIt->next() );
863         Ns2[k] = node;
864         Ps2[k] = gp_Pnt(node->X(), node->Y(), node->Z());
865         k++;
866       }
867
868       bool hasInt = false;
869       gp_Pnt Pint;
870       for(k=0; k<4; k++) {
871         gp_Vec Vtmp(Ps1[k],Ps1[4]);
872         gp_Pnt Pshift = Ps1[k].XYZ() + Vtmp.XYZ() * 0.01;
873         int m=0;
874         for(; m<3; m++) {
875           if( HasIntersection3( Pshift, Ps1[4], Pint, Ps2[m], Ps2[m+1], Ps2[4]) ) {
876             hasInt = true;
877             break;
878           }
879         }
880         if( HasIntersection3( Pshift, Ps1[4], Pint, Ps2[3], Ps2[0], Ps2[4]) ) {
881           hasInt = true;
882         }
883         if(hasInt) break;
884       }
885       if(!hasInt) {
886         for(k=0; k<4; k++) {
887           gp_Vec Vtmp(Ps2[k],Ps2[4]);
888           gp_Pnt Pshift = Ps2[k].XYZ() + Vtmp.XYZ() * 0.01;
889           int m=0;
890           for(; m<3; m++) {
891             if( HasIntersection3( Pshift, Ps2[4], Pint, Ps1[m], Ps1[m+1], Ps1[4]) ) {
892               hasInt = true;
893               break;
894             }
895           }
896           if( HasIntersection3( Pshift, Ps2[4], Pint, Ps1[3], Ps1[0], Ps1[4]) ) {
897             hasInt = true;
898           }
899           if(hasInt) break;
900         }
901       }
902
903       if(hasInt) {
904         //cout<<"    has intersec for i="<<i<<" j="<<j<<endl;
905         // check if MeshFaces have 2 common node
906         int nbc = 0;
907         for(k=0; k<4; k++) {
908           for(int m=0; m<4; m++) {
909             if( Ns1[k]==Ns2[m] ) nbc++;
910           }
911         }
912         //cout<<"      nbc = "<<nbc<<endl;
913         if(nbc>0) {
914           // create common node
915           SMDS_MeshNode* CommonNode = const_cast<SMDS_MeshNode*>(Ns1[4]);
916           CommonNode->setXYZ( ( nbI*Ps1[4].X() + nbJ*Ps2[4].X() ) / (nbI+nbJ),
917                               ( nbI*Ps1[4].Y() + nbJ*Ps2[4].Y() ) / (nbI+nbJ),
918                               ( nbI*Ps1[4].Z() + nbJ*Ps2[4].Z() ) / (nbI+nbJ) );
919           NeedMove = true;
920           //cout<<"       CommonNode: "<<CommonNode;
921           const SMDS_MeshNode* Nrem = Ns2[4];
922           Ns2[4] = CommonNode;
923           meshDS->ChangeElementNodes(Prm2, Ns2, 5);
924           // update pyramids for J
925           for(k=2; k<=nbJ; k++) {
926             const SMDS_MeshElement* tmpPrm = Pyrams[aMergesJ.Value(k)];
927             SMDS_ElemIteratorPtr tmpIt = tmpPrm->nodesIterator();
928             const SMDS_MeshNode* Ns[5];
929             int m = 0;
930             while( tmpIt->more() ) {
931               Ns[m] = static_cast<const SMDS_MeshNode*>( tmpIt->next() );
932               m++;
933             }
934             Ns[4] = CommonNode;
935             meshDS->ChangeElementNodes(tmpPrm, Ns, 5);
936           }
937
938           // update MergesInfo
939           for(k=1; k<=nbI; k++) {
940             int num = aMergesI.Value(k);
941             const TColStd_SequenceOfInteger& aSeq = MergesInfo.Value(num);
942             TColStd_SequenceOfInteger tmpSeq;
943             int m = 1;
944             for(; m<=aSeq.Length(); m++) {
945               tmpSeq.Append(aSeq.Value(m));
946             }
947             for(m=1; m<=nbJ; m++) {
948               tmpSeq.Append(aMergesJ.Value(m));
949             }
950             MergesInfo.SetValue(num,tmpSeq);
951           }
952           for(k=1; k<=nbJ; k++) {
953             int num = aMergesJ.Value(k);
954             const TColStd_SequenceOfInteger& aSeq = MergesInfo.Value(num);
955             TColStd_SequenceOfInteger tmpSeq;
956             int m = 1;
957             for(; m<=aSeq.Length(); m++) {
958               tmpSeq.Append(aSeq.Value(m));
959             }
960             for(m=1; m<=nbI; m++) {
961               tmpSeq.Append(aMergesI.Value(m));
962             }
963             MergesInfo.SetValue(num,tmpSeq);
964           }
965
966           // update triangles for aMergesJ
967           for(k=1; k<=nbJ; k++) {
968             std::list< std::list< const SMDS_MeshNode* > > aFNodes;
969             std::list< const SMDS_MeshElement* > aFFaces;
970             int num = aMergesJ.Value(k);
971             std::map< const SMDS_MeshElement*,
972               std::list<const SMDS_FaceOfNodes*> >::iterator itrm = myResMap.find(Faces[num]);
973             std::list<const SMDS_FaceOfNodes*> trias = (*itrm).second;
974             std::list<const SMDS_FaceOfNodes*>::iterator itt = trias.begin();
975             for(; itt!=trias.end(); itt++) {
976               int nn = -1;
977               SMDS_ElemIteratorPtr nodeIt = (*itt)->nodesIterator();
978               const SMDS_MeshNode* NF[3];
979               while ( nodeIt->more() ) {
980                 nn++;
981                 NF[nn] = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
982               }
983               NF[0] = CommonNode;
984               SMDS_FaceOfNodes* Ftria = const_cast< SMDS_FaceOfNodes*>( (*itt) );
985               Ftria->ChangeNodes(NF, 3);
986             }
987           }
988
989           // check and remove coincided faces
990           TColStd_SequenceOfInteger IdRemovedTrias;
991           int i1 = 1;
992           for(; i1<=nbI; i1++) {
993             int numI = aMergesI.Value(i1);
994             std::map< const SMDS_MeshElement*,
995               std::list<const SMDS_FaceOfNodes*> >::iterator itrmI = myResMap.find(Faces[numI]);
996             std::list<const SMDS_FaceOfNodes*> triasI = (*itrmI).second;
997             std::list<const SMDS_FaceOfNodes*>::iterator ittI = triasI.begin();
998             int nbfI = triasI.size();
999             std::vector<const SMDS_FaceOfNodes*> FsI(nbfI);
1000             k = 0;
1001             for(; ittI!=triasI.end(); ittI++) {
1002               FsI[k]  = (*ittI);
1003               k++;
1004             }
1005             int i2 = 0;
1006             for(; i2<nbfI; i2++) {
1007               const SMDS_FaceOfNodes* FI = FsI[i2];
1008               if(FI==0) continue;
1009               int j1 = 1;
1010               for(; j1<=nbJ; j1++) {
1011                 int numJ = aMergesJ.Value(j1);
1012                 std::map< const SMDS_MeshElement*,
1013                   std::list<const SMDS_FaceOfNodes*> >::iterator itrmJ = myResMap.find(Faces[numJ]);
1014                 std::list<const SMDS_FaceOfNodes*> triasJ = (*itrmJ).second;
1015                 std::list<const SMDS_FaceOfNodes*>::iterator ittJ = triasJ.begin();
1016                 int nbfJ = triasJ.size();
1017                 std::vector<const SMDS_FaceOfNodes*> FsJ(nbfJ);
1018                 k = 0;
1019                 for(; ittJ!=triasJ.end(); ittJ++) {
1020                   FsJ[k]  = (*ittJ);
1021                   k++;
1022                 }
1023                 int j2 = 0;
1024                 for(; j2<nbfJ; j2++) {
1025                   const SMDS_FaceOfNodes* FJ = FsJ[j2];
1026                   // compare triangles
1027                   if( CompareTrias(FI,FJ) ) {
1028                     IdRemovedTrias.Append( FI->GetID() );
1029                     IdRemovedTrias.Append( FJ->GetID() );
1030                     FsI[i2] = 0;
1031                     FsJ[j2] = 0;
1032                     std::list<const SMDS_FaceOfNodes*> new_triasI;
1033                     for(k=0; k<nbfI; k++) {
1034                       if( FsI[k]==0 ) continue;
1035                       new_triasI.push_back( FsI[k] );
1036                     }
1037                     (*itrmI).second = new_triasI;
1038                     triasI = new_triasI;
1039                     std::list<const SMDS_FaceOfNodes*> new_triasJ;
1040                     for(k=0; k<nbfJ; k++) {
1041                       if( FsJ[k]==0 ) continue;
1042                       new_triasJ.push_back( FsJ[k] );
1043                     }
1044                     (*itrmJ).second = new_triasJ;
1045                     triasJ = new_triasJ;
1046                     // remove faces
1047                     delete FI;
1048                     delete FJ;
1049                     // close for j2 and j1
1050                     j1 = nbJ;
1051                     break;
1052                   }
1053                 } // j2
1054               } // j1
1055             } // i2
1056           } // i1
1057           // removing node
1058           meshDS->RemoveNode(Nrem);
1059         }
1060         else { // nbc==0
1061           //cout<<"decrease height of pyramids"<<endl;
1062           // decrease height of pyramids
1063           double xc1 = 0., yc1 = 0., zc1 = 0.;
1064           double xc2 = 0., yc2 = 0., zc2 = 0.;
1065           for(k=0; k<4; k++) {
1066             xc1 += Ps1[k].X();
1067             yc1 += Ps1[k].Y();
1068             zc1 += Ps1[k].Z();
1069             xc2 += Ps2[k].X();
1070             yc2 += Ps2[k].Y();
1071             zc2 += Ps2[k].Z();
1072           }
1073           gp_Pnt PC1(xc1/4.,yc1/4.,zc1/4.);
1074           gp_Pnt PC2(xc2/4.,yc2/4.,zc2/4.);
1075           gp_Vec VN1(PC1,Ps1[4]);
1076           gp_Vec VI1(PC1,Pint);
1077           gp_Vec VN2(PC2,Ps2[4]);
1078           gp_Vec VI2(PC2,Pint);
1079           double ang1 = fabs(VN1.Angle(VI1));
1080           double ang2 = fabs(VN2.Angle(VI2));
1081           double h1,h2;
1082           if(ang1>PI/3.)
1083             h1 = VI1.Magnitude()/2;
1084           else
1085             h1 = VI1.Magnitude()*cos(ang1);
1086           if(ang2>PI/3.)
1087             h2 = VI2.Magnitude()/2;
1088           else
1089             h2 = VI2.Magnitude()*cos(ang2);
1090           double coef1 = 0.5;
1091           if(ang1<PI/3)
1092             coef1 -= cos(ang1)*0.25;
1093           double coef2 = 0.5;
1094           if(ang2<PI/3)
1095             coef2 -= cos(ang1)*0.25;
1096
1097           SMDS_MeshNode* aNode1 = const_cast<SMDS_MeshNode*>(Ns1[4]);
1098           VN1.Scale(coef1);
1099           aNode1->setXYZ( PC1.X()+VN1.X(), PC1.Y()+VN1.Y(), PC1.Z()+VN1.Z() );
1100           SMDS_MeshNode* aNode2 = const_cast<SMDS_MeshNode*>(Ns2[4]);
1101           VN2.Scale(coef2);
1102           aNode2->setXYZ( PC2.X()+VN2.X(), PC2.Y()+VN2.Y(), PC2.Z()+VN2.Z() );
1103           NeedMove = true;
1104         }
1105       } // end if(hasInt)
1106       else {
1107         //cout<<"    no intersec for i="<<i<<" j="<<j<<endl;
1108       }
1109
1110     }
1111     if( NeedMove && !meshDS->IsEmbeddedMode() ) {
1112       meshDS->MoveNode( Ns1[4], Ns1[4]->X(), Ns1[4]->Y(), Ns1[4]->Z() );
1113     }
1114   }
1115
1116   return true;
1117 }
1118
1119
1120 //================================================================================
1121 /*!
1122  * \brief Return list of created triangles for given face
1123  */
1124 //================================================================================
1125 const std::list<const SMDS_FaceOfNodes*>* StdMeshers_QuadToTriaAdaptor::GetTriangles
1126                                                    (const SMDS_MeshElement* aFace)
1127 {
1128   std::map< const SMDS_MeshElement*,
1129     std::list<const SMDS_FaceOfNodes*> >::iterator it = myResMap.find(aFace);
1130   if( it != myResMap.end() ) {
1131     return & it->second;
1132   }
1133   return 0;
1134 }
1135
1136
1137 //================================================================================
1138 /*!
1139  * \brief Remove all create auxilary faces
1140  */
1141 //================================================================================
1142 //void StdMeshers_QuadToTriaAdaptor::RemoveFaces(SMESH_Mesh& aMesh)
1143 //{
1144 //  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
1145 //  std::map< const SMDS_MeshElement*,
1146 //    std::list<const SMDS_MeshElement*> >::iterator it = myResMap.begin();
1147 //  for(; it != myResMap.end(); it++ ) {
1148 //    std::list<const SMDS_MeshElement*> aFaces = (*it).second;
1149 //    std::list<const SMDS_MeshElement*>::iterator itf = aFaces.begin();
1150 //    for(; itf!=aFaces.end(); itf++ ) {
1151 //      meshDS->RemoveElement( (*itf) );
1152 //    }
1153 //  }
1154 //}