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