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