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