0025310: Regressions in visualization
[occt.git] / src / BRepMesh / BRepMesh_FastDiscretFace.cxx
1 // Created by: Ekaterina SMIRNOVA
2 // Copyright (c) 2008-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BRepMesh_FastDiscretFace.hxx>
16
17 #include <BRepMesh_PairOfPolygon.hxx>
18 #include <BRepMesh_ShapeTool.hxx>
19 #include <Poly_PolygonOnTriangulation.hxx>
20 #include <Poly_Triangulation.hxx>
21
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepAdaptor_HSurface.hxx>
24 #include <BRepAdaptor_Curve.hxx>
25 #include <Adaptor3d_IsoCurve.hxx>
26
27 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
28 #include <BRep_PointRepresentation.hxx>
29 #include <BRep_TVertex.hxx>
30 #include <BRep_Tool.hxx>
31
32 #include <GeomLib.hxx>
33 #include <Geom_Surface.hxx>
34 #include <Geom_BSplineSurface.hxx>
35 #include <GCPnts_TangentialDeflection.hxx>
36
37 #include <Standard_ErrorHandler.hxx>
38 #include <Standard_Failure.hxx>
39 #include <SortTools_ShellSortOfReal.hxx>
40 #include <TCollection_CompareOfReal.hxx>
41 #include <TColStd_Array1OfReal.hxx>
42 #include <TColStd_ListOfInteger.hxx>
43 #include <TColStd_SequenceOfReal.hxx>
44 #include <TColStd_Array1OfInteger.hxx>
45 #include <TColStd_HArray1OfReal.hxx>
46 #include <TColgp_Array1OfPnt2d.hxx>
47 #include <TopTools_DataMapOfShapeReal.hxx>
48
49 #include <TopExp_Explorer.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Vertex.hxx>
52 #include <TopExp.hxx>
53
54 #include <NCollection_Map.hxx>
55 #include <Bnd_Box2d.hxx>
56
57 #include <algorithm>
58
59 IMPLEMENT_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient)
60 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace, Standard_Transient)
61
62 static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen)
63 {
64   Standard_Integer i, j, n = 0;
65   Standard_Real p, result = 0.;
66
67   for(i = 1; i <= PLen; i++)
68   {
69     // Sort
70     for(j = i + 1; j <= PLen; j++)
71     {
72       if(P(i) > P(j))
73       {
74         p = P(i);
75         P(i) = P(j);
76         P(j) = p;
77       }
78     }
79     // Accumulate
80     if (i != 1)
81     {
82       p = Abs(P(i) - P(i-1));
83       if(p > 1.e-7)
84       {
85         result += p;
86         n++;
87       }
88     }
89   }
90   return (n? (result / (Standard_Real) n) : -1.);
91 }
92
93 namespace {
94
95   //! Auxiliary class used to extract geometrical parameters of fixed TopoDS_Vertex.
96   class FixedVExplorer
97   {
98   public:
99
100     DEFINE_STANDARD_ALLOC
101
102     FixedVExplorer(const TopoDS_Vertex& theVertex)
103       : myVertex(theVertex)
104     {
105     }
106
107     const TopoDS_Vertex& Vertex() const
108     {
109       return myVertex;
110     }
111
112     Standard_Boolean IsSameUV() const
113     {
114       return Standard_False;
115     }
116
117     TopoDS_Vertex SameVertex() const
118     {
119       return TopoDS_Vertex();
120     }
121
122     virtual gp_Pnt Point() const
123     {
124       return BRep_Tool::Pnt(myVertex);
125     }
126
127   private:
128
129     void operator =(const FixedVExplorer& /*theOther*/)
130     {
131     }
132
133   private:
134     const TopoDS_Vertex& myVertex;
135   };
136 }
137
138
139 //=======================================================================
140 //function : BRepMesh_FastDiscretFace
141 //purpose  : 
142 //=======================================================================
143 BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace
144                           (const Standard_Real     theAngle,
145                            const Standard_Boolean  theWithShare)
146 : myAngle(theAngle), myWithShare(theWithShare),
147   myInternalVerticesMode(Standard_True)
148 {
149   myAllocator = new NCollection_IncAllocator(64000);
150 }
151
152 //=======================================================================
153 //function : Perform
154 //purpose  : 
155 //=======================================================================
156 void BRepMesh_FastDiscretFace::Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute)
157 {
158   Add(theAttribute);
159   commitSurfaceTriangulation();
160 }
161
162 //=======================================================================
163 //function : Add
164 //purpose  : 
165 //=======================================================================
166 void BRepMesh_FastDiscretFace::Add(const Handle(BRepMesh_FaceAttribute)& theAttribute)
167 {
168   if (!theAttribute->IsValid())
169     return;
170
171   myAttribute     = theAttribute;
172   myStructure     = myAttribute->ChangeStructure();
173   myVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
174   myClassifier    = myAttribute->ChangeClassifier();
175   mySurfacePoints = myAttribute->ChangeSurfacePoints();
176
177   Standard_Real aTolU = myAttribute->ToleranceU();
178   Standard_Real aTolV = myAttribute->ToleranceV();
179   Standard_Real uCellSize = 14.0 * aTolU;
180   Standard_Real vCellSize = 14.0 * aTolV;
181
182   const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
183   GeomAbs_SurfaceType thetype = gFace->GetType();
184
185   Standard_Integer i = 1;
186
187   //////////////////////////////////////////////////////////// 
188   //add internal vertices after self-intersection check
189   Standard_Integer nbVertices = 0;
190   if ( myInternalVerticesMode )
191   {
192     TopExp_Explorer anExplorer(myAttribute->Face(), TopAbs_VERTEX, TopAbs_EDGE);
193     for ( ; anExplorer.More(); anExplorer.Next() )
194       add(TopoDS::Vertex(anExplorer.Current()));
195     nbVertices = myVertexEdgeMap->Extent();
196   }
197
198   // essai de determination de la longueur vraie:
199   // akm (bug OCC16) : We must calculate these measures in non-singular
200   //     parts of face. Let`s try to compute average value of three
201   //     (umin, (umin+umax)/2, umax), and respectively for v.
202   //                 vvvvv
203   //Standard_Real longu = 0.0, longv = 0.0; //, last , first;
204   //gp_Pnt P11, P12, P21, P22, P31, P32;
205
206   const Standard_Real deltaX = myAttribute->GetDeltaX();
207   const Standard_Real deltaY = myAttribute->GetDeltaY();
208
209   BRepMesh::Array1OfInteger tabvert_corr(1, nbVertices);
210
211   // Check the necessity to fill the map of parameters
212   const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus         ||
213                                        thetype == GeomAbs_BezierSurface ||
214                                        thetype == GeomAbs_BSplineSurface);
215   myUParam.Clear(); 
216   myVParam.Clear();
217
218   BRepMesh_VertexTool aMoveNodes(nbVertices, myAllocator);
219
220   aMoveNodes.SetCellSize ( uCellSize / deltaX, vCellSize / deltaY);
221   aMoveNodes.SetTolerance( aTolU     / deltaX, aTolV     / deltaY);
222
223   for ( i = 1; i <= myStructure->NbNodes(); ++i )
224   {
225     const BRepMesh_Vertex& v = myStructure->GetNode(i);
226     gp_XY aPnt2d = v.Coord();
227
228     if (useUVParam)
229     {
230       myUParam.Add(aPnt2d.X());
231       myVParam.Add(aPnt2d.Y());
232     }
233
234     aPnt2d = myAttribute->Scale(aPnt2d, Standard_True);
235     BRepMesh_Vertex v_new(aPnt2d, v.Location3d(), v.Movability());
236     const BRepMesh::ListOfInteger& alist = myStructure->LinksConnectedTo(i);
237     aMoveNodes.Add(v_new, alist);
238     tabvert_corr(i) = i;
239   }
240   myStructure->ReplaceNodes(aMoveNodes);
241
242   Standard_Boolean rajout = 
243     (thetype == GeomAbs_Sphere || thetype == GeomAbs_Torus);
244
245   BRepMesh_Delaun trigu(myStructure, tabvert_corr);
246
247   //removed all free edges from triangulation
248   const Standard_Integer nbLinks = myStructure->NbLinks();
249   for( i = 1; i <= nbLinks; i++ ) 
250   {
251     if( myStructure->ElementsConnectedTo(i).Extent() < 1 )
252     {
253       BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i);
254       if ( anEdge.Movability() == BRepMesh_Deleted )
255         continue;
256
257       anEdge.SetMovability(BRepMesh_Free);
258       myStructure->RemoveLink(i);
259     }
260   }
261
262   const Standard_Real umax = myAttribute->GetUMax();
263   const Standard_Real umin = myAttribute->GetUMin();
264   const Standard_Real vmax = myAttribute->GetVMax();
265   const Standard_Real vmin = myAttribute->GetVMin();
266
267   Standard_Boolean isaline = 
268     ((umax - umin) < Precision::PConfusion() || 
269      (vmax - vmin) < Precision::PConfusion());
270
271   Standard_Real aDef = -1;
272   if ( !isaline && myStructure->ElementsOfDomain().Extent() > 0 )
273   {
274     BRepMesh::ListOfVertex aNewVertices;
275     if ( !rajout )
276     {
277       aDef = control(aNewVertices, trigu, Standard_True);
278
279       if( aDef > myAttribute->GetDefFace() || aDef < 0.)
280         rajout = Standard_True;
281     }
282
283     if ( !rajout && useUVParam )
284     {
285       if ( myVParam.Extent() > 2 &&
286           (gFace->IsUClosed()    ||
287             gFace->IsVClosed()))
288       {
289         rajout = Standard_True;
290       }
291     }
292
293     if ( rajout )
294     {
295       insertInternalVertices(aNewVertices, trigu);
296
297       //control internal points
298       aDef = control(aNewVertices, trigu, Standard_False);
299     }
300   }
301
302   //modify myStructure back
303   aMoveNodes.SetCellSize ( uCellSize, vCellSize );
304   aMoveNodes.SetTolerance( aTolU    , aTolV     );
305
306   for ( i = 1; i <= myStructure->NbNodes(); ++i )
307   {
308     const BRepMesh_Vertex& v = myStructure->GetNode(i);
309     gp_XY aPnt2d = myAttribute->Scale(v.Coord(), Standard_False);
310     BRepMesh_Vertex v_new(aPnt2d, v.Location3d(), v.Movability());
311     const BRepMesh::ListOfInteger& alist = myStructure->LinksConnectedTo(i);
312     aMoveNodes.Add(v_new, alist);
313
314     // Register internal nodes used in triangulation
315     if (!alist.IsEmpty() && myVertexEdgeMap->FindIndex(i) == 0)
316       myVertexEdgeMap->Add(i);
317   }
318   myStructure->ReplaceNodes(aMoveNodes);
319
320   if (!(aDef < 0.))
321     myAttribute->SetDefFace(aDef);
322 }
323
324 //=======================================================================
325 //function : addVerticesToMesh
326 //purpose  : 
327 //=======================================================================
328 Standard_Boolean BRepMesh_FastDiscretFace::addVerticesToMesh(
329   const BRepMesh::ListOfVertex& theVertices,
330   BRepMesh_Delaun&              theMeshBuilder)
331 {
332   if (theVertices.IsEmpty())
333     return Standard_False;
334
335   BRepMesh::Array1OfVertexOfDelaun aArrayOfNewVertices(1, theVertices.Extent());
336   BRepMesh::ListOfVertex::Iterator aVertexIt(theVertices);
337   for (Standard_Integer aVertexId = 0; aVertexIt.More(); aVertexIt.Next())
338     aArrayOfNewVertices(++aVertexId) = aVertexIt.Value();
339
340   theMeshBuilder.AddVertices(aArrayOfNewVertices);
341   return Standard_True;
342 }
343
344 //=======================================================================
345 //function : insertInternalVertices
346 //purpose  : 
347 //=======================================================================
348 static void filterParameters(const BRepMesh::IMapOfReal& theParams,
349                              const Standard_Real         theMinDist,
350                              const Standard_Real         theFilterDist,
351                              BRepMesh::SequenceOfReal&   theResult)
352 {
353   // Sort sequence of parameters
354   BRepMesh::SequenceOfReal aParamTmp;
355   Standard_Integer aParamLength = 1;
356   const Standard_Integer anInitLen = theParams.Extent();
357     
358   TColStd_Array1OfReal aParamArray(1, anInitLen);
359   Standard_Integer j;
360   for (j = 1; j <= anInitLen; j++)
361     aParamArray(j) = theParams(j);
362
363   TCollection_CompareOfReal aCompare;
364   SortTools_ShellSortOfReal::Sort(aParamArray, aCompare);
365
366   // mandadory pre-filtering using the first (minimal) filter value
367   Standard_Real aP1, aP2;
368   aP1 = aParamArray(1);
369   aParamTmp.Append(aP1);
370   for (j = 2; j <= anInitLen; j++) 
371   {
372     aP2 = aParamArray(j);
373     if ((aP2-aP1) > theMinDist)
374     {
375       aParamTmp.Append(aP2);
376       aP1 = aP2;
377       aParamLength++;
378     }
379   }
380
381   //add last point if required
382   if(aParamArray(anInitLen)-theParams(aParamLength) > theMinDist)
383   {
384     aParamTmp.Append(aParamArray(anInitLen));
385     aParamLength++;
386   }
387   
388   //perform filtering on series
389   Standard_Real aLastAdded, aLastCandidate;
390   Standard_Boolean isCandidateDefined = Standard_False;
391   aLastAdded = aParamTmp.First();
392   aLastCandidate = aLastAdded;
393   theResult.Append(aParamTmp.First());
394   
395   for(j=2;j<aParamTmp.Length();j++) 
396   {
397     Standard_Real aVal = aParamTmp.Value(j);
398     if(aVal-aLastAdded > theFilterDist) 
399     {
400       //adds the parameter
401       if(isCandidateDefined) {
402         aLastAdded = aLastCandidate;
403         isCandidateDefined = Standard_False;
404         j--;
405       }
406       else 
407       {
408         aLastAdded = aVal;
409       }
410       theResult.Append(aLastAdded);
411       continue;
412     }
413     
414     aLastCandidate = aVal;
415     isCandidateDefined = Standard_True;
416   }
417   theResult.Append(aParamTmp.Last());
418   
419   if( theResult.Length() == 2 )
420   {
421     Standard_Real    dist  = theResult.Last() - theResult.First();
422     Standard_Integer nbint = (Standard_Integer)((dist / theFilterDist) + 0.5);
423
424     if( nbint > 1 )
425     {
426       //Five points more is maximum
427       if( nbint > 5 )
428       {
429         nbint = 5;
430       }
431
432       Standard_Integer i;
433       Standard_Real dU = dist / nbint;
434       for( i = 1; i < nbint; i++ )
435       {
436         theResult.InsertAfter(i, theResult.First()+i*dU);
437       }
438     }
439   }
440 }
441
442 void BRepMesh_FastDiscretFace::insertInternalVertices(
443   BRepMesh::ListOfVertex&  theNewVertices,
444   BRepMesh_Delaun&         theMeshBuilder)
445 {
446   const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
447   switch (gFace->GetType())
448   {
449   case GeomAbs_Sphere:
450       insertInternalVerticesSphere(theNewVertices);
451       break;
452
453   case GeomAbs_Cylinder:
454       insertInternalVerticesCylinder(theNewVertices);
455       break;
456
457   case GeomAbs_Cone:
458     insertInternalVerticesCone(theNewVertices);
459     break;
460
461   case GeomAbs_Torus:
462     insertInternalVerticesTorus(theNewVertices);
463     break;
464
465   case GeomAbs_BezierSurface:
466   case GeomAbs_BSplineSurface:
467     insertInternalVerticesBSpline(theNewVertices);
468     break;
469
470   default:
471     insertInternalVerticesOther(theNewVertices);
472     break;
473   }
474   
475   addVerticesToMesh(theNewVertices, theMeshBuilder);
476 }
477
478 //=======================================================================
479 //function : insertInternalVerticesSphere
480 //purpose  : 
481 //=======================================================================
482 void BRepMesh_FastDiscretFace::insertInternalVerticesSphere(
483   BRepMesh::ListOfVertex& theNewVertices)
484 {
485   const Standard_Real umax = myAttribute->GetUMax();
486   const Standard_Real umin = myAttribute->GetUMin();
487   const Standard_Real vmax = myAttribute->GetVMax();
488   const Standard_Real vmin = myAttribute->GetVMin();
489
490   gp_Sphere S = myAttribute->Surface()->Sphere();
491   const Standard_Real R = S.Radius();
492
493   // Calculate parameters for iteration in V direction
494   Standard_Real Dv = 1.0 - (myAttribute->GetDefFace() / R);
495   if (Dv < 0.0) Dv = 0.0;
496   Standard_Real oldDv = 2.0 * ACos(Dv);
497   Dv = .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs
498   const Standard_Real sv = vmax - vmin;
499   Dv = sv / ((Standard_Integer)(sv / Dv) + 1);
500   const Standard_Real pasvmax = vmax - Dv*0.5;
501
502   //Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v)
503   //here approximate relation r*Du = R*Dv is used
504
505   Standard_Real Du, pasu, pasv; //, ru;
506   const Standard_Real su = umax - umin;
507   Standard_Boolean Shift = Standard_False;
508   for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
509   {
510     // Calculate parameters for iteration in U direction
511     // 1.-.365*pasv*pasv is simple approximation of Cos(pasv)
512     // with condition that it gives ~.1 when pasv = pi/2
513     Du = Dv / (1. - .365*pasv*pasv);
514     Du = su / ((Standard_Integer)(su / Du) + 1);
515     Shift = !Shift;
516     const Standard_Real d = (Shift) ? Du*.5 : 0.;
517     const Standard_Real pasumax = umax - Du*0.5 + d;
518     for (pasu = umin + Du - d; pasu < pasumax; pasu += Du)
519     {
520       tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices);
521     }
522   }
523 }
524
525 //=======================================================================
526 //function : insertInternalVerticesCylinder
527 //purpose  : 
528 //=======================================================================
529 void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder(
530   BRepMesh::ListOfVertex& theNewVertices)
531 {
532   const Standard_Real umax = myAttribute->GetUMax();
533   const Standard_Real umin = myAttribute->GetUMin();
534   const Standard_Real vmax = myAttribute->GetVMax();
535   const Standard_Real vmin = myAttribute->GetVMin();
536
537   gp_Cylinder S = myAttribute->Surface()->Cylinder();
538   const Standard_Real R = S.Radius();
539
540   // Calculate parameters for iteration in U direction
541   Standard_Real Du = 1.0 - (myAttribute->GetDefFace() / R);
542   if (Du < 0.0) Du = 0.0;
543   Du = 2.0 * ACos(Du);
544   if (Du > myAngle) Du = myAngle;
545   const Standard_Real su = umax - umin;
546   const Standard_Integer nbU = (Standard_Integer)(su / Du);
547   Du = su / (nbU + 1);
548
549   // Calculate parameters for iteration in V direction
550   const Standard_Real sv = vmax - vmin;
551   Standard_Integer nbV = (Standard_Integer)(nbU*sv / (su*R));
552   nbV = Min(nbV, 100 * nbU);
553   Standard_Real Dv = sv / (nbV + 1);
554
555   Standard_Real pasu, pasv, pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5;
556   for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
557   {
558     for (pasu = umin + Du; pasu < pasumax; pasu += Du)
559     {
560       tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices);
561     }
562   }
563 }
564
565 //=======================================================================
566 //function : insertInternalVerticesCone
567 //purpose  : 
568 //=======================================================================
569 void BRepMesh_FastDiscretFace::insertInternalVerticesCone(
570   BRepMesh::ListOfVertex& theNewVertices)
571 {
572   const Standard_Real umax = myAttribute->GetUMax();
573   const Standard_Real umin = myAttribute->GetUMin();
574   const Standard_Real vmax = myAttribute->GetVMax();
575   const Standard_Real vmin = myAttribute->GetVMin();
576
577   Standard_Real R, RefR, SAng;
578   gp_Cone C = myAttribute->Surface()->Cone();
579   RefR = C.RefRadius();
580   SAng = C.SemiAngle();
581   R = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng)));
582   Standard_Real Du, Dv, pasu, pasv;
583   Du = Max(1.0e0 - (myAttribute->GetDefFace() / R), 0.0e0);
584   Du = (2.0 * ACos(Du));
585   Standard_Integer nbU = (Standard_Integer)((umax - umin) / Du);
586   Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*R));
587   Du = (umax - umin) / (nbU + 1);
588   Dv = (vmax - vmin) / (nbV + 1);
589
590   Standard_Real pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5;
591   for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
592   {
593     for (pasu = umin + Du; pasu < pasumax; pasu += Du)
594     {
595       tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), C, theNewVertices);
596     }
597   }
598 }
599
600 //=======================================================================
601 //function : insertInternalVerticesTorus
602 //purpose  : 
603 //=======================================================================
604 void BRepMesh_FastDiscretFace::insertInternalVerticesTorus(
605   BRepMesh::ListOfVertex& theNewVertices)
606 {
607   const Standard_Real umax     = myAttribute->GetUMax();
608   const Standard_Real umin     = myAttribute->GetUMin();
609   const Standard_Real vmax     = myAttribute->GetVMax();
610   const Standard_Real vmin     = myAttribute->GetVMin();
611   const Standard_Real deltaX   = myAttribute->GetDeltaX();
612   const Standard_Real deltaY   = myAttribute->GetDeltaY();
613   const Standard_Real aDefFace = myAttribute->GetDefFace();
614
615   gp_Torus T = myAttribute->Surface()->Torus();
616
617   Standard_Boolean insert;
618   Standard_Integer i, j, ParamULength, ParamVLength;
619   Standard_Real pp, pasu, pasv;
620   Standard_Real r = T.MinorRadius(), R = T.MajorRadius();
621
622   BRepMesh::SequenceOfReal ParamU, ParamV;
623
624   Standard_Real Du, Dv;//, pasu, pasv;
625   Dv = Max(1.0e0 - (aDefFace / r), 0.0e0);
626   Standard_Real oldDv = 2.0 * ACos(Dv);
627   oldDv = Min(oldDv, myAngle);
628   Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
629   Dv = oldDv;
630
631   Standard_Integer nbV = Max((Standard_Integer)((vmax - vmin) / Dv), 2);
632   Dv = (vmax - vmin) / (nbV + 1);
633   Standard_Real ru = R + r;
634   if (ru > 1.e-16)
635   {
636     Du = 2.0 * ACos(Max(1.0 - (aDefFace / ru), 0.0));
637     if (myAngle < Du) Du = myAngle;
638     Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
639     if (aa < gp::Resolution())
640       return;
641     Du *= Min(oldDv, Du) / aa;
642   }
643   else Du = Dv;
644
645   Standard_Integer nbU = Max((Standard_Integer)((umax - umin) / Du), 2);
646   nbU = Max(nbU, (int)(nbV*(umax - umin)*R / ((vmax - vmin)*r) / 5.));
647   Du = (umax - umin) / (nbU + 1);
648
649   if (R < r)
650   {
651     // As the points of edges are returned.
652     // in this case, the points are not representative.
653
654     //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
655     for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du);
656   }//R<r
657   else //U if R > r
658   {
659     //--ofv: U
660     // Number of mapped U parameters
661     const Standard_Integer LenU = myUParam.Extent();
662     // Fill array of U parameters
663     TColStd_Array1OfReal Up(1, LenU);
664     for (j = 1; j <= LenU; j++) Up(j) = myUParam(j);
665
666     // Calculate DU, leave array of parameters
667     Standard_Real aDU = FUN_CalcAverageDUV(Up, LenU);
668     aDU = Max(aDU, Abs(umax - umin) / (Standard_Real)nbU / 2.);
669     Standard_Real dUstd = Abs(umax - umin) / (Standard_Real)LenU;
670     if (aDU > dUstd) dUstd = aDU;
671     // Add U parameters
672     for (j = 1; j <= LenU; j++)
673     {
674       pp = Up(j);
675       insert = Standard_True;
676       ParamULength = ParamU.Length();
677       for (i = 1; i <= ParamULength && insert; i++)
678       {
679         insert = (Abs(ParamU.Value(i) - pp) > (0.5*dUstd));
680       }
681       if (insert) ParamU.Append(pp);
682     }
683   }
684
685   //--ofv: V
686   // Number of mapped V parameters
687   const Standard_Integer LenV = myVParam.Extent();
688   // Fill array of V parameters
689   TColStd_Array1OfReal Vp(1, LenV);
690   for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j);
691   // Calculate DV, sort array of parameters
692   Standard_Real aDV = FUN_CalcAverageDUV(Vp, LenV);
693   aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real)nbV / 2.);
694
695   Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real)LenV;
696   if (aDV > dVstd) dVstd = aDV;
697   // Add V parameters
698   for (j = 1; j <= LenV; j++)
699   {
700     pp = Vp(j);
701
702     insert = Standard_True;
703     ParamVLength = ParamV.Length();
704     for (i = 1; i <= ParamVLength && insert; i++)
705     {
706       insert = (Abs(ParamV.Value(i) - pp) > (dVstd*2. / 3.));
707     }
708     if (insert) ParamV.Append(pp);
709   }
710
711   Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
712   Standard_Real uminnew = umin + deltaY*0.1;
713   Standard_Real vminnew = vmin + deltaX*0.1;
714   Standard_Real umaxnew = umax - deltaY*0.1;
715   Standard_Real vmaxnew = vmax - deltaX*0.1;
716
717   for (i = 1; i <= Lu; i++)
718   {
719     pasu = ParamU.Value(i);
720     if (pasu >= uminnew && pasu < umaxnew)
721     {
722       for (j = 1; j <= Lv; j++)
723       {
724         pasv = ParamV.Value(j);
725         if (pasv >= vminnew && pasv < vmaxnew)
726         {
727           tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), T, theNewVertices);
728         }
729       }
730     }
731   }
732 }
733
734 //=======================================================================
735 //function : insertInternalVerticesBSpline
736 //purpose  : 
737 //=======================================================================
738 void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline(
739   BRepMesh::ListOfVertex& theNewVertices)
740 {
741   const Standard_Real aRange[2][2] = {
742       { myAttribute->GetUMax(), myAttribute->GetUMin() },
743       { myAttribute->GetVMax(), myAttribute->GetVMin() }
744   };
745
746   const Standard_Real aDelta[2] = { 
747     myAttribute->GetDeltaX(),
748     myAttribute->GetDeltaY()
749   };
750
751   const Standard_Real                 aDefFace = myAttribute->GetDefFace();
752   const Handle(BRepAdaptor_HSurface)& gFace    = myAttribute->Surface();
753
754   BRepMesh::SequenceOfReal aParams[2];
755   for (Standard_Integer i = 0; i < 2; ++i)
756   {
757     Standard_Boolean isU = (i == 0);
758     Standard_Real aRes = isU ?
759       gFace->UResolution(aDefFace) :
760       gFace->VResolution(aDefFace);
761
762     // Sort and filter sequence of parameters
763     Standard_Real aMinDiff = Precision::PConfusion();
764     if (aDelta[i] < 1.)
765       aMinDiff /= aDelta[i];
766
767     Standard_Real aRangeDiff = aRange[i][0] - aRange[i][1];
768     Standard_Real aDiffMaxLim = 0.1 * aRangeDiff;
769     Standard_Real aDiff = Min(aDiffMaxLim, Max(0.005 * aRangeDiff, 2. * aRes));
770     filterParameters(isU ? myUParam : myVParam, aMinDiff, aDiff, aParams[i]);
771   }
772
773   // check intermediate isolines
774   Handle(Geom_Surface) aBSpline;
775   GeomAbs_SurfaceType  aSurfType = gFace->GetType();
776   if (aSurfType == GeomAbs_BezierSurface)
777     aBSpline = gFace->Bezier();
778   else if (aSurfType == GeomAbs_BSplineSurface)
779     aBSpline = gFace->BSpline();
780
781   // precision for compare square distances
782   const Standard_Real aPrecision   = Precision::Confusion();
783   const Standard_Real aSqPrecision = aPrecision * aPrecision;
784   for (Standard_Integer k = 0; k < 2; ++k)
785   {
786     BRepMesh::SequenceOfReal& aParams1 = aParams[k];
787     BRepMesh::SequenceOfReal& aParams2 = aParams[(k + 1) % 2];
788     const Standard_Boolean isU = (k == 0);
789     Standard_Integer aStartIndex, aEndIndex; 
790     if (isU)
791     {
792       aStartIndex = 1;
793       aEndIndex   = aParams1.Length();
794     }
795     else
796     {
797       aStartIndex = 2;
798       aEndIndex   = aParams1.Length() - 1;
799     }
800
801     for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i)
802     {
803       const Standard_Real aParam1 = aParams1(i);
804       Handle(Geom_Curve) aIso = isU ?
805         aBSpline->UIso(aParam1) : aBSpline->VIso(aParam1);
806
807       Standard_Real aPrevParam2 = aParams2(1);
808       gp_Pnt aPrevPnt2 = aIso->Value(aPrevParam2);
809       for (Standard_Integer j = 2; j <= aParams2.Length();)
810       {
811         Standard_Real aParam2 = aParams2(j);
812         gp_Pnt aPnt2 = aIso->Value(aParam2);
813         Standard_Real aMidParam = 0.5 * (aPrevParam2 + aParam2);
814         gp_Pnt aMidPnt = aIso->Value(aMidParam);
815
816         // 23.03.2010 skl for OCC21645 - change precision for comparison
817         Standard_Real aDist;
818         if (aPrevPnt2.SquareDistance(aPnt2) > aSqPrecision)
819         {
820           gp_Lin aLin(aPrevPnt2, gp_Dir(gp_Vec(aPrevPnt2, aPnt2)));
821           aDist = aLin.Distance(aMidPnt);
822         }
823         else
824           aDist = aPrevPnt2.Distance(aMidPnt);
825
826         if (aDist > aDefFace)
827         {
828           // insertion 
829           aParams2.InsertBefore(j, aMidParam);
830         }
831         else
832         {
833           //put regular grig for normals
834           gp_Pnt2d aStPnt1, aStPnt2;
835           if (isU)
836           {
837             aStPnt1 = gp_Pnt2d(aParam1, aPrevParam2);
838             aStPnt2 = gp_Pnt2d(aParam1, aMidParam);
839           }
840           else
841           {
842             aStPnt1 = gp_Pnt2d(aPrevParam2, aParam1);
843             aStPnt2 = gp_Pnt2d(aMidParam,   aParam1);
844           }
845
846           gp_Dir N1(0, 0, 1), N2(0, 0, 1);
847           Standard_Boolean aSt1 = GeomLib::NormEstim(aBSpline, aStPnt1, aPrecision, N1);
848           Standard_Boolean aSt2 = GeomLib::NormEstim(aBSpline, aStPnt2, aPrecision, N2);
849
850           Standard_Real aAngle = N2.Angle(N1);
851           if (aSt1 < 1 && aSt2 < 1 && aAngle > myAngle)
852           {
853             // insertion 
854             aParams2.InsertBefore(j, aMidParam);
855           }
856           else
857           {
858             aPrevParam2 = aParam2;
859             aPrevPnt2   = aPnt2;
860
861             if (!isU && j < aParams2.Length())
862             {
863               // Update point parameter.
864               aStPnt1.SetX(aPrevParam2);
865
866               // Classify intersection point
867               if (myClassifier->Perform(aStPnt1) == TopAbs_IN)
868               {
869                 insertVertex(aPrevPnt2, aStPnt1.Coord(), theNewVertices);
870               }
871             }
872
873             ++j;
874           }
875         }
876       }
877     }
878   }
879 }
880
881 //=======================================================================
882 //function : insertInternalVerticesOther
883 //purpose  : 
884 //=======================================================================
885 void BRepMesh_FastDiscretFace::insertInternalVerticesOther(
886   BRepMesh::ListOfVertex& theNewVertices)
887 {
888   const Standard_Real aAngle = 0.35;
889   const Standard_Real aRange[2][2] = {
890       { myAttribute->GetUMax(), myAttribute->GetUMin() },
891       { myAttribute->GetVMax(), myAttribute->GetVMin() }
892   };
893
894   const Standard_Real                 aDefFace = myAttribute->GetDefFace();
895   const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
896
897   BRepMesh::SequenceOfReal aParams[2];
898   const Standard_Integer aIsoPointsNb = 11;
899   for (Standard_Integer k = 0; k < 2; ++k)
900   {
901     const Standard_Boolean isU = (k == 0);
902     const GeomAbs_IsoType  aIsoType = isU ? GeomAbs_IsoU : GeomAbs_IsoV;
903     const Standard_Integer aOtherParamsIndex = (k + 1) % 2;
904     const Standard_Real (&aRange1)[2] = aRange[k];
905     const Standard_Real (&aRange2)[2] = aRange[aOtherParamsIndex];
906
907     GCPnts_TangentialDeflection aDiscretIso[aIsoPointsNb];
908     const Standard_Real aStepWidth = (aRange1[0] - aRange1[1]) / aIsoPointsNb;
909
910     // Find the most curved Iso.
911     Standard_Integer aMaxIndex = 1, aMaxPointsNb = 0;
912     for (Standard_Integer aIsoIt = 0; aIsoIt < aIsoPointsNb; ++aIsoIt)
913     {
914       Standard_Real aParam = aRange1[1] + aIsoIt * aStepWidth;
915       Adaptor3d_IsoCurve aIso(gFace, aIsoType, aParam);
916
917       Standard_Real aFirstParam = Max(aRange2[1], aIso.FirstParameter());
918       Standard_Real aLastParam  = Min(aRange2[0], aIso.LastParameter());
919
920       aDiscretIso[aIsoIt].Initialize(aIso, aFirstParam, aLastParam, 
921         aAngle, 0.7 * aDefFace, 2);
922
923       const Standard_Integer aPointsNb = aDiscretIso[aIsoIt].NbPoints();
924       if (aPointsNb > aMaxPointsNb)
925       {
926         aMaxPointsNb = aPointsNb;
927         aMaxIndex    = aIsoIt;
928       }
929     }
930
931     BRepMesh::SequenceOfReal& aParams2 = aParams[aOtherParamsIndex];
932     GCPnts_TangentialDeflection& aDIso = aDiscretIso[aMaxIndex];
933     for (Standard_Integer i = 1; i <= aMaxPointsNb; ++i)
934       aParams2.Append(aDIso.Parameter(i));
935
936     if (aParams2.Length() == 2)
937       aParams2.InsertAfter(1, 0.5 * (aRange2[1] + aRange2[0]));
938   }
939
940   Adaptor3d_IsoCurve aIsoV;
941   aIsoV.Load(gFace);
942
943   const Standard_Integer aUPointsNb = aParams[0].Length();
944   const Standard_Integer aVPointsNb = aParams[1].Length();
945   for (Standard_Integer i = 2; i < aVPointsNb; ++i)
946   {
947     const Standard_Real aV = aParams[1].Value(i);
948     aIsoV.Load(GeomAbs_IsoV, aV);
949
950     for (Standard_Integer j = 2; j < aUPointsNb; ++j)
951     {
952       const Standard_Real aU = aParams[0].Value(j);
953
954       const gp_Pnt2d aNewPoint(aU, aV);
955       if (myClassifier->Perform(aNewPoint) == TopAbs_IN)
956         insertVertex(aIsoV.Value(aU), aNewPoint.Coord(), theNewVertices);
957     }
958   }
959 }
960
961 //=======================================================================
962 //function : control
963 //purpose  : 
964 //=======================================================================
965 Standard_Real BRepMesh_FastDiscretFace::control(
966   BRepMesh::ListOfVertex&  theNewVertices,
967   BRepMesh_Delaun&         theTrigu,
968   const Standard_Boolean   theIsFirst)
969
970 #define CHECK_DEF_AND_INSERT_CURRENT(isSkipped)                 \
971 if (aSqDef > aMaxSqDef)                                         \
972   aMaxSqDef = aSqDef;                                           \
973                                                                 \
974 (isSkipped) = Standard_False;                                   \
975 if (aSqDef > aSqDefFace)                                        \
976 {                                                               \
977   (isSkipped) = theIsFirst;                                     \
978   if (!(isSkipped))                                             \
979     insertVertex(pDef, mi2d, theNewVertices);                   \
980 }                                                               \
981
982 {
983   Standard_Integer aTrianglesNb = myStructure->ElementsOfDomain().Extent();
984   if (aTrianglesNb < 1)
985     return -1.0;
986
987   //IMPORTANT: Constants used in calculations
988   const Standard_Real MinimalArea2d     = 1.e-9;
989   const Standard_Real MinimalSqLength3d = 1.e-12;
990   const Standard_Real aSqDefFace = myAttribute->GetDefFace() * myAttribute->GetDefFace();
991
992   const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
993
994   Handle(Geom_Surface) aBSpline;
995   GeomAbs_SurfaceType  aSurfType = gFace->GetType();
996   if (aSurfType == GeomAbs_BezierSurface)
997     aBSpline = gFace->Bezier();
998   else if (aSurfType == GeomAbs_BSplineSurface)
999     aBSpline = gFace->BSpline();
1000
1001   NCollection_DataMap<Standard_Integer, gp_Dir> aNorMap;
1002   BRepMesh::MapOfIntegerInteger                 aStatMap;
1003   NCollection_Map<BRepMesh_OrientedEdge>        aCouples(3 * aTrianglesNb);
1004
1005   // Perform refinement passes
1006   // Define the number of iterations
1007   Standard_Integer       aIterationsNb = 11;
1008   const Standard_Integer aPassesNb = (theIsFirst ? 1 : aIterationsNb);
1009   // Initialize stop condition
1010   Standard_Real aMaxSqDef = -1.;
1011   Standard_Integer aPass = 1, aInsertedNb = 1;
1012   Standard_Boolean isAllDegenerated = Standard_False;
1013   for (; aPass <= aPassesNb && aInsertedNb && !isAllDegenerated; ++aPass)
1014   {
1015     theNewVertices.Clear();
1016
1017     // Reset stop condition
1018     aInsertedNb      = 0;
1019     aMaxSqDef        = -1.;
1020     isAllDegenerated = Standard_True;
1021
1022     aTrianglesNb = myStructure->ElementsOfDomain().Extent();
1023     if (aTrianglesNb < 1)
1024       break;
1025
1026     // Iterate on current triangles
1027     const BRepMesh::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
1028     BRepMesh::MapOfInteger::Iterator aTriangleIt(aTriangles);
1029     for (; aTriangleIt.More(); aTriangleIt.Next())
1030     {
1031       const Standard_Integer aTriangleId = aTriangleIt.Key();
1032       const BRepMesh_Triangle& aCurrentTriangle = myStructure->GetElement(aTriangleId);
1033
1034       if (aCurrentTriangle.Movability() == BRepMesh_Deleted)
1035         continue;
1036
1037       Standard_Integer v[3];
1038       myStructure->ElementNodes(aCurrentTriangle, v);
1039
1040       Standard_Integer e[3];
1041       Standard_Boolean o[3];
1042       aCurrentTriangle.Edges(e, o);
1043
1044       gp_XY xy[3];
1045       gp_XYZ p[3];
1046       Standard_Boolean m[3];
1047       for (Standard_Integer i = 0; i < 3; ++i)
1048       {
1049         m[i] = (myStructure->GetLink(e[i]).Movability() == BRepMesh_Frontier);
1050
1051         const BRepMesh_Vertex& aVertex = myStructure->GetNode(v[i]);
1052         xy[i] = myAttribute->Scale(aVertex.Coord(), Standard_False);
1053         p [i] = myAttribute->GetPoint(aVertex).Coord();
1054       }
1055
1056       gp_XYZ aLinkVec[3];
1057       Standard_Boolean isDegeneratedTri = Standard_False;
1058       for (Standard_Integer i = 0; i < 3 && !isDegeneratedTri; ++i)
1059       {
1060         aLinkVec[i] = p[(i + 1) % 3] - p[i];
1061         isDegeneratedTri = (aLinkVec[i].SquareModulus() < MinimalSqLength3d);
1062       }
1063
1064       if (isDegeneratedTri) 
1065         continue;
1066
1067       isAllDegenerated = Standard_False;
1068
1069       // Check triangle area in 2d
1070       if (Abs((xy[1]-xy[0])^(xy[2]-xy[1])) < MinimalArea2d)
1071         continue;
1072
1073       // Check triangle normal
1074       gp_Pnt pDef;
1075       Standard_Real aSqDef = -1.;
1076       Standard_Boolean isSkipped = Standard_False;
1077       gp_XYZ normal(aLinkVec[0] ^ aLinkVec[1]);
1078       try
1079       {
1080         OCC_CATCH_SIGNALS
1081
1082         normal.Normalize();
1083
1084         // Check deflection on triangle
1085         gp_XY mi2d = (xy[0] + xy[1] + xy[2]) / 3.0;
1086         gFace->D0(mi2d.X(), mi2d.Y(), pDef);
1087         aSqDef = Abs(normal * (pDef.XYZ() - p[0]));
1088         aSqDef *= aSqDef;
1089
1090         CHECK_DEF_AND_INSERT_CURRENT(isSkipped);
1091         if (isSkipped)
1092           break;
1093       }
1094       catch (Standard_Failure)
1095       {
1096         continue;
1097       }
1098
1099       for (Standard_Integer i = 0; i < 3 && !isSkipped; ++i)
1100       {
1101         if (m[i]) // is a boundary
1102           continue;
1103
1104         Standard_Integer j = (i + 1) % 3;
1105         // Check if this link was already processed
1106         Standard_Integer aFirstVertex, aLastVertex;
1107         if (v[i] < v[j])
1108         { 
1109           aFirstVertex = v[i];
1110           aLastVertex = v[j];
1111         }
1112         else
1113         {
1114           aFirstVertex = v[j];
1115           aLastVertex = v[i];
1116         }
1117
1118         if (aCouples.Add(BRepMesh_OrientedEdge(aFirstVertex, aLastVertex)))
1119         {
1120           // Check deflection on edge 1
1121           gp_XY mi2d = (xy[i] + xy[j]) * 0.5;
1122           gFace->D0(mi2d.X(), mi2d.Y(), pDef);
1123           gp_Lin aLin(p[i], gp_Vec(p[i], p[j]));
1124           aSqDef = aLin.SquareDistance(pDef);
1125
1126           CHECK_DEF_AND_INSERT_CURRENT(isSkipped);
1127         }
1128       }
1129
1130       if (isSkipped)
1131         break;
1132
1133       //check normal on bsplines
1134       if (theIsFirst && !aBSpline.IsNull())
1135       {
1136         gp_Dir N[3] = { gp::DZ(), gp::DZ(), gp::DZ() };
1137         Standard_Integer aSt[3];
1138
1139         for (Standard_Integer i = 0; i < 3; ++i)
1140         {
1141           if (aNorMap.IsBound(v[i]))
1142           {
1143             aSt[i] = aStatMap.Find(v[i]);
1144             N[i] = aNorMap.Find(v[i]);
1145           }
1146           else
1147           {
1148             aSt[i] = GeomLib::NormEstim(aBSpline, gp_Pnt2d(xy[i]), Precision::Confusion(), N[i]);
1149             aStatMap.Bind(v[i], aSt[i]);
1150             aNorMap.Bind(v[i], N[i]);
1151           }
1152         }
1153
1154         Standard_Real aAngle[3];
1155         for (Standard_Integer i = 0; i < 3; ++i)
1156           aAngle[i] = N[(i + 1) % 3].Angle(N[i]);
1157
1158         if (aSt[0] < 1 && aSt[1] < 1 && aSt[2] < 1)
1159         {
1160           if (aAngle[0] > myAngle || aAngle[1] > myAngle || aAngle[2] > myAngle)
1161           {
1162             aMaxSqDef = -1.;
1163             break;
1164           }
1165         }
1166       }
1167     }
1168
1169     if (theIsFirst)
1170       continue;
1171
1172     if (addVerticesToMesh(theNewVertices, theTrigu))
1173       ++aInsertedNb;
1174   }
1175
1176   return (aMaxSqDef < 0) ? aMaxSqDef : Sqrt(aMaxSqDef);
1177 }
1178
1179 //=======================================================================
1180 //function : add
1181 //purpose  : 
1182 //=======================================================================
1183 void BRepMesh_FastDiscretFace::add(const TopoDS_Vertex& theVertex)
1184 {
1185   if (theVertex.Orientation() != TopAbs_INTERNAL)
1186     return;
1187
1188   try
1189   {
1190     OCC_CATCH_SIGNALS
1191
1192     gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, myAttribute->Face());
1193
1194     NCollection_Handle<FixedVExplorer> aFixedVExplorer = new FixedVExplorer(theVertex);
1195     Standard_Integer aIndex = myAttribute->GetVertexIndex(aFixedVExplorer);
1196     gp_XY anUV = BRepMesh_ShapeTool::FindUV(aIndex, aPnt2d,
1197       theVertex, BRep_Tool::Tolerance(theVertex), myAttribute);
1198
1199     Standard_Integer aTmpId1, aTmpId2;
1200     myAttribute->AddNode(aIndex, anUV, BRepMesh_Fixed, aTmpId1, aTmpId2);
1201   }
1202   catch (Standard_Failure)
1203   {
1204   }
1205 }
1206
1207 //=======================================================================
1208 //function : insertVertex
1209 //purpose  : 
1210 //=======================================================================
1211 void BRepMesh_FastDiscretFace::insertVertex(
1212   const gp_Pnt&           thePnt3d,
1213   const gp_XY&            theUV,
1214   BRepMesh::ListOfVertex& theVertices)
1215 {
1216   Standard_Integer aNbLocat = myAttribute->LastPointId();
1217   mySurfacePoints->Bind(++aNbLocat, thePnt3d);
1218
1219   gp_XY aPnt2d  = myAttribute->Scale(theUV, Standard_True);
1220   BRepMesh_Vertex aVertex(aPnt2d, aNbLocat, BRepMesh_Free);
1221   theVertices.Append(aVertex);
1222 }
1223
1224 //=======================================================================
1225 //function : commitSurfaceTriangulation
1226 //purpose  : 
1227 //=======================================================================
1228 void BRepMesh_FastDiscretFace::commitSurfaceTriangulation()
1229 {
1230   if (myAttribute.IsNull() || !myAttribute->IsValid())
1231     return;
1232
1233   TopoDS_Face aFace = myAttribute->Face();
1234   BRepMesh_ShapeTool::NullifyFace(aFace);
1235
1236   Handle(BRepMesh_DataStructureOfDelaun)& aStructure = myAttribute->ChangeStructure();
1237   const BRepMesh::MapOfInteger&           aTriangles = aStructure->ElementsOfDomain();
1238
1239   if (aTriangles.IsEmpty())
1240     return;
1241
1242   BRepMesh::HIMapOfInteger& aVetrexEdgeMap = myAttribute->ChangeVertexEdgeMap();
1243
1244   // Store triangles
1245   Standard_Integer aVerticesNb  = aVetrexEdgeMap->Extent();
1246   Standard_Integer aTrianglesNb = aTriangles.Extent();
1247   Handle(Poly_Triangulation) aNewTriangulation =
1248     new Poly_Triangulation(aVerticesNb, aTrianglesNb, Standard_True);
1249
1250   Poly_Array1OfTriangle& aPolyTrianges = aNewTriangulation->ChangeTriangles();
1251
1252   Standard_Integer aTriangeId = 1;
1253   BRepMesh::MapOfInteger::Iterator aTriIt(aTriangles);
1254   for (; aTriIt.More(); aTriIt.Next())
1255   {
1256     const BRepMesh_Triangle& aCurElem = aStructure->GetElement(aTriIt.Key());
1257
1258     Standard_Integer aNode[3];
1259     aStructure->ElementNodes(aCurElem, aNode);
1260
1261     Standard_Integer aNodeId[3];
1262     for (Standard_Integer i = 0; i < 3; ++i)
1263       aNodeId[i] = aVetrexEdgeMap->FindIndex(aNode[i]);
1264
1265     aPolyTrianges(aTriangeId++).Set(aNodeId[0], aNodeId[1], aNodeId[2]);
1266   }
1267
1268   // Store mesh nodes
1269   TColgp_Array1OfPnt&   aNodes   = aNewTriangulation->ChangeNodes();
1270   TColgp_Array1OfPnt2d& aNodes2d = aNewTriangulation->ChangeUVNodes();
1271
1272   for (Standard_Integer i = 1; i <= aVerticesNb; ++i)
1273   {
1274     Standard_Integer       aVertexId = aVetrexEdgeMap->FindKey(i);
1275     const BRepMesh_Vertex& aVertex   = aStructure->GetNode(aVertexId);
1276     const gp_Pnt&          aPoint    = myAttribute->GetPoint(aVertex);
1277
1278     aNodes(i)   = aPoint;
1279     aNodes2d(i) = aVertex.Coord();
1280   }
1281
1282   aNewTriangulation->Deflection(myAttribute->GetDefFace());
1283   BRepMesh_ShapeTool::AddInFace(aFace, aNewTriangulation);
1284
1285   // Delete unused data
1286   myStructure.Nullify();
1287   myAttribute->Clear(Standard_True);
1288 }