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