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