0027135: Incorrect result of the normal projection algorithm
[occt.git] / src / ProjLib / ProjLib_ProjectOnSurface.cxx
CommitLineData
b311480e 1// Created on: 1994-09-15
2// Created by: Bruno DUMORTIER
3// Copyright (c) 1994-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17
42cf5bc1 18#include <Adaptor3d_HCurve.hxx>
19#include <Adaptor3d_HSurface.hxx>
7fd59977 20#include <AppCont_Function.hxx>
7fd59977 21#include <AppParCurves_MultiCurve.hxx>
42cf5bc1 22#include <Approx_FitAndDivide.hxx>
7fd59977 23#include <BSplCLib.hxx>
42cf5bc1 24#include <Extrema_ExtPS.hxx>
25#include <Extrema_POnSurf.hxx>
7fd59977 26#include <Geom_BSplineCurve.hxx>
42cf5bc1 27#include <PLib.hxx>
28#include <Precision.hxx>
29#include <ProjLib_ProjectOnSurface.hxx>
30#include <Standard_NoSuchObject.hxx>
7fd59977 31#include <TColgp_Array1OfPnt.hxx>
7fd59977 32#include <TColStd_Array1OfInteger.hxx>
42cf5bc1 33#include <TColStd_Array1OfReal.hxx>
7fd59977 34
35//=======================================================================
36//function : OnSurface_Value
37//purpose : Evaluate current point of the projected curve
38//=======================================================================
7fd59977 39static gp_Pnt OnSurface_Value(const Standard_Real U,
40 const Handle(Adaptor3d_HCurve)& myCurve,
41 Extrema_ExtPS * myExtPS)
42{
43 // on essaie de rendre le point solution le plus proche.
44 myExtPS->Perform(myCurve->Value(U));
45
46 Standard_Real Dist2Min = RealLast();
47 Standard_Integer Index = 0;
48
49 for ( Standard_Integer i = 1; i <= myExtPS->NbExt(); i++) {
50 if ( myExtPS->SquareDistance(i) < Dist2Min) {
51 Index = i;
52 Dist2Min = myExtPS->SquareDistance(Index);
53 }
54 }
55 if ( Index == 0 ) {
56 cout << " Extrema non trouve pour U = " << U << endl;
57 return gp_Pnt(0.,0.,0.);
58 }
59 else {
60 return (myExtPS->Point(Index)).Value();
61 }
62}
63
64//=======================================================================
65//function : OnSurface_D1
66//purpose :
67//=======================================================================
68
69static Standard_Boolean OnSurface_D1(const Standard_Real , // U,
70 gp_Pnt& , // P,
71 gp_Vec& , // V,
72 const Handle(Adaptor3d_HCurve)& , // myCurve,
73 Extrema_ExtPS *) // myExtPS)
74{
75 return Standard_False;
76}
77
78
79//=======================================================================
80// class : ProjLib_OnSurface
81//purpose : Use to approximate the projection on a plane
82//=======================================================================
83
84class ProjLib_OnSurface : public AppCont_Function
85
86{
6a38ff48 87public:
7fd59977 88
89 ProjLib_OnSurface(const Handle(Adaptor3d_HCurve) & C,
368cdde6 90 const Handle(Adaptor3d_HSurface) & S)
91 : myCurve(C)
92 {
93 myNbPnt = 1;
94 myNbPnt2d = 0;
95 Standard_Real U = myCurve->FirstParameter();
96 gp_Pnt P = myCurve->Value(U);
97 Standard_Real Tol = Precision::PConfusion();
98 myExtPS = new Extrema_ExtPS(P,S->Surface(),Tol,Tol);
99 }
7fd59977 100
101 ~ProjLib_OnSurface() { delete myExtPS; }
102
103 Standard_Real FirstParameter() const
104 {return myCurve->FirstParameter();}
368cdde6 105
7fd59977 106 Standard_Real LastParameter() const
107 {return myCurve->LastParameter();}
108
368cdde6 109 Standard_Boolean Value(const Standard_Real theT,
110 NCollection_Array1<gp_Pnt2d>& /*thePnt2d*/,
111 NCollection_Array1<gp_Pnt>& thePnt) const
112 {
113 thePnt(1) = OnSurface_Value(theT, myCurve, myExtPS);
114 return Standard_True;
115 }
7fd59977 116
368cdde6 117 Standard_Boolean D1(const Standard_Real theT,
118 NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
119 NCollection_Array1<gp_Vec>& theVec) const
120 {
121 gp_Pnt aPnt;
122 return OnSurface_D1(theT, aPnt, theVec(1), myCurve, myExtPS);
123 }
6a38ff48 124
125private:
126 ProjLib_OnSurface (const ProjLib_OnSurface&);
127 ProjLib_OnSurface& operator= (const ProjLib_OnSurface&);
128
129private:
130 Handle(Adaptor3d_HCurve) myCurve;
131 Extrema_ExtPS* myExtPS;
7fd59977 132};
7fd59977 133
134
135//=====================================================================//
136// //
137// D E S C R I P T I O N O F T H E C L A S S : //
138// //
139// P r o j L i b _ A p p r o x P r o j e c t O n P l a n e //
140// //
141//=====================================================================//
142
143
144//=======================================================================
145//function : ProjLib_ProjectOnSurface
146//purpose :
147//=======================================================================
148
149ProjLib_ProjectOnSurface::ProjLib_ProjectOnSurface() :
150myIsDone(Standard_False)
151{
152}
153
154//=======================================================================
155//function : ProjLib_ProjectOnSurface
156//purpose :
157//=======================================================================
158
159ProjLib_ProjectOnSurface::ProjLib_ProjectOnSurface
160(const Handle(Adaptor3d_HSurface)& S ) :
161myIsDone(Standard_False)
162{
163 mySurface = S;
164}
165
166void ProjLib_ProjectOnSurface::Load(const Handle(Adaptor3d_HCurve)& C,
167 const Standard_Real Tolerance)
168{
169 myTolerance = Tolerance ;
170 myCurve = C;
171 myIsDone = Standard_False ;
172 if (!mySurface.IsNull()) {
173
174 ProjLib_OnSurface F(myCurve, mySurface);
175
176 Standard_Integer Deg1, Deg2;
177 Deg1 = 8; Deg2 = 8;
178
179 Approx_FitAndDivide Fit(F,Deg1,Deg2,Precision::Approximation(),
180 Precision::PApproximation(),Standard_True);
181 Standard_Integer i;
182 Standard_Integer NbCurves = Fit.NbMultiCurves();
183 Standard_Integer MaxDeg = 0;
184
185 // Pour transformer la MultiCurve en BSpline, il faut que toutes
186 // les Bezier la constituant aient le meme degre -> Calcul de MaxDeg
187 Standard_Integer NbPoles = 1;
188 for (i = 1; i <= NbCurves; i++) {
189 Standard_Integer Deg = Fit.Value(i).Degree();
190 MaxDeg = Max ( MaxDeg, Deg);
191 }
192 NbPoles = MaxDeg * NbCurves + 1; //Poles sur la BSpline
193 TColgp_Array1OfPnt Poles( 1, NbPoles);
194
195 TColgp_Array1OfPnt TempPoles( 1, MaxDeg + 1); //pour augmentation du degre
196
197 TColStd_Array1OfReal Knots( 1, NbCurves + 1); //Noeuds de la BSpline
198
199 Standard_Integer Compt = 1;
200 for (i = 1; i <= Fit.NbMultiCurves(); i++) {
201 Fit.Parameters(i, Knots(i), Knots(i+1));
202
203 AppParCurves_MultiCurve MC = Fit.Value( i); //Charge la Ieme Curve
204 TColgp_Array1OfPnt LocalPoles( 1, MC.Degree() + 1);//Recupere les poles
205 MC.Curve(1, Poles);
206
207 //Augmentation eventuelle du degre
208 Standard_Integer Inc = MaxDeg - MC.Degree();
209 if ( Inc > 0) {
0e14656b 210 BSplCLib::IncreaseDegree( Inc, LocalPoles, BSplCLib::NoWeights(),
211 TempPoles, BSplCLib::NoWeights());
7fd59977 212 //mise a jour des poles de la PCurve
213 for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) {
214 Poles.SetValue( Compt, TempPoles( j));
215 Compt++;
216 }
217 }
218 else {
219 //mise a jour des poles de la PCurve
220 for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) {
221 Poles.SetValue( Compt, LocalPoles( j));
222 Compt++;
223 }
224 }
225
226 Compt--;
227 }
228
229 //mise a jour des fields de ProjLib_Approx
230
231 Standard_Integer NbKnots = NbCurves + 1;
232
233 TColStd_Array1OfInteger Mults( 1, NbKnots);
234 Mults.SetValue( 1, MaxDeg + 1);
235 for ( i = 2; i <= NbCurves; i++) {
236 Mults.SetValue( i, MaxDeg);
237 }
238 Mults.SetValue(NbKnots, MaxDeg + 1);
239 myResult =
240 new Geom_BSplineCurve(Poles,
241 Knots,
242 Mults,
243 MaxDeg,
244 Standard_False) ;
245 myIsDone = Standard_True ;
246 }
247}
248
e6f550da 249//=======================================================================
250//function : ~ProjLib_ProjectOnSurface
251//purpose :
252//=======================================================================
253
254ProjLib_ProjectOnSurface::~ProjLib_ProjectOnSurface()
7fd59977 255{}
256
257//=======================================================================
258//function : BSpline
259//purpose :
260//=======================================================================
261
262Handle(Geom_BSplineCurve) ProjLib_ProjectOnSurface::BSpline() const
263{
264 Standard_NoSuchObject_Raise_if
265 (!myIsDone,
266 "ProjLib_ProjectOnSurface:BSpline");
267 return myResult ;
268}
269
270//=======================================================================
271//function : IsDone
272//purpose :
273//=======================================================================
274
275Standard_Boolean ProjLib_ProjectOnSurface::IsDone() const
276{
277 return myIsDone;
278}