0024002: Overall code and build procedure refactoring -- automatic
[occt.git] / src / BRepBuilderAPI / BRepBuilderAPI_FindPlane.cxx
1 // Created on: 1995-11-02
2 // Created by: Jing Cheng MEI
3 // Copyright (c) 1995-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
18 #include <BRep_Tool.hxx>
19 #include <BRepBuilderAPI_FindPlane.hxx>
20 #include <Geom_BezierCurve.hxx>
21 #include <Geom_BSplineCurve.hxx>
22 #include <Geom_Circle.hxx>
23 #include <Geom_Conic.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom_Ellipse.hxx>
26 #include <Geom_Hyperbola.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom_Parabola.hxx>
29 #include <Geom_Plane.hxx>
30 #include <gp_Dir.hxx>
31 #include <gp_Pln.hxx>
32 #include <gp_Vec.hxx>
33 #include <Precision.hxx>
34 #include <Standard_NoSuchObject.hxx>
35 #include <TColgp_SequenceOfPnt.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopLoc_Location.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Shape.hxx>
40
41 //=======================================================================
42 //function : BRepBuilderAPI_FindPlane
43 //purpose  : 
44 //=======================================================================
45 BRepBuilderAPI_FindPlane::BRepBuilderAPI_FindPlane() 
46 {
47 }
48
49 //=======================================================================
50 //function : BRepBuilderAPI_FindPlane
51 //purpose  : 
52 //=======================================================================
53
54 BRepBuilderAPI_FindPlane::BRepBuilderAPI_FindPlane(const TopoDS_Shape&    S, 
55                                      const Standard_Real    Tol)
56 {
57   Init(S,Tol);
58 }
59
60 //=======================================================================
61 //function : Init
62 //purpose  : 
63 //=======================================================================
64
65 void BRepBuilderAPI_FindPlane::Init(const TopoDS_Shape&    S, 
66                              const Standard_Real    Tol)
67 {
68   Standard_Real tolerance = Tol;
69   myPlane.Nullify();
70
71   // compute the tolerance
72   TopExp_Explorer ex;
73   for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) {
74     Standard_Real t = BRep_Tool::Tolerance(TopoDS::Edge(ex.Current()));
75     if (t > tolerance) tolerance = t;
76   }
77   
78   Standard_Real tol2 = tolerance*tolerance;
79   // try to find an analytical curve and calculate points
80   TopLoc_Location loc;
81   Standard_Real first, last;
82   Standard_Boolean found = Standard_False;  
83   Handle(Geom_Plane) P;
84   TColgp_SequenceOfPnt points;
85   Standard_Integer nbPnts;
86
87   for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) {
88     Handle(Geom_Curve) c3d = 
89       BRep_Tool::Curve(TopoDS::Edge(ex.Current()), loc, first, last);
90
91     if (!c3d.IsNull()) {
92       Handle(Geom_Curve) c3dptr = 
93         Handle(Geom_Curve)::DownCast(c3d->Transformed(loc.Transformation()));
94
95       Handle(Standard_Type) cType = c3dptr->DynamicType();
96       
97       if (cType == STANDARD_TYPE(Geom_Line)) {
98         nbPnts = 3;
99       }
100       else if ((cType == STANDARD_TYPE(Geom_Circle)) ||
101                (cType == STANDARD_TYPE(Geom_Ellipse)) ||
102                (cType == STANDARD_TYPE(Geom_Parabola)) ||
103                (cType == STANDARD_TYPE(Geom_Hyperbola))) {
104         nbPnts = 4; 
105         if (!found) {
106           found = Standard_True;
107           Handle(Geom_Conic) Co = Handle(Geom_Conic)::DownCast(c3dptr);
108           P = new Geom_Plane(gp_Ax3(Co->Position()));
109         }
110       }
111       else if (cType == STANDARD_TYPE(Geom_BezierCurve)) {
112         Handle(Geom_BezierCurve) Co = 
113           Handle(Geom_BezierCurve)::DownCast(c3dptr);
114         nbPnts = Co->NbPoles();
115       }
116       else if (cType == STANDARD_TYPE(Geom_BSplineCurve)) {
117         Handle(Geom_BSplineCurve) Co = 
118           Handle(Geom_BSplineCurve)::DownCast(c3dptr);
119         nbPnts = Co->NbPoles();
120       }
121       else {
122         nbPnts = 10;
123       }
124       
125       gp_Pnt p0;
126       for (Standard_Integer i=1; i<=nbPnts; i++) {
127         if (i == 1) {
128           c3dptr->D0(first, p0);
129         }
130         else if (i == nbPnts) {
131           c3dptr->D0(last, p0);
132         }
133         else {
134           c3dptr->D0(first+(last-first)/(nbPnts-1)*(i-1), p0);
135         }
136         points.Append(p0);
137       }
138     }
139   }
140
141   if (!found) {
142     // try to find a plane with the points
143     if (points.Length() > 2) {    
144
145       Standard_Real disMax = 0.0;
146       gp_Pnt p0 = points(1);
147       gp_Pnt p1;
148       for (Standard_Integer i=2; i<=points.Length(); i++) {
149         Standard_Real dist = p0.SquareDistance(points(i));
150         if (dist > disMax) {
151           disMax = dist;
152           p1 = points(i); // it will be faster to store the point, otherwise it is necessary to find a value in a sequence
153         }
154       }
155
156       if (disMax > tol2) {
157         gp_Vec V1(p0, p1), V3;
158         Standard_Real proMax = 0.0;
159         gp_Pnt p2 = p0 ;
160         for (Standard_Integer j=2; j<=points.Length(); j++) {
161           V3 = V1^gp_Vec(p0, points(j));
162           Standard_Real pro = V3.SquareMagnitude();
163           if (pro > proMax) {
164             proMax = pro;
165             p2 = points(j);
166           }
167         }
168         
169         if (p0.SquareDistance(p2) > tol2) {
170           gp_Dir D1(V1), D2(gp_Vec(p0, p2));
171           if (!D1.IsParallel(D2, Precision::Angular())) {
172             P = new Geom_Plane(gp_Ax3(p0, D1.Crossed(D2), D1));
173             found = Standard_True;
174           }
175         }
176       }
177     }
178   }
179   
180   if (found) {
181     // test if all points are on the plane
182     const gp_Pln& pln = P->Pln();
183     for (Standard_Integer i=1; i<=points.Length(); i++) {
184       if (pln.SquareDistance(points(i)) > tol2) {
185         found = Standard_False;
186         break;
187       }
188     } 
189   }
190   
191   if (found) {
192     myPlane = P;
193   }
194 }
195
196 //=======================================================================
197 //function : Found
198 //purpose  : 
199 //=======================================================================
200
201 Standard_Boolean BRepBuilderAPI_FindPlane::Found() const 
202 {
203   return !myPlane.IsNull();
204 }
205
206 //=======================================================================
207 //function : Plane
208 //purpose  : 
209 //=======================================================================
210
211 Handle(Geom_Plane) BRepBuilderAPI_FindPlane::Plane() const 
212 {
213   return myPlane;
214 }
215