Adding of testing cases from subgroups 937 940 and 941 of CHL group
[occt.git] / src / BOP / BOP_CorrectTolerances.cxx
1 // Created on: 2001-04-17
2 // Created by: Peter KURNEV
3 // Copyright (c) 2001-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 <BOP_CorrectTolerances.ixx>
23
24 #include <TopTools_IndexedMapOfShape.hxx>
25 #include <TopExp.hxx>
26 #include <TopExp_Explorer.hxx>
27
28 #include <TopoDS.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Vertex.hxx>
31 #include <TopoDS_Face.hxx>
32
33 #include <TopLoc_Location.hxx>
34
35 #include <BRep_TVertex.hxx>
36 #include <BRep_TEdge.hxx>
37 #include <BRep_TFace.hxx>
38 #include <BRep_Tool.hxx>
39 #include <BRep_GCurve.hxx>
40 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
41 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
42 #include <BRep_CurveRepresentation.hxx>
43 #include <BRep_PointRepresentation.hxx>
44
45 #include <Geom_Curve.hxx>
46 #include <Geom_Surface.hxx>
47 #include <Geom_Plane.hxx>
48 #include <Geom_TrimmedCurve.hxx>
49
50 #include <GeomAdaptor_Curve.hxx>
51 #include <GeomAdaptor_HCurve.hxx>
52 #include <GeomAdaptor_HSurface.hxx>
53
54 #include <Geom2d_Curve.hxx>
55
56 #include <Geom2dAdaptor_HCurve.hxx>
57 #include <Geom_RectangularTrimmedSurface.hxx>
58 #include <Geom2dAdaptor.hxx>
59 #include <GeomProjLib.hxx>
60
61 #include <ProjLib_ProjectedCurve.hxx>
62 #include <Extrema_LocateExtPC.hxx>
63
64 #include <gp_Pnt.hxx>
65
66 #include <Adaptor3d_HCurve.hxx>
67 #include <Adaptor3d_CurveOnSurface.hxx>
68 #include <Adaptor3d_HCurveOnSurface.hxx>
69
70
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 static
88   void CorrectVertexTolerance(const TopoDS_Edge& aE);
89 //
90
91 //=======================================================================
92 // Function : CorrectTolerances
93 // purpose : 
94 //=======================================================================
95   void BOP_CorrectTolerances::CorrectTolerances(const TopoDS_Shape& aShape,
96                                                 const Standard_Real aMaxTol)
97 {
98   BOP_CorrectTolerances::CorrectPointOnCurve(aShape, aMaxTol);
99   BOP_CorrectTolerances::CorrectCurveOnSurface(aShape, aMaxTol);
100 }
101
102 //=======================================================================
103 // Function : CorrectPointOnCurve
104 // purpose : 
105 //=======================================================================
106   void BOP_CorrectTolerances::CorrectPointOnCurve(const TopoDS_Shape& S,
107                                                   const Standard_Real aMaxTol)
108 {
109   Standard_Integer i, aNb;
110   TopTools_IndexedMapOfShape Edges;
111   TopExp::MapShapes (S, TopAbs_EDGE, Edges);
112   aNb=Edges.Extent();
113   for (i=1; i<=aNb; i++) {
114     const TopoDS_Edge& E= TopoDS::Edge(Edges(i));
115     CheckEdge(E, aMaxTol);
116   }     
117 }
118
119 //=======================================================================
120 // Function : CorrectCurveOnSurface
121 // purpose : 
122 //=======================================================================
123   void BOP_CorrectTolerances::CorrectCurveOnSurface(const TopoDS_Shape& S,
124                                                     const Standard_Real aMaxTol)
125 {
126   Standard_Integer i, aNbFaces, j, aNbEdges;
127   TopTools_IndexedMapOfShape Faces;
128   TopExp::MapShapes (S, TopAbs_FACE, Faces);
129   
130   aNbFaces=Faces.Extent();
131   for (i=1; i<=aNbFaces; i++) {
132     const TopoDS_Face& F= TopoDS::Face(Faces(i));
133     TopTools_IndexedMapOfShape Edges;
134     TopExp::MapShapes (F, TopAbs_EDGE, Edges);
135     aNbEdges=Edges.Extent();
136     for (j=1; j<=aNbEdges; j++) {
137       const TopoDS_Edge& E= TopoDS::Edge(Edges(j));
138       CorrectEdgeTolerance (E, F, aMaxTol);
139     }
140   }
141 }
142
143 //=======================================================================
144 // Function : CorrectEdgeTolerance
145 // purpose :  Correct tolerances for Edge 
146 //=======================================================================
147 void CorrectEdgeTolerance (const TopoDS_Edge& myShape, 
148                            const TopoDS_Face& S,
149                            const Standard_Real aMaxTol)
150 {
151   // 
152   // 1. Minimum of conditions to Perform
153   Handle (BRep_CurveRepresentation) myCref;
154   Handle (Adaptor3d_HCurve) myHCurve;
155
156   myCref.Nullify();
157
158   Handle(BRep_TEdge)& TEx = *((Handle(BRep_TEdge)*)&myShape.TShape());
159   BRep_ListIteratorOfListOfCurveRepresentation itcrx(TEx->Curves());
160   Standard_Boolean Degenerated, SameParameterx, SameRangex;
161
162   Standard_Integer unique = 0;
163
164   Degenerated    = TEx->Degenerated();
165   SameParameterx = TEx->SameParameter();
166   SameRangex     = TEx->SameRange();
167   
168   if (!SameRangex && SameParameterx) {
169     return;
170   }
171
172   Handle(Geom_Curve) C3d;
173   while (itcrx.More()) {
174     const Handle(BRep_CurveRepresentation)& cr = itcrx.Value();
175     if (cr->IsCurve3D()) {
176       unique++;
177       if (myCref.IsNull() && !cr->Curve3D().IsNull()) {
178         myCref = cr;
179       }
180     }
181     itcrx.Next();
182   }
183   
184   if (unique==0) {
185     return;//...No3DCurve
186   }
187   if (unique>1) {
188     return;//...Multiple3DCurve;
189   }
190
191   if (myCref.IsNull() && !Degenerated) {
192     itcrx.Initialize(TEx->Curves());
193     while (itcrx.More()) {
194       const Handle(BRep_CurveRepresentation)& cr = itcrx.Value();
195       if (cr->IsCurveOnSurface()) {
196         myCref = cr;
197         break;
198       }
199       itcrx.Next();
200     }
201   }
202   
203   else if (!myCref.IsNull() && Degenerated){
204     return ;//...InvalidDegeneratedFlag;
205   }
206   
207   if (!myCref.IsNull()) {
208     const Handle(BRep_GCurve)& GCref = *((Handle(BRep_GCurve)*)&myCref);
209     Standard_Real First,Last;
210     GCref->Range(First,Last);
211     if (Last<=First) {
212       myCref.Nullify();
213       return ;//InvalidRange;
214     }
215     
216     else {
217       if (myCref->IsCurve3D()) {
218         Handle(Geom_Curve) C3dx = Handle(Geom_Curve)::DownCast
219           (myCref->Curve3D()->Transformed (myCref->Location().Transformation()));
220         GeomAdaptor_Curve GAC3d(C3dx, First, Last);
221         myHCurve = new GeomAdaptor_HCurve(GAC3d);
222       }
223       else { // curve on surface
224         Handle(Geom_Surface) Sref = myCref->Surface();
225         Sref = Handle(Geom_Surface)::DownCast(Sref->Transformed(myCref->Location().Transformation()));
226         const  Handle(Geom2d_Curve)& PCref = myCref->PCurve();
227         Handle(GeomAdaptor_HSurface) GAHSref = new GeomAdaptor_HSurface(Sref);
228         Handle(Geom2dAdaptor_HCurve) GHPCref = new Geom2dAdaptor_HCurve(PCref, First, Last);
229         Adaptor3d_CurveOnSurface ACSref(GHPCref,GAHSref);
230         myHCurve = new Adaptor3d_HCurveOnSurface(ACSref);
231       }
232     }
233   }
234
235   //=============================================== 
236   // 2. Tolerances in InContext
237   {
238     if (myCref.IsNull()) 
239       return;
240     Standard_Boolean ok=Standard_True;;
241
242     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&myShape.TShape());
243     Standard_Real Tol = BRep_Tool::Tolerance(TopoDS::Edge(myShape));
244     Standard_Real aNewTol=Tol;
245
246     Standard_Boolean SameParameter = TE->SameParameter();
247     Standard_Boolean SameRange = TE->SameRange();
248     Standard_Real First = myHCurve->FirstParameter();
249     Standard_Real Last  = myHCurve->LastParameter();
250     Standard_Real Delta =1.e-14;
251
252     Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &S.TShape());
253     const TopLoc_Location& Floc = S.Location();
254     const TopLoc_Location& TFloc = TF->Location();
255     const Handle(Geom_Surface)& Su = TF->Surface();
256     TopLoc_Location L = (Floc * TFloc).Predivided(myShape.Location());
257     //      Standard_Boolean checkclosed = Standard_False;
258     Standard_Boolean pcurvefound = Standard_False;
259
260     BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
261     while (itcr.More()) {
262       const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
263       if (cr != myCref && cr->IsCurveOnSurface(Su,L)) {
264         pcurvefound = Standard_True;
265         const Handle(BRep_GCurve)& GC = *((Handle(BRep_GCurve)*)&cr);
266         Standard_Real f,l;
267         GC->Range(f,l);
268         if (SameRange && (f != First || l != Last)) {
269           return ;//BRepCheck_InvalidSameRangeFlag);
270           if (SameParameter) {
271             return; //BRepCheck_InvalidSameParameterFlag);
272           }
273         }
274         
275         Handle(Geom_Surface) Sb = cr->Surface();
276         Sb = Handle(Geom_Surface)::DownCast (Su->Transformed(L.Transformation()));
277         Handle(Geom2d_Curve) PC = cr->PCurve();
278         Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(Sb);
279         Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve(PC,f,l);
280         Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
281         ok = Validate(myHCurve->Curve(), ACS, Tol, SameParameter, aNewTol);
282         if (ok) {
283           if (cr->IsCurveOnClosedSurface()) {
284             //return ;// BRepCheck::Add(lst,BRepCheck_InvalidCurveOnClosedSurface);
285           }
286           else {
287             //return;//BRepCheck::Add(lst,BRepCheck_InvalidCurveOnSurface);
288           }
289           if (SameParameter) {
290             //return;//BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
291           }
292           //
293           if (aNewTol<aMaxTol) {
294             TE->UpdateTolerance(aNewTol+Delta); 
295             //
296             CorrectVertexTolerance(myShape);
297           }
298         }
299
300         if (cr->IsCurveOnClosedSurface()) {
301           //        checkclosed = Standard_True;
302           GHPC->ChangeCurve2d().Load(cr->PCurve2(),f,l); // same bounds
303           ACS.Load(GAHS); // sans doute inutile
304           ACS.Load(GHPC); // meme remarque...
305           ok = Validate(myHCurve->Curve(),ACS,Tol,SameParameter, aNewTol);
306           if (ok) {
307             //return;//BRepCheck::Add(lst,BRepCheck_InvalidCurveOnClosedSurface);
308             if (SameParameter) {
309               //return;//BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
310             }
311             if (aNewTol<aMaxTol) {
312               TE->UpdateTolerance(aNewTol+Delta);
313               CorrectVertexTolerance(myShape);
314             } 
315           }
316         }
317       }
318       itcr.Next();
319     }
320     
321     if (!pcurvefound) {
322       Handle(Geom_Plane) P;
323       Handle(Standard_Type) styp = Su->DynamicType();
324       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
325         P = Handle(Geom_Plane)::DownCast(Handle(Geom_RectangularTrimmedSurface)::
326                                          DownCast(Su)->BasisSurface());
327       }
328       else {
329         P = Handle(Geom_Plane)::DownCast(Su);
330       }
331       if (P.IsNull()) { // not a plane
332         return;//BRepCheck::Add(lst,BRepCheck_NoCurveOnSurface);
333       }
334       
335       else {// on fait la projection a la volee, comme BRep_Tool
336         P = Handle(Geom_Plane)::DownCast(P->Transformed(L.Transformation()));
337         //on projette Cref sur ce plan
338         Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(P);
339         
340         // Dub - Normalement myHCurve est une GeomAdaptor_HCurve
341         GeomAdaptor_Curve& Gac = Handle(GeomAdaptor_HCurve)::DownCast(myHCurve)->ChangeCurve();
342         Handle(Geom_Curve) C3dx = Gac.Curve();
343         Handle(Geom_Curve) ProjOnPlane = GeomProjLib::ProjectOnPlane
344           (new Geom_TrimmedCurve(C3dx,First,Last), P, P->Position().Direction(), Standard_True);
345
346         Handle(GeomAdaptor_HCurve) aHCurve = new GeomAdaptor_HCurve(ProjOnPlane);
347         
348         ProjLib_ProjectedCurve proj(GAHS,aHCurve);
349         Handle(Geom2d_Curve) PC = Geom2dAdaptor::MakeCurve(proj);
350         Handle(Geom2dAdaptor_HCurve) GHPC = 
351           new Geom2dAdaptor_HCurve(PC, myHCurve->FirstParameter(), myHCurve->LastParameter());
352         
353         Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
354         
355         Standard_Boolean okx = Validate(myHCurve->Curve(),ACS,
356                                         Tol,Standard_True, aNewTol); // voir dub...
357         if (okx) {
358           //return;//BRepCheck::Add(lst,BRepCheck_InvalidCurveOnSurface);
359           if (aNewTol<aMaxTol) {
360             TE->UpdateTolerance(aNewTol+Delta);
361             CorrectVertexTolerance(myShape);
362           }
363         }
364       }
365       
366     }//end of if (!pcurvefound) {
367   } // end of  2. Tolerances in InContext
368
369 }
370
371 //=======================================================================
372 //function : CorrectVertexTolerance
373 //purpose  : 
374 //=======================================================================
375 void CorrectVertexTolerance(const TopoDS_Edge& aE)
376 {
377   Standard_Integer k, aNbV;
378   Standard_Real aTolE, aTolV;
379   TopTools_IndexedMapOfShape aVMap;
380   
381   aTolE=BRep_Tool::Tolerance(aE);
382   
383   TopExp::MapShapes(aE, TopAbs_VERTEX, aVMap);
384   aNbV=aVMap.Extent();
385   for (k=1; k<=aNbV; ++k) {
386     const TopoDS_Vertex& aV=TopoDS::Vertex(aVMap(k));
387     aTolV=BRep_Tool::Tolerance(aV);
388     if (aTolV<aTolE) {
389       Handle(BRep_TVertex)& aTV = *((Handle(BRep_TVertex)*)&aV.TShape());
390       aTV->UpdateTolerance(aTolE);
391     }
392   }
393 }
394
395                             
396
397 #define NCONTROL 23
398 //=======================================================================
399 //function : Validate
400 //purpose  : 
401 //=======================================================================
402 Standard_Boolean Validate(const Adaptor3d_Curve& CRef,
403                        const Adaptor3d_Curve& Other,
404                        const Standard_Real Tol,
405                        const Standard_Boolean SameParameter,
406                        Standard_Real& aNewTolerance)
407 {
408   Standard_Real First, Last, MaxDistance, aD, Tol2;
409
410   First = CRef.FirstParameter();
411   Last  = CRef.LastParameter();
412   MaxDistance = 0.;
413   Tol2 = Tol*Tol;
414
415   Standard_Integer i, aNC1=NCONTROL-1;
416
417   Standard_Boolean aFlag=Standard_False;
418   Standard_Boolean proj = (!SameParameter || 
419                            First != Other.FirstParameter() ||
420                            Last  != Other.LastParameter());
421   //
422   // 1. 
423   if (!proj) {
424     for (i = 0; i < NCONTROL; i++) {
425       Standard_Real prm = ((aNC1-i)*First + i*Last)/aNC1;
426       gp_Pnt pref   = CRef.Value(prm);
427       gp_Pnt pother = Other.Value(prm);
428       
429       aD=pref.SquareDistance(pother);
430
431       if (aD > Tol2) {
432         if (aD>MaxDistance) {
433           MaxDistance=aD;
434         }
435         aFlag=Standard_True;
436       }
437     }
438
439     if (aFlag) {
440       aNewTolerance=sqrt(MaxDistance);
441     }
442     return aFlag;
443   }
444   
445   //
446   // 2.
447   else {
448     Extrema_LocateExtPC refd,otherd;
449     Standard_Real OFirst, OLast;
450     OFirst = Other.FirstParameter();
451     OLast  = Other.LastParameter();
452     
453     gp_Pnt pd  = CRef.Value(First);
454     gp_Pnt pdo = Other.Value(OFirst);
455     
456     aD = pd.SquareDistance(pdo);
457     if (aD > Tol2) {
458       if (aD>MaxDistance) {
459         MaxDistance=aD;
460       }
461       aFlag=Standard_True;
462     }
463
464     pd  = CRef.Value(Last);
465     pdo = Other.Value(OLast);
466     aD = pd.SquareDistance(pdo);
467     if (aD > Tol2 && aD > MaxDistance) {
468       MaxDistance=aD;
469       aFlag=Standard_True;
470     }
471
472     refd.Initialize(CRef, First, Last, CRef.Resolution(Tol));
473     otherd.Initialize(Other, OFirst, OLast, Other.Resolution(Tol));
474     
475     for (i = 2; i< aNC1; i++) {
476       Standard_Real rprm = ((aNC1-i)*First + i*Last)/aNC1;
477       gp_Pnt pref = CRef.Value(rprm);
478
479       Standard_Real oprm = ((aNC1-i)*OFirst + i*OLast)/aNC1;
480       gp_Pnt pother = Other.Value(oprm);
481
482       refd.Perform(pother,rprm);
483       if (!refd.IsDone() || refd.SquareDistance() > Tol2) {
484         if (refd.IsDone()) {
485           aD=refd.SquareDistance();
486           if (aD > Tol2 && aD>MaxDistance) {
487             aFlag=Standard_True;
488             MaxDistance=aD;
489           }
490         }
491       }
492
493       otherd.Perform(pref,oprm);
494       if (!otherd.IsDone() || otherd.SquareDistance() > Tol2) {
495         
496         if (otherd.IsDone()) {
497           aD=otherd.SquareDistance();
498           if (aD > Tol2 && aD>MaxDistance) {
499             aFlag=Standard_True;
500             MaxDistance=aD;
501           }
502         }
503       }
504     }
505   }
506   
507   aD=sqrt (MaxDistance);
508   aNewTolerance=aD;
509
510   return aFlag;
511   
512 }
513
514 //=======================================================================
515 // Function : CheckEdge
516 // purpose :  Correct tolerances for Vertices on Edge 
517 //=======================================================================
518 void CheckEdge (const TopoDS_Edge& Ed, const Standard_Real aMaxTol)
519 {
520   TopoDS_Edge E=Ed;
521   E.Orientation(TopAbs_FORWARD);
522
523   gp_Pnt Controlp;
524   
525   TopExp_Explorer aVExp;
526   aVExp.Init(E, TopAbs_VERTEX);
527   for (; aVExp.More(); aVExp.Next()) {
528     TopoDS_Vertex aVertex= TopoDS::Vertex(aVExp.Current());
529
530     Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &aVertex.TShape());
531     const gp_Pnt& prep = TV->Pnt();
532
533     Standard_Real Tol, aD2, aNewTolerance, dd;
534
535     Tol =BRep_Tool::Tolerance(aVertex);
536     Tol = Max(Tol, BRep_Tool::Tolerance(E));
537     dd=0.1*Tol;
538     Tol*=Tol;
539
540     const TopLoc_Location& Eloc = E.Location();
541     BRep_ListIteratorOfListOfPointRepresentation itpr;
542     
543     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
544     BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
545     while (itcr.More()) {
546       const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
547       const TopLoc_Location& loc = cr->Location();
548       TopLoc_Location L = (Eloc * loc).Predivided(aVertex.Location());
549       
550       if (cr->IsCurve3D()) {
551         const Handle(Geom_Curve)& C = cr->Curve3D();
552         if (!C.IsNull()) {
553           itpr.Initialize(TV->Points());
554           while (itpr.More()) {
555             const Handle(BRep_PointRepresentation)& pr = itpr.Value();
556             if (pr->IsPointOnCurve(C,L)) {
557               Controlp = C->Value(pr->Parameter());
558               Controlp.Transform(L.Transformation());
559               aD2=prep.SquareDistance(Controlp);
560               if (aD2 > Tol) {
561                 aNewTolerance=sqrt(aD2)+dd;
562                 if (aNewTolerance<aMaxTol)
563                   TV->UpdateTolerance(aNewTolerance);
564               }
565             }
566             itpr.Next();
567           }
568           
569           TopAbs_Orientation orv = aVertex.Orientation();
570           if (orv == TopAbs_FORWARD || orv == TopAbs_REVERSED) {
571             const Handle(BRep_GCurve)& GC = *((Handle(BRep_GCurve)*)&cr);
572             
573             if (orv==TopAbs_FORWARD)
574               Controlp = C->Value(GC->First());
575             else 
576               Controlp = C->Value(GC->Last());
577
578             Controlp.Transform(L.Transformation());
579             aD2=prep.SquareDistance(Controlp);
580             
581             if (aD2 > Tol) {
582               aNewTolerance=sqrt(aD2)+dd;
583               if (aNewTolerance<aMaxTol)
584                 TV->UpdateTolerance(aNewTolerance);
585             }
586           }
587         }
588       }
589       itcr.Next();
590     }
591   }
592 }
593