0031313: Foundation Classes - Dump improvement for classes
[occt.git] / src / GeomLib / GeomLib_CheckBSplineCurve.cxx
1 // Created on: 1997-05-28
2 // Created by: Xavier BENVENISTE
3 // Copyright (c) 1997-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 <Geom_BSplineCurve.hxx>
19 #include <GeomLib_CheckBSplineCurve.hxx>
20 #include <gp_Pnt.hxx>
21 #include <gp_Vec.hxx>
22 #include <Standard_OutOfRange.hxx>
23 #include <StdFail_NotDone.hxx>
24
25 //=======================================================================
26 //function : GeomLib_CheckBSplineCurve
27 //purpose  : 
28 //=======================================================================
29 GeomLib_CheckBSplineCurve::GeomLib_CheckBSplineCurve(const Handle(Geom_BSplineCurve)& Curve,
30                                                      const Standard_Real Tolerance,
31                                                      const Standard_Real AngularTolerance)
32  : myCurve(Curve),
33    myDone(Standard_False),
34    myFixFirstTangent(Standard_False),
35    myFixLastTangent(Standard_False),
36    myAngularTolerance(Abs(AngularTolerance)),
37    myTolerance(Abs(Tolerance)),
38    myIndSecondPole(-1),
39    myIndPrelastPole(-1)
40 {
41   Standard_Integer ii,
42     num_poles ;
43   Standard_Real tangent_magnitude,
44     value,
45     vector_magnitude ;
46   num_poles = myCurve->NbPoles() ;
47   
48   if (( ! myCurve->IsPeriodic() )&& num_poles >= 4) {
49     
50     gp_Vec tangent, tangent_normalized,
51       a_vector, avector_normalized;
52     
53     const Standard_Real CrossProdSqTol = myAngularTolerance*myAngularTolerance;
54     
55     //Near first
56     tangent = gp_Vec(myCurve->Pole(1), myCurve->Pole(2));
57     tangent_magnitude = tangent.Magnitude() ;
58     if (tangent_magnitude > myTolerance)
59       tangent_normalized = tangent/tangent_magnitude;
60     
61     for (ii = 3; ii <= num_poles; ii++)
62     {
63       a_vector = gp_Vec(myCurve->Pole(1), myCurve->Pole(ii));
64       vector_magnitude = a_vector.Magnitude() ;
65       
66       if (tangent_magnitude > myTolerance &&
67           vector_magnitude  > myTolerance)
68       {
69         avector_normalized = a_vector/vector_magnitude;
70
71         gp_Vec CrossProd = tangent_normalized ^ avector_normalized;
72         Standard_Real CrossProdSqLength = CrossProd.SquareMagnitude();
73         if (CrossProdSqLength > CrossProdSqTol)
74           break;
75         
76         value = tangent.Dot(a_vector) ;
77         if ( value < 0.0e0)
78         {
79           myFixFirstTangent = Standard_True ;
80           myIndSecondPole = ii;
81           break;
82         }
83       }
84     }
85
86     //Near last
87     tangent = gp_Vec(myCurve->Pole(num_poles), myCurve->Pole(num_poles-1));
88     tangent_magnitude = tangent.Magnitude() ;
89     if (tangent_magnitude > myTolerance)
90       tangent_normalized = tangent/tangent_magnitude;
91
92     for (ii = num_poles-2; ii >= 1; ii--)
93     {
94       a_vector = gp_Vec(myCurve->Pole(num_poles), myCurve->Pole(ii));
95       vector_magnitude = a_vector.Magnitude() ;
96       
97       if (tangent_magnitude > myTolerance &&
98           vector_magnitude  > myTolerance)
99       {
100         avector_normalized = a_vector/vector_magnitude;
101
102         gp_Vec CrossProd = tangent_normalized ^ avector_normalized;
103         Standard_Real CrossProdSqLength = CrossProd.SquareMagnitude();
104         if (CrossProdSqLength > CrossProdSqTol)
105           break;
106           
107         value = tangent.Dot(a_vector) ;
108         if (value < 0.0e0)
109         {
110           myFixLastTangent = Standard_True ;
111           myIndPrelastPole = ii;
112           break;
113         }
114       }
115     }
116   } //if (( ! myCurve->IsPeriodic() )&& num_poles >= 4)
117   else {
118     myDone = Standard_True ;
119   }
120 }
121   
122 //=======================================================================
123 //function : NeedTangentFix
124 //purpose  : 
125 //=======================================================================
126
127 void GeomLib_CheckBSplineCurve::NeedTangentFix(Standard_Boolean & FirstFlag,
128                                                Standard_Boolean & LastFlag) const 
129 {
130   FirstFlag = myFixFirstTangent ;
131   LastFlag  = myFixLastTangent ;
132 }
133
134 //=======================================================================
135 //function : FixedTangent
136 //purpose  : 
137 //=======================================================================
138
139 Handle(Geom_BSplineCurve)  GeomLib_CheckBSplineCurve::FixedTangent(const Standard_Boolean FirstFlag,
140                                                                    const Standard_Boolean LastFlag)
141
142   Handle(Geom_BSplineCurve) new_curve ;
143   if ((myFixFirstTangent && FirstFlag) ||(myFixLastTangent && LastFlag)) {
144     new_curve =
145       Handle(Geom_BSplineCurve)::DownCast(myCurve->Copy()) ;
146     
147     FixTangentOnCurve(new_curve, FirstFlag, LastFlag);
148   }
149   return new_curve ;
150 }
151
152 //=======================================================================
153 //function : FixTangent
154 //purpose  : 
155 //=======================================================================
156
157 void GeomLib_CheckBSplineCurve::FixTangent(const Standard_Boolean FirstFlag,
158                                            const Standard_Boolean LastFlag)
159 {
160   FixTangentOnCurve(myCurve, FirstFlag, LastFlag);
161 }
162
163 //=======================================================================
164 //function : FixTangentOnCurve
165 //purpose  : 
166 //=======================================================================
167
168 void GeomLib_CheckBSplineCurve::FixTangentOnCurve(Handle(Geom_BSplineCurve)& theCurve,
169                                                   const Standard_Boolean FirstFlag,
170                                                   const Standard_Boolean LastFlag)
171
172   if (myFixFirstTangent && FirstFlag) {
173     gp_XYZ XYZ1 = theCurve->Pole(1).XYZ();
174     gp_XYZ XYZ2 = theCurve->Pole(myIndSecondPole).XYZ();
175     Standard_Real NbSamples = myIndSecondPole - 1;
176     for (Standard_Integer i = 2; i < myIndSecondPole; i++)
177     {
178       Standard_Real ii = i-1;
179       gp_Pnt aNewPole((1. - ii/NbSamples)*XYZ1 + ii/NbSamples*XYZ2);
180       theCurve->SetPole(i, aNewPole);
181     }
182   }
183   
184   if (myFixLastTangent && LastFlag) {
185     Standard_Integer num_poles = theCurve->NbPoles() ;
186     
187     gp_XYZ XYZ1 = theCurve->Pole(num_poles).XYZ();
188     gp_XYZ XYZ2 = theCurve->Pole(myIndPrelastPole).XYZ();
189     Standard_Real NbSamples = num_poles - myIndPrelastPole;
190     for (Standard_Integer i = num_poles-1; i > myIndPrelastPole; i--)
191     {
192       Standard_Real ii = num_poles-i;
193       gp_Pnt aNewPole((1. - ii/NbSamples)*XYZ1 + ii/NbSamples*XYZ2);
194       theCurve->SetPole(i, aNewPole);
195     }
196   }
197   
198   myDone = Standard_True ;
199 }