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