Test for 0022778: Bug in BRepMesh
[occt.git] / src / TopOpeBRepBuild / TopOpeBRepBuild_Tools_1.cxx
1 // Created on: 2000-02-11
2 // Created by: Peter KURNEV
3 // Copyright (c) 2000-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21
22 #include <TopOpeBRepBuild_Tools.ixx>
23
24
25 #include <TopTools_IndexedMapOfShape.hxx>
26 #include <TopExp.hxx>
27 #include <TopExp_Explorer.hxx>
28
29 #include <TopoDS.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Vertex.hxx>
32 #include <TopoDS_Face.hxx>
33
34 #include <TopLoc_Location.hxx>
35
36 #include <BRep_TVertex.hxx>
37 #include <BRep_TEdge.hxx>
38 #include <BRep_TFace.hxx>
39 #include <BRep_Tool.hxx>
40 #include <BRep_GCurve.hxx>
41 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
42 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
43 #include <BRep_CurveRepresentation.hxx>
44 #include <BRep_PointRepresentation.hxx>
45
46 #include <Geom_Curve.hxx>
47 #include <Geom_Surface.hxx>
48 #include <Geom_Plane.hxx>
49 #include <Geom_TrimmedCurve.hxx>
50
51 #include <GeomAdaptor_Curve.hxx>
52 #include <GeomAdaptor_HCurve.hxx>
53 #include <GeomAdaptor_HSurface.hxx>
54
55 #include <Geom2d_Curve.hxx>
56
57 #include <Geom2dAdaptor_HCurve.hxx>
58 #include <Geom_RectangularTrimmedSurface.hxx>
59 #include <Geom2dAdaptor.hxx>
60 #include <GeomProjLib.hxx>
61
62 #include <gp_Pnt.hxx>
63
64 #include <Adaptor3d_HCurve.hxx>
65 #include <Adaptor3d_CurveOnSurface.hxx>
66 #include <Adaptor3d_HCurveOnSurface.hxx>
67
68 #include <ProjLib_ProjectedCurve.hxx>
69 #include <Extrema_LocateExtPC.hxx>
70 #include <BRepCheck_Wire.hxx>
71
72 static 
73   void CheckEdge (const TopoDS_Edge& E,
74                   const Standard_Real aMaxTol);
75 static 
76   void CorrectEdgeTolerance (const TopoDS_Edge& myShape,
77                              const TopoDS_Face& S,
78                              const Standard_Real aMaxTol);
79 static 
80   Standard_Boolean Validate(const Adaptor3d_Curve& CRef,
81                          const Adaptor3d_Curve& Other,
82                          const Standard_Real Tol,
83                          const Standard_Boolean SameParameter,
84                          Standard_Real& aNewTolerance);
85
86 //=======================================================================
87 // Function : CorrectTolerances
88 // purpose : 
89 //=======================================================================
90   void TopOpeBRepBuild_Tools::CorrectTolerances(const TopoDS_Shape& aShape,
91                                                 const Standard_Real aMaxTol)
92 {
93   TopOpeBRepBuild_Tools::CorrectPointOnCurve(aShape, aMaxTol);
94   TopOpeBRepBuild_Tools::CorrectCurveOnSurface(aShape, aMaxTol);
95 }
96
97 //=======================================================================
98 // Function : CorrectPointOnCurve
99 // purpose : 
100 //=======================================================================
101   void TopOpeBRepBuild_Tools::CorrectPointOnCurve(const TopoDS_Shape& S,
102                                                   const Standard_Real aMaxTol)
103 {
104   Standard_Integer i, aNb;
105   TopTools_IndexedMapOfShape Edges;
106   TopExp::MapShapes (S, TopAbs_EDGE, Edges);
107   aNb=Edges.Extent();
108   for (i=1; i<=aNb; i++) {
109     const TopoDS_Edge& E= TopoDS::Edge(Edges(i));
110     CheckEdge(E, aMaxTol);
111   }     
112 }
113
114 //=======================================================================
115 // Function : CorrectCurveOnSurface
116 // purpose : 
117 //=======================================================================
118   void TopOpeBRepBuild_Tools::CorrectCurveOnSurface(const TopoDS_Shape& S,
119                                                     const Standard_Real aMaxTol)
120 {
121   Standard_Integer i, aNbFaces, j, aNbEdges;
122   TopTools_IndexedMapOfShape Faces;
123   TopExp::MapShapes (S, TopAbs_FACE, Faces);
124   
125   aNbFaces=Faces.Extent();
126   for (i=1; i<=aNbFaces; i++) {
127     const TopoDS_Face& F= TopoDS::Face(Faces(i));
128     TopTools_IndexedMapOfShape Edges;
129     TopExp::MapShapes (F, TopAbs_EDGE, Edges);
130     aNbEdges=Edges.Extent();
131     for (j=1; j<=aNbEdges; j++) {
132       const TopoDS_Edge& E= TopoDS::Edge(Edges(j));
133       CorrectEdgeTolerance (E, F, aMaxTol);
134     }
135   }
136 }
137
138 //=======================================================================
139 // Function : CorrectEdgeTolerance
140 // purpose :  Correct tolerances for Edge 
141 //=======================================================================
142 void CorrectEdgeTolerance (const TopoDS_Edge& myShape, 
143                            const TopoDS_Face& S,
144                            const Standard_Real aMaxTol)
145 {
146   // 
147   // 1. Minimum of conditions to Perform
148   Handle (BRep_CurveRepresentation) myCref;
149   Handle (Adaptor3d_HCurve) myHCurve;
150
151   myCref.Nullify();
152
153   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&myShape.TShape());
154   BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
155   Standard_Boolean Degenerated, SameParameter, SameRange;
156
157   Standard_Integer unique = 0;
158
159   Degenerated   = TE->Degenerated();
160   SameParameter = TE->SameParameter();
161   SameRange     = TE->SameRange();
162   
163   if (!SameRange && SameParameter) {
164     return;
165   }
166
167   while (itcr.More()) {
168     const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
169     if (cr->IsCurve3D()) {
170       unique++;
171       if (myCref.IsNull() && !cr->Curve3D().IsNull()) {
172         myCref = cr;
173       }
174     }
175     itcr.Next();
176   }
177   
178   if (unique==0) {
179     return;//...No3DCurve
180   }
181   if (unique>1) {
182     return;//...Multiple3DCurve;
183   }
184
185   if (myCref.IsNull() && !Degenerated) {
186     itcr.Initialize(TE->Curves());
187     while (itcr.More()) {
188       const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
189       if (cr->IsCurveOnSurface()) {
190         myCref = cr;
191         break;
192       }
193       itcr.Next();
194     }
195   }
196   
197   else if (!myCref.IsNull() && Degenerated){
198     return ;//...InvalidDegeneratedFlag;
199   }
200   
201   if (!myCref.IsNull()) {
202     const Handle(BRep_GCurve)& GCref = *((Handle(BRep_GCurve)*)&myCref);
203     Standard_Real First,Last;
204     GCref->Range(First,Last);
205     if (Last<=First) {
206       myCref.Nullify();
207       return ;//InvalidRange;
208     }
209     
210     else {
211       if (myCref->IsCurve3D()) {
212         Handle(Geom_Curve) C3d = Handle(Geom_Curve)::DownCast
213           (myCref->Curve3D()->Transformed (myCref->Location().Transformation()));
214         GeomAdaptor_Curve GAC3d(C3d,First,Last);
215         myHCurve = new GeomAdaptor_HCurve(GAC3d);
216       }
217       else { // curve on surface
218         Handle(Geom_Surface) Sref = myCref->Surface();
219         Sref = Handle(Geom_Surface)::DownCast(Sref->Transformed(myCref->Location().Transformation()));
220         const  Handle(Geom2d_Curve)& PCref = myCref->PCurve();
221         Handle(GeomAdaptor_HSurface) GAHSref = new GeomAdaptor_HSurface(Sref);
222         Handle(Geom2dAdaptor_HCurve) GHPCref = new Geom2dAdaptor_HCurve(PCref, First, Last);
223         Adaptor3d_CurveOnSurface ACSref(GHPCref,GAHSref);
224         myHCurve = new Adaptor3d_HCurveOnSurface(ACSref);
225       }
226     }
227   }
228
229   //=============================================== 
230   // 2. Tolerances in InContext
231   {
232     if (myCref.IsNull()) 
233       return;
234     Standard_Boolean ok=Standard_True;
235
236     Standard_Real Tol = BRep_Tool::Tolerance(TopoDS::Edge(myShape));
237     Standard_Real aNewTol=Tol;
238
239     Standard_Real First = myHCurve->FirstParameter();
240     Standard_Real Last  = myHCurve->LastParameter();
241     
242     Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &S.TShape());
243     const TopLoc_Location& Floc = S.Location();
244     const TopLoc_Location& TFloc = TF->Location();
245     const Handle(Geom_Surface)& Su = TF->Surface();
246     TopLoc_Location L = (Floc * TFloc).Predivided(myShape.Location());
247     //      Standard_Boolean checkclosed = Standard_False;
248     Standard_Boolean pcurvefound = Standard_False;
249
250     itcr.Initialize(TE->Curves());
251     while (itcr.More()) {
252       const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
253       if (cr != myCref && cr->IsCurveOnSurface(Su,L)) {
254         pcurvefound = Standard_True;
255         const Handle(BRep_GCurve)& GC = *((Handle(BRep_GCurve)*)&cr);
256         Standard_Real f,l;
257         GC->Range(f,l);
258         if (SameRange && (f != First || l != Last)) {
259           return ;//BRepCheck_InvalidSameRangeFlag);
260           if (SameParameter) {
261             return; //BRepCheck_InvalidSameParameterFlag);
262           }
263         }
264         
265         Handle(Geom_Surface) Sb = cr->Surface();
266         Sb = Handle(Geom_Surface)::DownCast (Su->Transformed(L.Transformation()));
267         Handle(Geom2d_Curve) PC = cr->PCurve();
268         Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(Sb);
269         Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve(PC,f,l);
270         Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
271         ok = Validate(myHCurve->Curve(), ACS, Tol, SameParameter, aNewTol);
272         if (ok) {
273           if (cr->IsCurveOnClosedSurface()) {
274             //return ;// BRepCheck::Add(lst,BRepCheck_InvalidCurveOnClosedSurface);
275           }
276           else {
277             //return;//BRepCheck::Add(lst,BRepCheck_InvalidCurveOnSurface);
278           }
279           if (SameParameter) {
280             //return;//BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
281           }
282 //        printf("(Edge,1) Tolerance=%15.10lg\n", aNewTol);
283           if (aNewTol<aMaxTol)
284             TE->UpdateTolerance(aNewTol); 
285         }
286
287         if (cr->IsCurveOnClosedSurface()) {
288           //        checkclosed = Standard_True;
289           GHPC->ChangeCurve2d().Load(cr->PCurve2(),f,l); // same bounds
290           ACS.Load(GAHS); // sans doute inutile
291           ACS.Load(GHPC); // meme remarque...
292           ok = Validate(myHCurve->Curve(),ACS,Tol,SameParameter, aNewTol);
293           if (ok) {
294             //return;//BRepCheck::Add(lst,BRepCheck_InvalidCurveOnClosedSurface);
295             if (SameParameter) {
296               //return;//BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
297             }
298 //          printf("(Edge,2) Tolerance=%15.10lg\n", aNewTol);
299             if (aNewTol<aMaxTol)
300               TE->UpdateTolerance(aNewTol); 
301           }
302         }
303       }
304       itcr.Next();
305     }
306     
307     if (!pcurvefound) {
308       Handle(Geom_Plane) P;
309       Handle(Standard_Type) styp = Su->DynamicType();
310       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
311         P = Handle(Geom_Plane)::DownCast(Handle(Geom_RectangularTrimmedSurface)::
312                                          DownCast(Su)->BasisSurface());
313       }
314       else {
315         P = Handle(Geom_Plane)::DownCast(Su);
316       }
317       if (P.IsNull()) { // not a plane
318         return;//BRepCheck::Add(lst,BRepCheck_NoCurveOnSurface);
319       }
320       
321       else {// on fait la projection a la volee, comme BRep_Tool
322         P = Handle(Geom_Plane)::DownCast(P->Transformed(L.Transformation()));
323         //on projette Cref sur ce plan
324         Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(P);
325         
326         // Dub - Normalement myHCurve est une GeomAdaptor_HCurve
327         GeomAdaptor_Curve& Gac = Handle(GeomAdaptor_HCurve)::DownCast(myHCurve)->ChangeCurve();
328         Handle(Geom_Curve) C3d = Gac.Curve();
329         Handle(Geom_Curve) ProjOnPlane = GeomProjLib::ProjectOnPlane
330           (new Geom_TrimmedCurve(C3d,First,Last), P, P->Position().Direction(), Standard_True);
331
332         Handle(GeomAdaptor_HCurve) aHCurve = new GeomAdaptor_HCurve(ProjOnPlane);
333         
334         ProjLib_ProjectedCurve proj(GAHS,aHCurve);
335         Handle(Geom2d_Curve) PC = Geom2dAdaptor::MakeCurve(proj);
336         Handle(Geom2dAdaptor_HCurve) GHPC = 
337           new Geom2dAdaptor_HCurve(PC, myHCurve->FirstParameter(), myHCurve->LastParameter());
338         
339         Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
340         
341         ok = Validate(myHCurve->Curve(),ACS,
342                       Tol,Standard_True, aNewTol); // voir dub...
343         if (ok) {
344           //return;//BRepCheck::Add(lst,BRepCheck_InvalidCurveOnSurface);
345 //        printf("(Edge,3) Tolerance=%15.10lg\n", aNewTol);
346           if (aNewTol<aMaxTol)
347             TE->UpdateTolerance(aNewTol); 
348         }
349       }
350       
351     }//end of if (!pcurvefound) {
352   } // end of  2. Tolerances in InContext
353
354 }
355
356 #define NCONTROL 23
357 //=======================================================================
358 //function : Validate
359 //purpose  : 
360 //=======================================================================
361 Standard_Boolean Validate(const Adaptor3d_Curve& CRef,
362                        const Adaptor3d_Curve& Other,
363                        const Standard_Real Tol,
364                        const Standard_Boolean SameParameter,
365                        Standard_Real& aNewTolerance)
366 {
367   Standard_Real First, Last, MaxDistance, aD;
368
369   First = CRef.FirstParameter();
370   Last  = CRef.LastParameter();
371   MaxDistance = Tol*Tol;
372
373   Standard_Integer i, aNC1=NCONTROL-1;
374
375   Standard_Boolean aFlag=Standard_False;
376   Standard_Boolean proj = (!SameParameter || 
377                            First != Other.FirstParameter() ||
378                            Last  != Other.LastParameter());
379   //
380   // 1. 
381   if (!proj) {
382     for (i = 0; i < NCONTROL; i++) {
383       Standard_Real prm = ((aNC1-i)*First + i*Last)/aNC1;
384       gp_Pnt pref   = CRef.Value(prm);
385       gp_Pnt pother = Other.Value(prm);
386       
387       aD=pref.SquareDistance(pother);
388
389       if (aD > MaxDistance) {
390         MaxDistance=aD;
391         aFlag=Standard_True;
392       }
393     }
394   }
395   
396   //
397   // 2.
398   else {
399     Extrema_LocateExtPC refd,otherd;
400     Standard_Real OFirst, OLast;
401     OFirst = Other.FirstParameter();
402     OLast  = Other.LastParameter();
403     
404     gp_Pnt pd  = CRef.Value(First);
405     gp_Pnt pdo = Other.Value(OFirst);
406     
407     aD = pd.SquareDistance(pdo);
408     if (aD > MaxDistance) {
409       MaxDistance=aD;
410       aFlag=Standard_True;
411     }
412
413     pd  = CRef.Value(Last);
414     pdo = Other.Value(OLast);
415     aD = pd.SquareDistance(pdo);
416     if (aD > MaxDistance) {
417       MaxDistance=aD;
418       aFlag=Standard_True;
419     }
420
421     refd.Initialize(CRef, First, Last, CRef.Resolution(Tol));
422     otherd.Initialize(Other, OFirst, OLast, Other.Resolution(Tol));
423     
424     for (i = 2; i< aNC1; i++) {
425       Standard_Real rprm = ((aNC1-i)*First + i*Last)/aNC1;
426       gp_Pnt pref = CRef.Value(rprm);
427
428       Standard_Real oprm = ((aNC1-i)*OFirst + i*OLast)/aNC1;
429       gp_Pnt pother = Other.Value(oprm);
430
431       refd.Perform(pother,rprm);
432       if (!refd.IsDone() || refd.SquareDistance() > Tol * Tol) {
433         if (refd.IsDone()) {
434           aD=refd.SquareDistance();
435           if (aD > MaxDistance) {
436             aFlag=Standard_True;
437             MaxDistance=aD;
438           }
439         }
440       }
441
442       otherd.Perform(pref,oprm);
443       if (!otherd.IsDone() || otherd.SquareDistance() > Tol * Tol) {
444         
445         if (otherd.IsDone()) {
446           aD=otherd.SquareDistance();
447           if (aD > MaxDistance) {
448             aFlag=Standard_True;
449             MaxDistance=aD;
450           }
451         }
452       }
453     }
454   }
455
456   if (aFlag) {
457     aD=sqrt (MaxDistance);
458     aNewTolerance=aD*1.05;
459   }
460
461   return aFlag;
462   
463 }
464
465 //=======================================================================
466 // Function : CheckEdge
467 // purpose :  Correct tolerances for Vertices on Edge 
468 //=======================================================================
469 void CheckEdge (const TopoDS_Edge& Ed, const Standard_Real aMaxTol)
470 {
471   TopoDS_Edge E=Ed;
472   E.Orientation(TopAbs_FORWARD);
473
474   gp_Pnt Controlp;
475   
476   TopExp_Explorer aVExp;
477   aVExp.Init(E, TopAbs_VERTEX);
478   for (; aVExp.More(); aVExp.Next()) {
479     TopoDS_Vertex aVertex= TopoDS::Vertex(aVExp.Current());
480
481     Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &aVertex.TShape());
482     const gp_Pnt& prep = TV->Pnt();
483
484     Standard_Real Tol, aD2, aNewTolerance, dd;
485
486     Tol =BRep_Tool::Tolerance(aVertex);
487     Tol = Max(Tol, BRep_Tool::Tolerance(E));
488     dd=0.1*Tol;
489     Tol*=Tol;
490
491     const TopLoc_Location& Eloc = E.Location();
492     BRep_ListIteratorOfListOfPointRepresentation itpr;
493     
494     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
495     BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
496     while (itcr.More()) {
497       const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
498       const TopLoc_Location& loc = cr->Location();
499       TopLoc_Location L = (Eloc * loc).Predivided(aVertex.Location());
500       
501       if (cr->IsCurve3D()) {
502         const Handle(Geom_Curve)& C = cr->Curve3D();
503         if (!C.IsNull()) {
504           itpr.Initialize(TV->Points());
505           while (itpr.More()) {
506             const Handle(BRep_PointRepresentation)& pr = itpr.Value();
507             if (pr->IsPointOnCurve(C,L)) {
508               Controlp = C->Value(pr->Parameter());
509               Controlp.Transform(L.Transformation());
510               aD2=prep.SquareDistance(Controlp);
511               if (aD2 > Tol) {
512                 aNewTolerance=sqrt(aD2)+dd;
513 //              printf("(Vert,1) Tolerance=%15.10lg\n", aNewTolerance);
514                 if (aNewTolerance<aMaxTol)
515                   TV->UpdateTolerance(aNewTolerance);
516               }
517             }
518             itpr.Next();
519           }
520           
521           TopAbs_Orientation orv = aVertex.Orientation();
522           if (orv == TopAbs_FORWARD || orv == TopAbs_REVERSED) {
523             const Handle(BRep_GCurve)& GC = *((Handle(BRep_GCurve)*)&cr);
524             
525             if (orv==TopAbs_FORWARD)
526               Controlp = C->Value(GC->First());
527             else 
528               Controlp = C->Value(GC->Last());
529
530             Controlp.Transform(L.Transformation());
531             aD2=prep.SquareDistance(Controlp);
532             
533             if (aD2 > Tol) {
534               aNewTolerance=sqrt(aD2)+dd;
535 //            printf("(Vert,2) Tolerance=%15.10lg\n", aNewTolerance);
536               if (aNewTolerance<aMaxTol)
537                 TV->UpdateTolerance(aNewTolerance);
538             }
539           }
540         }
541       }
542       itcr.Next();
543     }
544   }
545 }
546
547 //=======================================================================
548 //function : CheckFaceClosed2d
549 //purpose  : 
550 //=======================================================================
551
552 Standard_Boolean TopOpeBRepBuild_Tools::CheckFaceClosed2d(const TopoDS_Face& theFace)
553 {
554   Standard_Boolean isClosed = Standard_True;
555   TopExp_Explorer ex(theFace,TopAbs_WIRE);
556   for (; ex.More() && isClosed; ex.Next()) {
557     const TopoDS_Wire& aW = TopoDS::Wire(ex.Current());
558     BRepCheck_Wire aWChk(aW);
559     BRepCheck_Status aStatus = aWChk.Orientation(theFace);
560     if (aStatus != BRepCheck_NoError)
561       isClosed = Standard_False;
562   }
563   return isClosed;
564 }