0023024: Update headers of OCCT files
[occt.git] / src / gce / gce_MakeCirc.cxx
1 // Created on: 1992-09-02
2 // Created by: Remi GILET
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #include <gce_MakeCirc.ixx>
23
24 #include <StdFail_NotDone.hxx>
25
26 #include <gp.hxx>
27 #include <gp_Ax1.hxx>
28 #include <gp_Lin.hxx>
29
30 #include <gce_MakeDir.hxx>
31
32 #include <Extrema_POnCurv.hxx>
33 #include <Extrema_ExtElC.hxx>
34 //=======================================================================
35 //function : gce_MakeCirc
36 //purpose  : 
37 //   Creation d un cercle 3d de gp passant par trois points.              +
38 //   Trois cas de figures :                                               +
39 //      1/ Les trois points sont confondus.                               +
40 //      -----------------------------------                               +
41 //      Le resultat est le cercle centre en Point1 de rayon zero.         +
42 //      2/ Deux des trois points sont confondus.                          +
43 //      ----------------------------------------                          +
44 //      Pas de solution (Erreur : Points confondus).                      +
45 //      3/ Les trois points sont distinct.                                +
46 //      ----------------------------------                                +
47 //      On cree la mediatrice a P1P2 ainsi que la mediatrice a P1P3.      +
48 //      La solution a pour centre l intersection de ces deux droite et    +
49 //      pour rayon la distance entre ce centre et l un des trois points.  +
50 //=========================================================================
51 gce_MakeCirc::gce_MakeCirc(const gp_Pnt&  P1 ,
52                            const gp_Pnt&  P2 ,
53                            const gp_Pnt&  P3) {
54 //=========================================================================
55 //   Traitement.                                                          +
56 //=========================================================================
57   Standard_Real dist1, dist2, dist3, aResolution;
58   //
59   aResolution=gp::Resolution();
60   //
61   dist1 = P1.Distance(P2);
62   dist2 = P1.Distance(P3);
63   dist3 = P2.Distance(P3);
64   //
65   if ((dist1<aResolution) && (dist2<aResolution) && (dist3<aResolution)) {
66     gp_Dir Dirx(1.,0.,0.);
67     gp_Dir Dirz(0.,0.,1.);
68     TheCirc = gp_Circ(gp_Ax2(P1,Dirx,Dirz), 0.);
69     return;
70   }
71   if (!(dist1 >= aResolution && dist2 >= aResolution)) {
72     TheError = gce_ConfusedPoints;
73     return;
74   }
75   //
76   Standard_Real x1,y1,z1,x2,y2,z2,x3,y3,z3;
77   //
78   P1.Coord(x1,y1,z1);
79   P2.Coord(x2,y2,z2);
80   P3.Coord(x3,y3,z3);
81   gp_Dir Dir1(x2-x1,y2-y1,z2-z1);
82   gp_Dir Dir2(x3-x2,y3-y2,z3-z2);
83   //
84   gp_Ax1 anAx1(P1, Dir1);
85   gp_Lin aL12 (anAx1);
86   if (aL12.Distance(P3)<aResolution) {
87     TheError = gce_ColinearPoints;
88     return;
89   }
90   //
91   gp_Dir Dir3 = Dir1.Crossed(Dir2);
92   //
93   gp_Dir dir = Dir1.Crossed(Dir3);
94   gp_Lin L1(gp_Pnt((P1.XYZ()+P2.XYZ())/2.),dir);
95   dir = Dir2.Crossed(Dir3);
96   gp_Lin L2(gp_Pnt((P3.XYZ()+P2.XYZ())/2.),dir);
97
98   Standard_Real Tol = 0.000000001;
99   Extrema_ExtElC distmin(L1,L2,Tol);
100   
101   if (!distmin.IsDone()) { 
102     TheError = gce_IntersectionError; 
103   }
104   else {
105     Standard_Integer nbext;
106     //
107     //
108     if (distmin.IsParallel()) {
109       TheError = gce_IntersectionError;
110       return;
111     }
112     nbext = distmin.NbExt();
113     //
114     //
115     if (nbext == 0) {
116       TheError = gce_IntersectionError; 
117     }
118     else {
119       Standard_Real TheDist = RealLast();
120       gp_Pnt pInt,pon1,pon2;
121       Standard_Integer i = 1;
122       Extrema_POnCurv Pon1,Pon2;
123       while (i<=nbext) {
124         if (distmin.SquareDistance(i)<TheDist) {
125           TheDist = distmin.SquareDistance(i);
126           distmin.Points(i,Pon1,Pon2);
127           pon1 = Pon1.Value();
128           pon2 = Pon2.Value();
129           pInt = gp_Pnt((pon1.XYZ()+pon2.XYZ())/2.);
130         }
131         i++;
132       }
133       //modified by NIZNHY-PKV Thu Mar  3 11:30:34 2005f
134       //Dir2.Cross(Dir1);
135       //modified by NIZNHY-PKV Thu Mar  3 11:30:37 2005t
136       dist1 = P1.Distance(pInt);
137       dist2 = P2.Distance(pInt);
138       dist3 = P3.Distance(pInt);
139       pInt.Coord(x3,y3,z3);
140       Dir1 = gp_Dir(x1-x3,y1-y3,z1-z3);
141       //modified by NIZNHY-PKV Thu Mar  3 11:31:11 2005f
142       //Dir2 = gp_Dir(x2-x3,y2-y3,z2-z3);
143       //modified by NIZNHY-PKV Thu Mar  3 11:31:13 2005t
144       //
145       TheCirc = gp_Circ(gp_Ax2(pInt, Dir3, Dir1),(dist1+dist2+dist3)/3.);
146       TheError = gce_Done;
147     }
148   }
149 }
150 //=======================================================================
151 //function : gce_MakeCirc
152 //purpose  : 
153 //=======================================================================
154 gce_MakeCirc::gce_MakeCirc(const gp_Ax2&       A2      ,
155                            const Standard_Real Radius  ) {
156   if (Radius < 0.) { 
157     TheError = gce_NegativeRadius;
158   }
159   else {
160     TheError = gce_Done;
161     TheCirc = gp_Circ(A2,Radius);
162   }
163 }
164 //=========================================================================
165 //   Creation d un gp_Circ par son centre <Center>, son plan <Plane> et   +
166 //   son rayon <Radius>.                                                  +
167 //=========================================================================
168 gce_MakeCirc::gce_MakeCirc(const gp_Pnt&       Center  ,
169                            const gp_Pln&       Plane   ,
170                            const Standard_Real Radius  ) {
171   gce_MakeCirc C = gce_MakeCirc(Center,Plane.Position().Direction(),Radius);
172   TheCirc = C.Value();
173   TheError = C.Status();
174 }
175 //=======================================================================
176 //function : gce_MakeCirc
177 //purpose  : Creation d un gp_Circ par son centre <Center>, 
178 //sa normale <Norm> et son rayon <Radius>.  
179 //=======================================================================
180 gce_MakeCirc::gce_MakeCirc(const gp_Pnt&       Center  ,
181                            const gp_Dir&       Norm    ,
182                            const Standard_Real Radius  ) {
183    if (Radius < 0.) { 
184      TheError = gce_NegativeRadius;
185    }
186    else {
187      Standard_Real A = Norm.X();
188      Standard_Real B = Norm.Y();
189      Standard_Real C = Norm.Z();
190      Standard_Real Aabs = Abs(A);
191      Standard_Real Babs = Abs(B);
192      Standard_Real Cabs = Abs(C);
193      gp_Ax2 Pos;
194
195 //=========================================================================
196 //  pour determiner l'axe X :                                             +
197 //  on dit que le produit scalaire Vx.Norm = 0.                           +
198 //  et on recherche le max(A,B,C) pour faire la division.                 +
199 //  l'une des coordonnees du vecteur est nulle.                           +
200 //=========================================================================
201
202      if( Babs <= Aabs && Babs <= Cabs) {
203        if(Aabs > Cabs) { Pos = gp_Ax2(Center,Norm,gp_Dir(-C,0.,A)); }
204        else { Pos = gp_Ax2(Center,Norm,gp_Dir(C,0.,-A)); }
205      }
206      else if( Aabs <= Babs && Aabs <= Cabs) {
207        if(Babs > Cabs) { Pos = gp_Ax2(Center,Norm,gp_Dir(0.,-C,B)); }
208        else { Pos = gp_Ax2(Center,Norm,gp_Dir(0.,C,-B)); }
209      }
210      else {
211        if(Aabs > Babs) { Pos = gp_Ax2(Center,Norm,gp_Dir(-B,A,0.)); }
212        else { Pos = gp_Ax2(Center,Norm,gp_Dir(B,-A,0.)); }
213      }
214      TheCirc = gp_Circ(Pos,Radius);
215      TheError = gce_Done;
216    }
217  }
218 //=======================================================================
219 //function : gce_MakeCirc
220 //purpose  :  Creation d un gp_Circ par son centre <Center>, 
221 // sa normale <Ptaxis> et  son rayon <Radius>
222 //=======================================================================
223 gce_MakeCirc::gce_MakeCirc(const gp_Pnt&       Center  ,
224                            const gp_Pnt&       Ptaxis  ,
225                            const Standard_Real Radius  ) {
226    if (Radius < 0.) { 
227      TheError = gce_NegativeRadius;
228    }
229    else {
230      if (Center.Distance(Ptaxis) <= gp::Resolution()) {
231        TheError = gce_NullAxis;
232      }
233      else {
234        Standard_Real A = Ptaxis.X()-Center.X();
235        Standard_Real B = Ptaxis.Y()-Center.Y();
236        Standard_Real C = Ptaxis.Z()-Center.Z();
237        Standard_Real Aabs = Abs(A);
238        Standard_Real Babs = Abs(B);
239        Standard_Real Cabs = Abs(C);
240        gp_Ax2 Pos;
241
242 //=========================================================================
243 //  pour determiner l'axe X :                                             +
244 //  on dit que le produit scalaire Vx.Norm = 0.                           +
245 //  et on recherche le max(A,B,C) pour faire la division.                 +
246 //  l'une des coordonnees du vecteur est nulle.                           +
247 //=========================================================================
248
249        gp_Dir Norm = gce_MakeDir(Center,Ptaxis);
250        if( Babs <= Aabs && Babs <= Cabs) {
251          if(Aabs > Cabs) { Pos = gp_Ax2(Center,Norm,gp_Dir(-C,0.,A)); }
252          else { Pos = gp_Ax2(Center,Norm,gp_Dir(C,0.,-A)); }
253        }
254        else if( Aabs <= Babs && Aabs <= Cabs) {
255          if(Babs > Cabs) { Pos = gp_Ax2(Center,Norm,gp_Dir(0.,-C,B)); }
256          else { Pos = gp_Ax2(Center,Norm,gp_Dir(0.,C,-B)); }
257        }
258        else {
259          if(Aabs > Babs) { Pos = gp_Ax2(Center,Norm,gp_Dir(-B,A,0.)); }
260          else { Pos = gp_Ax2(Center,Norm,gp_Dir(B,-A,0.)); }
261        }
262        TheCirc = gp_Circ(Pos,Radius);
263        TheError = gce_Done;
264      }
265    }
266  }
267 //=======================================================================
268 //function : gce_MakeCirc
269 //purpose  : Creation d un gp_Circ par son axe <Axis> et son rayon <Radius>.  
270 //=======================================================================
271 gce_MakeCirc::gce_MakeCirc(const gp_Ax1&       Axis    ,
272                            const Standard_Real Radius  ) 
273 {
274   if (Radius < 0.) { 
275     TheError = gce_NegativeRadius;
276   }
277   else {
278     gp_Dir Norm(Axis.Direction());
279     gp_Pnt Center(Axis.Location());
280     Standard_Real A = Norm.X();
281     Standard_Real B = Norm.Y();
282     Standard_Real C = Norm.Z();
283     Standard_Real Aabs = Abs(A);
284     Standard_Real Babs = Abs(B);
285     Standard_Real Cabs = Abs(C);
286     gp_Ax2 Pos;
287
288 //=========================================================================
289 //  pour determiner l'axe X :                                             +
290 //  on dit que le produit scalaire Vx.Norm = 0.                           +
291 //  et on recherche le max(A,B,C) pour faire la division.                 +
292 //  l'une des coordonnees du vecteur est nulle.                           +
293 //=========================================================================
294
295     if( Babs <= Aabs && Babs <= Cabs) {
296       if(Aabs > Cabs) { Pos = gp_Ax2(Center,Norm,gp_Dir(-C,0.,A)); }
297       else { Pos = gp_Ax2(Center,Norm,gp_Dir(C,0.,-A)); }
298     }
299     else if( Aabs <= Babs && Aabs <= Cabs) {
300       if(Babs > Cabs) { Pos = gp_Ax2(Center,Norm,gp_Dir(0.,-C,B)); }
301       else { Pos = gp_Ax2(Center,Norm,gp_Dir(0.,C,-B)); }
302     }
303     else {
304       if(Aabs > Babs) { Pos = gp_Ax2(Center,Norm,gp_Dir(-B,A,0.)); }
305       else { Pos = gp_Ax2(Center,Norm,gp_Dir(B,-A,0.)); }
306     }
307     TheCirc = gp_Circ(Pos,Radius);
308     TheError = gce_Done;
309   }
310 }
311 //=======================================================================
312 //function : gce_MakeCirc
313 //purpose  : Creation d un gp_Circ concentrique a un autre gp_circ a une distance +
314 //   donnee.                
315 //=======================================================================
316 gce_MakeCirc::gce_MakeCirc(const gp_Circ&      Circ    ,
317                            const Standard_Real Dist    )
318 {
319   Standard_Real Rad = Circ.Radius()+Dist;
320   if (Rad < 0.) { 
321     TheError = gce_NegativeRadius;
322   }
323   else {
324     TheCirc = gp_Circ(Circ.Position(),Rad);
325     TheError = gce_Done;
326   }
327 }
328 //=======================================================================
329 //function : gce_MakeCirc
330 //purpose  : Creation d un gp_Circ concentrique a un autre gp_circ dont le rayon 
331 //   est egal a la distance de <Point> a l axe de <Circ>. 
332 //=======================================================================
333 gce_MakeCirc::gce_MakeCirc(const gp_Circ& Circ ,
334                            const gp_Pnt&  P    ) 
335 {
336   Standard_Real Rad = gp_Lin(Circ.Axis()).Distance(P);
337   TheCirc = gp_Circ(Circ.Position(),Rad);
338   TheError = gce_Done;
339 }
340 //=======================================================================
341 //function : Value
342 //purpose  : 
343 //=======================================================================
344 const gp_Circ& gce_MakeCirc::Value() const
345
346   StdFail_NotDone_Raise_if(!TheError == gce_Done,"");
347   return TheCirc;
348 }
349 //=======================================================================
350 //function : Operator
351 //purpose  : 
352 //=======================================================================
353 const gp_Circ& gce_MakeCirc::Operator() const 
354 {
355   return Value();
356 }
357 //=======================================================================
358 //function : operator
359 //purpose  : 
360 //=======================================================================
361 gce_MakeCirc::operator gp_Circ() const
362 {
363   return Value();
364 }
365