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