0025612: Introduce possibility to disable adaptive reconfigutation of triangles in...
[occt.git] / src / BRepMesh / BRepMesh_FastDiscret.cxx
1 // Created on: 1996-02-27
2 // Created by: Ekaterina SMIRNOVA
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepMesh_FastDiscret.hxx>
18
19 #include <BRepMesh_WireChecker.hxx>
20 #include <BRepMesh_FastDiscretFace.hxx>
21 #include <BRepMesh_FaceAttribute.hxx>
22 #include <BRepMesh_DataStructureOfDelaun.hxx>
23 #include <BRepMesh_GeomTool.hxx>
24 #include <BRepMesh_PairOfPolygon.hxx>
25 #include <BRepMesh_Classifier.hxx>
26 #include <BRepMesh_EdgeParameterProvider.hxx>
27 #include <BRepMesh_IEdgeTool.hxx>
28 #include <BRepMesh_EdgeTessellator.hxx>
29 #include <BRepMesh_EdgeTessellationExtractor.hxx>
30
31 #include <BRepAdaptor_Curve.hxx>
32 #include <BRepAdaptor_Surface.hxx>
33 #include <BRepAdaptor_HSurface.hxx>
34
35 #include <Bnd_Box.hxx>
36 #include <BRepTools.hxx>
37 #include <BRepBndLib.hxx>
38 #include <BndLib_Add3dCurve.hxx>
39 #include <Poly_Triangulation.hxx>
40 #include <Poly_PolygonOnTriangulation.hxx>
41
42 #include <Precision.hxx>
43 #include <Geom2d_Curve.hxx>
44 #include <Geom_Surface.hxx>
45 #include <Geom_Plane.hxx>
46 #include <GeomAbs_SurfaceType.hxx>
47 #include <Extrema_LocateExtPC.hxx>
48
49 #include <TColStd_Array1OfInteger.hxx>
50 #include <TColStd_HArray1OfReal.hxx>
51 #include <TColgp_Array1OfPnt2d.hxx>
52 #include <TColGeom2d_SequenceOfCurve.hxx>
53 #include <SortTools_ShellSortOfReal.hxx>
54 #include <TCollection_CompareOfReal.hxx>
55
56 #include <TopTools_SequenceOfShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58
59 #include <TopAbs.hxx>
60 #include <TopoDS.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopExp.hxx>
63 #include <TopExp_Explorer.hxx>
64
65 #include <Standard_ErrorHandler.hxx>
66 #include <Standard_Failure.hxx>
67 #include <NCollection_IncAllocator.hxx>
68
69 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
70 #include <BRep_PointRepresentation.hxx>
71
72 #include <vector>
73
74 #ifdef HAVE_TBB
75   // paralleling using Intel TBB
76   #include <tbb/parallel_for_each.h>
77 #endif
78
79 #define UVDEFLECTION 1.e-05
80
81 IMPLEMENT_STANDARD_HANDLE (BRepMesh_FastDiscret, Standard_Transient)
82 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret, Standard_Transient)
83
84 //=======================================================================
85 //function : BRepMesh_FastDiscret
86 //purpose  : 
87 //=======================================================================
88 BRepMesh_FastDiscret::BRepMesh_FastDiscret(
89   const Standard_Real    theDefle,
90   const Standard_Real    theAngl,
91   const Bnd_Box&         theBox,
92   const Standard_Boolean theWithShare,
93   const Standard_Boolean theInshape,
94   const Standard_Boolean theRelative,
95   const Standard_Boolean theShapetrigu,
96   const Standard_Boolean isInParallel,
97   const Standard_Real    theMinSize,
98   const Standard_Boolean isInternalVerticesMode,
99   const Standard_Boolean isControlSurfaceDeflection)
100 : myAngle (theAngl),
101   myDeflection (theDefle),
102   myWithShare (theWithShare),
103   myInParallel (isInParallel),
104   myRelative (theRelative),
105   myShapetrigu (theShapetrigu), 
106   myInshape (theInshape),
107   myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
108   myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt),
109   myMinSize(theMinSize),
110   myInternalVerticesMode(isInternalVerticesMode),
111   myIsControlSurfaceDeflection(isControlSurfaceDeflection)
112 {
113   if ( myRelative )
114     BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
115 }
116
117 //=======================================================================
118 //function : BRepMesh_FastDiscret
119 //purpose  : 
120 //=======================================================================
121 BRepMesh_FastDiscret::BRepMesh_FastDiscret(
122   const TopoDS_Shape&    theShape,
123   const Standard_Real    theDefle,
124   const Standard_Real    theAngl,
125   const Bnd_Box&         theBox,
126   const Standard_Boolean theWithShare,
127   const Standard_Boolean theInshape,
128   const Standard_Boolean theRelative,
129   const Standard_Boolean theShapetrigu,
130   const Standard_Boolean isInParallel,
131   const Standard_Real    theMinSize,
132   const Standard_Boolean isInternalVerticesMode,
133   const Standard_Boolean isControlSurfaceDeflection)
134 : myAngle (theAngl),
135   myDeflection (theDefle),
136   myWithShare (theWithShare),
137   myInParallel (isInParallel),
138   myRelative (theRelative),
139   myShapetrigu (theShapetrigu),
140   myInshape (theInshape),
141   myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
142   myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt),
143   myMinSize(theMinSize),
144   myInternalVerticesMode(isInternalVerticesMode),
145   myIsControlSurfaceDeflection(isControlSurfaceDeflection)
146 {
147   if ( myRelative )
148     BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
149
150   Perform(theShape);
151 }
152
153 //=======================================================================
154 //function : InitSharedFaces
155 //purpose  : 
156 //=======================================================================
157 void BRepMesh_FastDiscret::InitSharedFaces(const TopoDS_Shape& theShape)
158 {
159   TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces);
160 }
161
162 //=======================================================================
163 //function : Perform(shape)
164 //purpose  : 
165 //=======================================================================
166 void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
167 {
168   InitSharedFaces(theShape);
169
170   std::vector<TopoDS_Face> aFaces;
171   TopExp_Explorer anExplorer(theShape, TopAbs_FACE);
172   for (; anExplorer.More(); anExplorer.Next())
173   {
174     const TopoDS_Face& aFace = TopoDS::Face(anExplorer.Current());
175     Add(aFace);
176     aFaces.push_back(aFace);
177   }
178
179 #ifdef HAVE_TBB
180   if ( myInParallel )
181   {
182     tbb::parallel_for_each(aFaces.begin(), aFaces.end(), *this);
183   }
184   else
185   {
186 #endif
187     std::vector<TopoDS_Face>::const_iterator anIt(aFaces.begin());
188     for (; anIt != aFaces.end(); anIt++)
189       Process(*anIt);
190 #ifdef HAVE_TBB
191   }
192 #endif
193 }
194
195
196 //=======================================================================
197 //function : Process
198 //purpose  : 
199 //=======================================================================
200 void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
201 {
202   Handle(BRepMesh_FaceAttribute) anAttribute;
203   if (GetFaceAttribute(theFace, anAttribute))
204   {
205     try
206     {
207       OCC_CATCH_SIGNALS
208
209       BRepMesh_FastDiscretFace aTool(GetAngle(), myMinSize, 
210         myInternalVerticesMode, myIsControlSurfaceDeflection);
211       aTool.Perform(anAttribute);
212     }
213     catch (Standard_Failure)
214     {
215       anAttribute->SetStatus(BRepMesh_Failure);
216     }
217   }
218 }
219
220 //=======================================================================
221 //function : resetDataStructure
222 //purpose  : 
223 //=======================================================================
224 void BRepMesh_FastDiscret::resetDataStructure()
225 {
226   Handle(NCollection_IncAllocator) aAllocator;
227   if (myAttribute->ChangeStructure().IsNull())
228     aAllocator = new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
229   else
230     aAllocator = myAttribute->ChangeStructure()->Allocator();
231
232   myAttribute->Clear();
233   aAllocator->Reset(Standard_False);
234   Handle(BRepMesh_DataStructureOfDelaun) aStructure = 
235     new BRepMesh_DataStructureOfDelaun(aAllocator);
236
237   const Standard_Real aTolU = myAttribute->ToleranceU();
238   const Standard_Real aTolV = myAttribute->ToleranceV();
239   const Standard_Real uCellSize = 14.0 * aTolU;
240   const Standard_Real vCellSize = 14.0 * aTolV;
241
242   aStructure->Data()->SetCellSize ( uCellSize, vCellSize);
243   aStructure->Data()->SetTolerance( aTolU    , aTolV    );
244
245   myAttribute->ChangeStructure() = aStructure;
246 }
247
248 //=======================================================================
249 //function : Add(face)
250 //purpose  : 
251 //=======================================================================
252 Standard_Integer BRepMesh_FastDiscret::Add(const TopoDS_Face& theFace)
253 {
254   try
255   {
256     OCC_CATCH_SIGNALS
257
258     // Initialize face attributes
259     myAttribute.Nullify();
260     GetFaceAttribute(theFace, myAttribute);
261     if (myAttribute.IsNull())
262     {
263       myAttribute = new BRepMesh_FaceAttribute(theFace,
264         myBoundaryVertices, myBoundaryPoints);
265
266       myAttributes.Bind(theFace, myAttribute);
267     }
268
269     BRepMesh::HIMapOfInteger&            aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
270     BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
271
272     resetDataStructure();
273
274     if (!myWithShare)
275     {
276       myEdges.Clear();
277       myBoundaryVertices->Clear();
278       myBoundaryPoints->Clear();
279     }
280
281     Standard_Real defedge;
282     Standard_Integer nbEdge = 0;
283     Standard_Real savangle = myAngle;
284     Standard_Real cdef;
285     Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theFace);
286
287     Standard_Real defface = 0.;
288     if (!myRelative)
289       defface = Max(myDeflection, maxdef);
290
291     NCollection_Sequence<EdgePCurve>  aPCurves;
292     NCollection_Sequence<TopoDS_Edge> aFaceEdges;
293
294     const TopoDS_Face&                  aFace = myAttribute->Face();
295     const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
296     TopExp_Explorer aWireIt(aFace, TopAbs_WIRE);
297     for (; aWireIt.More(); aWireIt.Next())
298     {
299       TopExp_Explorer aEdgeIt(aWireIt.Current(), TopAbs_EDGE);
300       for (; aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge)
301       {
302         const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
303         if (!myMapdefle.IsBound(aEdge))
304         {
305           if (myRelative)
306           {
307             if (myEdges.IsBound(aEdge))
308             {
309               const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge);
310               const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
311               defedge = aPolygon->Deflection();
312             }
313             else
314             {
315               defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection(
316                 aEdge, myDeflection, myDtotale, cdef);
317
318               myAngle = savangle * cdef;
319             }
320
321             defface += defedge;
322             defface = Max(maxdef, defface);
323           }
324           else
325           {
326             defedge = myDeflection;
327           }
328
329           defedge = Max(maxdef, defedge);
330           defedge = Max(UVDEFLECTION, defedge);
331           myMapdefle.Bind(aEdge, defedge);
332         }
333         else
334         {
335           defedge = myMapdefle(aEdge);
336           if ( myRelative )
337           {
338             defface += defedge;
339             defface = Max(maxdef, defface);
340           }
341         }
342
343         Standard_Real aFirstParam, aLastParam;
344         Handle(Geom2d_Curve) aCurve2d = 
345           BRep_Tool::CurveOnSurface(aEdge, aFace, aFirstParam, aLastParam);
346
347         if (aCurve2d.IsNull())
348           continue;
349
350         EdgePCurve aPCurve = { aCurve2d, aFirstParam, aLastParam };
351         aPCurves.Append(aPCurve);
352         aFaceEdges.Append(aEdge);
353
354         add(aEdge, aPCurve, defedge);
355         myAngle = savangle;
356       }
357     }
358
359     if ( nbEdge == 0 || aVertexEdgeMap->Extent() < 3 )
360     {
361       myAttribute->ChangeStructure().Nullify();
362       myAttribute->SetStatus(BRepMesh_Failure);
363       return myAttribute->GetStatus();
364     }
365
366     if ( myRelative )
367     {
368       defface = defface / nbEdge;
369     }
370     else
371     {
372       defface = myDeflection;
373     }
374
375     if ( myWithShare )
376       defface = Max(maxdef, defface);
377
378     TopLoc_Location aLoc;
379     Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
380
381     if (!myShapetrigu || aTriangulation.IsNull())
382     {
383       Standard_Real xCur, yCur;
384       Standard_Real maxX, minX, maxY, minY;
385
386       minX = minY = 1.e100;
387       maxX = maxY =-1.e100;
388
389       Standard_Integer ipn = 0;
390       Standard_Integer i1 = 1;
391       for ( i1 = 1; i1 <= aVertexEdgeMap->Extent(); ++i1 )
392       {
393         const BRepMesh_Vertex& aVertex = 
394           myAttribute->ChangeStructure()->GetNode(aVertexEdgeMap->FindKey(i1));
395
396         ++ipn;
397
398         xCur = aVertex.Coord().X();
399         yCur = aVertex.Coord().Y();
400
401         minX = Min(xCur, minX);
402         maxX = Max(xCur, maxX);
403         minY = Min(yCur, minY);
404         maxY = Max(yCur, maxY);
405       }
406
407       Standard_Real myumin = minX;
408       Standard_Real myumax = maxX;
409       Standard_Real myvmin = minY;
410       Standard_Real myvmax = maxY;
411
412       const Standard_Real umin = gFace->FirstUParameter();
413       const Standard_Real umax = gFace->LastUParameter();
414       const Standard_Real vmin = gFace->FirstVParameter();
415       const Standard_Real vmax = gFace->LastVParameter();
416
417       if (myumin < umin || myumax > umax)
418       {
419         if (gFace->IsUPeriodic())
420         {
421           if ((myumax - myumin) > (umax - umin))
422             myumax = myumin + (umax - umin);
423         }
424         else
425         {
426           if (umin > myumin)
427             myumin = umin;
428
429           if (umax < myumax)
430             myumax = umax;
431         }
432       }
433
434       if (myvmin < vmin || myvmax > vmax)
435       {
436         if (gFace->IsVPeriodic())
437         {
438           if ((myvmax - myvmin) > (vmax - vmin))
439             myvmax = myvmin + (vmax - vmin);
440         }
441         else
442         {
443           if ( vmin > myvmin )
444             myvmin = vmin;
445
446           if (vmax < myvmax)
447             myvmax = vmax;
448         }
449       }
450
451       GeomAbs_SurfaceType aSurfType = gFace->GetType();
452       // Fast verification of the validity of calculated limits.
453       // If wrong, sure a problem of pcurve.
454       if (aSurfType == GeomAbs_BezierSurface &&
455          (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5) )
456       {
457         myAttribute->ChangeStructure().Nullify();
458         myAttribute->SetStatus(BRepMesh_Failure);
459         return myAttribute->GetStatus();
460       }
461
462       //define parameters for correct parametrics
463       Standard_Real deltaX = 1.0;
464       Standard_Real deltaY = 1.0;
465
466       {
467         BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier();
468         BRepMesh_WireChecker aDFaceChecker(aFace, Precision::PConfusion(),
469           aInternalEdges, aVertexEdgeMap, myAttribute->ChangeStructure(),
470           myumin, myumax, myvmin, myvmax, myInParallel );
471
472         aDFaceChecker.ReCompute(aClassifier);
473         BRepMesh_Status aCheckStatus = aDFaceChecker.Status();
474
475         if (aCheckStatus == BRepMesh_SelfIntersectingWire)
476         {
477           Standard_Integer nbmaill = 0;
478           Standard_Real eps = Precision::Confusion();
479           while (nbmaill < 5 && aCheckStatus != BRepMesh_ReMesh)
480           {
481             ++nbmaill;
482
483             resetDataStructure();
484             for (Standard_Integer j = 1; j <= aFaceEdges.Length(); ++j)
485             {
486               const TopoDS_Edge& anEdge = aFaceEdges(j);
487               if (myEdges.IsBound(anEdge))
488                 myEdges.UnBind(anEdge);
489
490               defedge = Max(myMapdefle(anEdge) / 3.0, eps);
491               myMapdefle.Bind(anEdge, defedge);
492
493               add(anEdge, aPCurves(j), defedge);
494             }
495
496             aDFaceChecker.ReCompute(aClassifier);
497             if (aDFaceChecker.Status() == BRepMesh_NoError)
498               aCheckStatus = BRepMesh_ReMesh;
499           }
500         }
501
502         myAttribute->SetStatus(aCheckStatus);
503         if (!myAttribute->IsValid())
504         {
505           myAttribute->ChangeStructure().Nullify();
506           return myAttribute->GetStatus();
507         }
508       }
509
510       // try to find the real length:
511       // akm (bug OCC16) : We must calculate these measures in non-singular
512       //     parts of face. Let's try to compute average value of three
513       //     (umin, (umin+umax)/2, umax), and respectively for v.
514       //                 vvvvv
515       Standard_Real longu = 0.0, longv = 0.0; //, last , first;
516       gp_Pnt P11, P12, P21, P22, P31, P32;
517
518       Standard_Real du = 0.05 * ( myumax - myumin );
519       Standard_Real dv = 0.05 * ( myvmax - myvmin );
520       Standard_Real dfuave = 0.5 * ( myumin + myumax );
521       Standard_Real dfvave = 0.5 * ( myvmin + myvmax );
522       Standard_Real dfucur, dfvcur;
523
524       // U loop
525       gFace->D0(myumin, myvmin, P11);
526       gFace->D0(myumin, dfvave, P21);
527       gFace->D0(myumin, myvmax, P31);
528       for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du)
529       {
530         gFace->D0(dfucur, myvmin, P12);
531         gFace->D0(dfucur, dfvave, P22);
532         gFace->D0(dfucur, myvmax, P32);
533         longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
534         P11 = P12;
535         P21 = P22;
536         P31 = P32;
537       }
538
539       // V loop
540       gFace->D0(myumin, myvmin, P11);
541       gFace->D0(dfuave, myvmin, P21);
542       gFace->D0(myumax, myvmin, P31);
543       for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv)
544       {
545         gFace->D0(myumin, dfvcur, P12);
546         gFace->D0(dfuave, dfvcur, P22);
547         gFace->D0(myumax, dfvcur, P32);
548         longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
549         P11 = P12;
550         P21 = P22;
551         P31 = P32;
552       }
553
554       longu /= 3.;
555       longv /= 3.;
556       // akm (bug OCC16) ^^^^^
557
558       if (longu <= 1.e-16 || longv <= 1.e-16)
559       {
560         //yes, it is seen!!
561         myAttribute->ChangeStructure().Nullify();
562         myAttribute->SetStatus(BRepMesh_Failure);
563         return myAttribute->GetStatus();
564       }
565
566
567       if (aSurfType == GeomAbs_Torus)
568       {
569         gp_Torus Tor = gFace->Torus();
570         Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius();
571         Standard_Real Du, Dv;//, pasu, pasv;
572
573         Dv = Max(1.0e0 - (defface/r),0.0e0) ;
574         Standard_Real oldDv = 2.0 * ACos (Dv);
575         oldDv = Min(oldDv, myAngle);
576         Dv  =  0.9*oldDv; //TWOTHIRD * oldDv;
577         Dv = oldDv;
578
579         Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2);
580         Dv = (myvmax-myvmin)/(nbV+1);
581
582         Standard_Real ru = R + r;
583         if ( ru > 1.e-16 )
584         {
585           Du = Max(1.0e0 - (defface/ru),0.0e0);
586           Du  = (2.0 * ACos (Du));
587           Du = Min(Du, myAngle);
588           Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
589
590           if (aa < gp::Resolution())
591           {
592             myAttribute->ChangeStructure().Nullify();
593             return myAttribute->GetStatus();
594           }
595
596           Du = Du * Min(oldDv, Du) / aa;
597         }
598         else
599         {
600           Du = Dv;
601         }
602
603         Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2);
604         nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.));
605       
606         Du = (myumax-myumin)/(nbU+1);
607         //-- DeltaX and DeltaY are chosen so that to avoid "jumping" 
608         //-- of points on the grid
609         deltaX = Du;
610         deltaY = Dv;
611       }
612       else if (aSurfType == GeomAbs_Cylinder)
613       {
614         gp_Cylinder Cyl = gFace->Cylinder();
615         Standard_Real R = Cyl.Radius();
616
617         // Calculate parameters for iteration in U direction
618         Standard_Real Du = 1.0 - (defface/R);
619         if (Du < 0.0)
620           Du = 0.0;
621
622         Du = 2.0 * ACos (Du);
623         if (Du > GetAngle())
624           Du = GetAngle();
625
626         deltaX = Du / longv;
627         deltaY = 1.;
628       }
629       else
630       {
631         deltaX = (myumax-myumin)/longu;
632         deltaY = (myvmax-myvmin)/longv;
633       }
634
635       // Restore face attribute
636       myAttribute->SetDefFace(defface);
637       myAttribute->SetUMax(myumax);
638       myAttribute->SetVMax(myvmax);
639       myAttribute->SetUMin(myumin);
640       myAttribute->SetVMin(myvmin);
641       myAttribute->SetDeltaX(deltaX);
642       myAttribute->SetDeltaY(deltaY);
643     }
644   }
645   catch(Standard_Failure)
646   {
647     myAttribute->SetStatus(BRepMesh_Failure);
648   }
649
650   myAttribute->ChangeMeshNodes() = 
651     myAttribute->ChangeStructure()->Data()->Vertices();
652
653   myAttribute->ChangeStructure().Nullify();
654   return myAttribute->GetStatus();
655 }
656
657 //=======================================================================
658 //function : getEdgeAttributes
659 //purpose  :
660 //=======================================================================
661 Standard_Boolean BRepMesh_FastDiscret::getEdgeAttributes(
662   const TopoDS_Edge&                      theEdge,
663   const BRepMesh_FastDiscret::EdgePCurve& thePCurve,
664   const Standard_Real                     theDefEdge,
665   BRepMesh_FastDiscret::EdgeAttributes&   theAttributes) const
666 {
667   EdgeAttributes& aEAttr = theAttributes;
668
669   // Get vertices
670   TopExp::Vertices(theEdge, aEAttr.FirstVertex, aEAttr.LastVertex);
671   if (aEAttr.FirstVertex.IsNull() || aEAttr.LastVertex.IsNull())
672     return Standard_False;
673
674   // Get range on 2d curve
675   const TopoDS_Face& aFace = myAttribute->Face();
676   BRep_Tool::Range(theEdge, aFace, aEAttr.FirstParam, aEAttr.LastParam);
677
678   // Get end points on 2d curve
679   BRep_Tool::UVPoints(theEdge, aFace, aEAttr.FirstUV, aEAttr.LastUV);
680
681   aEAttr.IsSameUV =
682     aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion());
683
684   //Control tolerance of vertices
685   const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
686   gp_Pnt pFirst = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y());
687   gp_Pnt pLast  = gFace->Value(aEAttr.LastUV.X(),  aEAttr.LastUV.Y());
688
689   aEAttr.MinDist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(aEAttr.FirstVertex)),
690                              pLast .Distance(BRep_Tool::Pnt(aEAttr.LastVertex)));
691
692   if (aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.FirstVertex) ||
693       aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.LastVertex))
694   {
695     aEAttr.MinDist = theDefEdge;
696   }
697
698   if (aEAttr.IsSameUV)
699   {
700     // 1. is it really sameUV without being degenerated
701     gp_Pnt2d uvF, uvL;
702     thePCurve.Curve2d->D0(thePCurve.FirstParam, uvF);
703     thePCurve.Curve2d->D0(thePCurve.LastParam,  uvL);
704
705     if (!aEAttr.FirstUV.IsEqual(uvF, Precision::PConfusion()))
706       aEAttr.FirstUV = uvF;
707
708     if (!aEAttr.LastUV.IsEqual(uvL, Precision::PConfusion()))
709       aEAttr.LastUV = uvL;
710   }
711
712   return Standard_True;
713 }
714
715 //=======================================================================
716 //function : registerEdgeVertices
717 //purpose  : 
718 //=======================================================================
719 void BRepMesh_FastDiscret::registerEdgeVertices(
720   BRepMesh_FastDiscret::EdgeAttributes& theAttributes,
721   Standard_Integer&                     ipf,
722   Standard_Integer&                     ivf,
723   Standard_Integer&                     isvf,
724   Standard_Integer&                     ipl,
725   Standard_Integer&                     ivl,
726   Standard_Integer&                     isvl)
727 {
728   EdgeAttributes& aEAttr = theAttributes;
729   if (aEAttr.FirstVExtractor.IsNull())
730   {
731     // Use edge geometry to produce tesselation.
732     aEAttr.FirstVExtractor = 
733       new TopoDSVExplorer(aEAttr.FirstVertex, aEAttr.IsSameUV, aEAttr.LastVertex);
734   }
735
736   if (aEAttr.LastVExtractor.IsNull())
737   {
738     // Use edge geometry to produce tesselation.
739     aEAttr.LastVExtractor = 
740       new TopoDSVExplorer(aEAttr.LastVertex, aEAttr.IsSameUV, aEAttr.FirstVertex);
741   }
742
743   gp_XY aTmpUV;
744   // Process first vertex
745   ipf = myAttribute->GetVertexIndex(aEAttr.FirstVExtractor, Standard_True);
746   aTmpUV = BRepMesh_ShapeTool::FindUV(ipf, aEAttr.FirstUV, aEAttr.FirstVertex, 
747     aEAttr.MinDist, myAttribute);
748
749   myAttribute->AddNode(ipf, aTmpUV, BRepMesh_Frontier, ivf, isvf);
750
751   // Process last vertex
752   ipl = aEAttr.LastVertex.IsSame(aEAttr.FirstVertex) ? ipf :
753     myAttribute->GetVertexIndex(aEAttr.LastVExtractor, Standard_True);
754   aTmpUV = BRepMesh_ShapeTool::FindUV(ipl, aEAttr.LastUV, aEAttr.LastVertex, 
755     aEAttr.MinDist, myAttribute);
756
757   myAttribute->AddNode(ipl, aTmpUV, BRepMesh_Frontier, ivl, isvl);
758 }
759
760 //=======================================================================
761 //function : add
762 //purpose  : 
763 //=======================================================================
764 void BRepMesh_FastDiscret::add(
765   const TopoDS_Edge&                      theEdge,
766   const BRepMesh_FastDiscret::EdgePCurve& thePCurve,
767   const Standard_Real                     theDefEdge)
768 {
769   const TopAbs_Orientation orEdge = theEdge.Orientation();
770   if (orEdge == TopAbs_EXTERNAL)
771     return;
772
773   EdgeAttributes aEAttr;
774   if (!getEdgeAttributes(theEdge, thePCurve, theDefEdge, aEAttr))
775     return;
776
777   if (!myEdges.IsBound(theEdge))
778   {
779     update(theEdge, thePCurve.Curve2d, theDefEdge, aEAttr);
780     return;
781   }
782
783   Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
784   registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
785
786   // If this Edge has been already checked and it is not degenerated, 
787   // the points of the polygon calculated at the first check are retrieved :
788
789   // retrieve the polygone:
790   const BRepMesh_PairOfPolygon&              aPair    = myEdges.Find(theEdge);
791   const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
792   const TColStd_Array1OfInteger&             aNodes   = aPolygon->Nodes();
793   Handle(TColStd_HArray1OfReal)              aParams  = aPolygon->Parameters();
794
795   // creation anew:
796   const Standard_Integer  aNodesNb = aNodes.Length();
797   TColStd_Array1OfInteger aNewNodes (1, aNodesNb);
798   TColStd_Array1OfReal    aNewParams(1, aNodesNb);
799
800   aNewNodes (1) = isvf;
801   aNewParams(1) = aEAttr.FirstParam;
802
803   aNewNodes (aNodesNb) = isvl;
804   aNewParams(aNodesNb) = aEAttr.LastParam;
805
806   const TopoDS_Face& aFace = myAttribute->Face();
807   if (!BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
808   {
809     BRepMesh_EdgeParameterProvider aProvider(theEdge, aFace, aParams);
810     for (Standard_Integer i = 2; i < aNodesNb; ++i)
811     {
812       const Standard_Integer aPointId = aNodes(i);
813       const gp_Pnt& aPnt = myBoundaryPoints->Find(aPointId);
814
815       const Standard_Real aParam = aProvider.Parameter(i, aPnt);
816       gp_Pnt2d aUV = thePCurve.Curve2d->Value(aParam);
817
818       Standard_Integer iv2, isv;
819       myAttribute->AddNode(aPointId, aUV.Coord(), BRepMesh_OnCurve, iv2, isv);
820
821       aNewNodes (i) = isv;
822       aNewParams(i) = aParam;
823     }
824   }
825
826   Handle(Poly_PolygonOnTriangulation) P1 = 
827     new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
828
829   storePolygon(theEdge, P1, theDefEdge);
830 }
831
832 //=======================================================================
833 //function : update(edge)
834 //purpose  :
835 //=======================================================================
836 void BRepMesh_FastDiscret::update(
837   const TopoDS_Edge&                                theEdge,
838   const Handle(Geom2d_Curve)&                       theC2d,
839   const Standard_Real                               theDefEdge,
840   BRepMesh_FastDiscret::EdgeAttributes&             theAttributes)
841 {
842   EdgeAttributes& aEAttr = theAttributes;
843
844   const TopoDS_Face& aFace = myAttribute->Face();
845   Handle(BRepMesh_IEdgeTool) aEdgeTool;
846   // Try to find existing tessellation.
847   for (Standard_Integer i = 1; aEdgeTool.IsNull(); ++i)
848   {
849     TopLoc_Location aLoc;
850     Handle(Poly_Triangulation) aTriangulation;
851     Handle(Poly_PolygonOnTriangulation) aPolygon;
852     BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, aTriangulation, aLoc, i);
853
854     if (aPolygon.IsNull())
855       break;
856
857     if (aTriangulation.IsNull() || !aPolygon->HasParameters())
858       continue;
859
860     if (aPolygon->Deflection() > 1.1 * theDefEdge)
861       continue;
862
863     const TColgp_Array1OfPnt&      aNodes   = aTriangulation->Nodes();
864     const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes();
865     Handle(TColStd_HArray1OfReal)  aParams  = aPolygon->Parameters();
866
867     aEAttr.FirstVExtractor = new PolyVExplorer(aEAttr.FirstVertex, 
868       aEAttr.IsSameUV, aEAttr.LastVertex, aIndices(1), aNodes, aLoc);
869
870     aEAttr.LastVExtractor = new PolyVExplorer(aEAttr.LastVertex, 
871       aEAttr.IsSameUV, aEAttr.FirstVertex, aIndices(aIndices.Length()), aNodes, aLoc);
872
873     aEdgeTool = new BRepMesh_EdgeTessellationExtractor(theEdge, theC2d, 
874       aFace, aTriangulation, aPolygon, aLoc);
875   }
876
877   if (aEdgeTool.IsNull())
878   {
879     aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute, 
880       mySharedFaces, theDefEdge, myAngle, myMinSize);
881   }
882
883   Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
884   registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
885
886   Handle(Poly_PolygonOnTriangulation) P1, P2;
887   if (BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
888   {
889     const Standard_Integer  aNodesNb = 2;
890     TColStd_Array1OfInteger aNewNodes      (1, aNodesNb);
891     TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb);
892     TColStd_Array1OfReal    aNewParams     (1, aNodesNb);
893
894     aNewNodInStruct(1) = ipf;
895     aNewNodes      (1) = isvf;
896     aNewParams     (1) = aEAttr.FirstParam;
897
898     aNewNodInStruct(aNodesNb) = ipl;
899     aNewNodes      (aNodesNb) = isvl;
900     aNewParams     (aNodesNb) = aEAttr.LastParam;
901
902     P1 = new Poly_PolygonOnTriangulation(aNewNodes,       aNewParams);
903     P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
904   }
905   else
906   {
907     const Standard_Integer  aNodesNb = aEdgeTool->NbPoints();
908     TColStd_Array1OfInteger aNewNodes      (1, aNodesNb);
909     TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb);
910     TColStd_Array1OfReal    aNewParams     (1, aNodesNb);
911
912     aNewNodInStruct(1) = ipf;
913     aNewNodes      (1) = isvf;
914     aNewParams     (1) = aEAttr.FirstParam;
915
916     aNewNodInStruct(aNodesNb) = ipl;
917     aNewNodes      (aNodesNb) = isvl;
918     aNewParams     (aNodesNb) = aEAttr.LastParam;
919
920     Standard_Integer aLastPointId = myAttribute->LastPointId();
921     for (Standard_Integer i = 2; i < aNodesNb; ++i)
922     {
923       gp_Pnt        aPnt;
924       gp_Pnt2d      aUV;
925       Standard_Real aParam;
926       aEdgeTool->Value(i, aParam, aPnt, aUV);
927       myBoundaryPoints->Bind(++aLastPointId, aPnt);
928
929       Standard_Integer iv2, isv;
930       myAttribute->AddNode(aLastPointId, aUV.Coord(), BRepMesh_Frontier, iv2, isv);
931
932       aNewNodInStruct(i) = aLastPointId;
933       aNewNodes      (i) = isv;
934       aNewParams     (i) = aParam;
935     }
936
937     P1 = new Poly_PolygonOnTriangulation(aNewNodes,       aNewParams);
938     P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
939   }
940
941   storePolygon(theEdge, P1, theDefEdge);
942   storePolygonSharedData(theEdge, P2, theDefEdge);
943 }
944
945 //=======================================================================
946 //function : storeInternalPolygon
947 //purpose  : 
948 //=======================================================================
949 void BRepMesh_FastDiscret::storePolygon(
950   const TopoDS_Edge&                         theEdge,
951   Handle(Poly_PolygonOnTriangulation)&       thePolygon,
952   const Standard_Real                        theDeflection)
953 {
954   thePolygon->Deflection(theDeflection);
955   BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
956   if (aInternalEdges->IsBound(theEdge))
957   {
958     BRepMesh_PairOfPolygon& aPair = aInternalEdges->ChangeFind(theEdge);
959     if (theEdge.Orientation() == TopAbs_REVERSED)
960       aPair.Append(thePolygon);
961     else
962       aPair.Prepend(thePolygon);
963
964     return;
965   }
966
967   BRepMesh_PairOfPolygon aPair;
968   aPair.Append(thePolygon);
969   aInternalEdges->Bind(theEdge, aPair);
970 }
971
972 //=======================================================================
973 //function : storePolygonSharedData
974 //purpose  : 
975 //=======================================================================
976 void BRepMesh_FastDiscret::storePolygonSharedData(
977   const TopoDS_Edge&                         theEdge,
978   Handle(Poly_PolygonOnTriangulation)&       thePolygon,
979   const Standard_Real                        theDeflection)
980 {
981   thePolygon->Deflection(theDeflection);
982   BRepMesh_PairOfPolygon aPair;
983   aPair.Append(thePolygon);
984   myEdges.Bind(theEdge, aPair);
985 }
986
987 //=======================================================================
988 //function : GetFaceAttribute
989 //purpose  : 
990 //=======================================================================
991 Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(
992   const TopoDS_Face&              theFace,
993   Handle(BRepMesh_FaceAttribute)& theAttribute ) const
994 {
995   if (myAttributes.IsBound(theFace))
996   {
997     theAttribute = myAttributes(theFace);
998     return Standard_True;
999   }
1000
1001   return Standard_False;
1002 }
1003
1004 //=======================================================================
1005 //function : RemoveFaceAttribute
1006 //purpose  : 
1007 //=======================================================================
1008 void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace)
1009 {
1010   if (myAttributes.IsBound(theFace))
1011     myAttributes.UnBind(theFace);
1012 }