0023043: Wrong results of BRepExtrema_DistShapeShape: non-null minimum distance betwe...
[occt.git] / src / Extrema / Extrema_ExtCS.cxx
CommitLineData
b311480e 1// Created on: 1995-07-18
2// Created by: Modelistation
3// Copyright (c) 1995-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
7fd59977 21
22// Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134
23
24#include <Extrema_ExtCS.ixx>
25#include <Extrema_GenExtCS.hxx>
26#include <StdFail_NotDone.hxx>
27#include <Standard_NotImplemented.hxx>
28#include <StdFail_InfiniteSolutions.hxx>
29#include <Precision.hxx>
30#include <GeomAbs_CurveType.hxx>
31#include <gp_Pnt.hxx>
32#include <gp_Pln.hxx>
33#include <gp_Cylinder.hxx>
34#include <gp_Cone.hxx>
35#include <gp_Sphere.hxx>
36#include <gp_Torus.hxx>
37#include <gp_Lin.hxx>
38
39#include <ElCLib.hxx>
40#include <Extrema_ExtPElC.hxx>
41#include <Bnd_Box.hxx>
42#include <BndLib_AddSurface.hxx>
43#include <Extrema_ExtPElS.hxx>
44
45Extrema_ExtCS::Extrema_ExtCS()
46{
47 myDone = Standard_False;
48}
49
50Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
51 const Adaptor3d_Surface& S,
52 const Standard_Real TolC,
53 const Standard_Real TolS)
54
55{
56 Initialize(S, S.FirstUParameter(), S.LastUParameter(),
57 S.FirstVParameter(), S.LastVParameter(),
58 TolC, TolS);
59 Perform(C, C.FirstParameter(), C.LastParameter());
60}
61
62Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
63 const Adaptor3d_Surface& S,
64 const Standard_Real UCinf,
65 const Standard_Real UCsup,
66 const Standard_Real Uinf,
67 const Standard_Real Usup,
68 const Standard_Real Vinf,
69 const Standard_Real Vsup,
70 const Standard_Real TolC,
71 const Standard_Real TolS)
72
73{
74 Initialize(S, Uinf, Usup, Vinf, Vsup, TolC, TolS);
75 Perform(C, UCinf, UCsup);
76}
77
78
79void Extrema_ExtCS::Initialize(const Adaptor3d_Surface& S,
80 const Standard_Real Uinf,
81 const Standard_Real Usup,
82 const Standard_Real Vinf,
83 const Standard_Real Vsup,
84 const Standard_Real TolC,
85 const Standard_Real TolS)
86{
87 myS = (Adaptor3d_SurfacePtr)&S;
88 myIsPar = Standard_False;
89 myuinf = Uinf;
90 myusup = Usup;
91 myvinf = Vinf;
92 myvsup = Vsup;
93 mytolC = TolC;
94 mytolS = TolS;
95 myStype = myS->GetType();
96}
97
98
99void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C,
100 const Standard_Real Uinf,
101 const Standard_Real Usup)
102{
103 myucinf = Uinf;
104 myucsup = Usup;
105 myPOnS.Clear();
106 myPOnC.Clear();
107 mySqDist.Clear();
108 Standard_Integer i;
109 Standard_Integer NbT, NbU, NbV;
110 NbT = NbU = NbV = 10;
111 GeomAbs_CurveType myCtype = C.GetType();
112
113
114 switch(myCtype) {
115
116 case GeomAbs_Line:
117 {
118
119 switch(myStype) {
120 case GeomAbs_Sphere:
121 myExtElCS.Perform(C.Line(), myS->Sphere());
122 break;
123 case GeomAbs_Cylinder:
124 myExtElCS.Perform(C.Line(), myS->Cylinder());
125 break;
126 case GeomAbs_Plane:
127 myExtElCS.Perform(C.Line(), myS->Plane());
128 if (myExtElCS.IsParallel()) break;
129
130 case GeomAbs_Torus:
131 case GeomAbs_Cone:
132 case GeomAbs_BezierSurface:
133 case GeomAbs_BSplineSurface:
134 case GeomAbs_SurfaceOfRevolution:
135 case GeomAbs_SurfaceOfExtrusion:
136 case GeomAbs_OtherSurface:
137 {
138 Standard_Real cfirst = myucinf, clast = myucsup;
139 Standard_Real ufirst = myS->FirstUParameter(), ulast = myS->LastUParameter(),
140 vfirst = myS->FirstVParameter(), vlast = myS->LastVParameter();
141
142 if(Precision::IsInfinite(Abs(cfirst)) || Precision::IsInfinite(Abs(clast))) {
143
144 Bnd_Box aSurfBox;
6e6cd5d9 145 BndLib_AddSurface::Add(*myS, ufirst, ulast, vfirst, vlast, Precision::Confusion(), aSurfBox);
7fd59977 146 Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
147 aSurfBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
148 Standard_Real tmin = Precision::Infinite(), tmax = -tmin;
149 gp_Lin aLin = C.Line();
150
151
152 if(!( Precision::IsInfinite(Abs(xmin)) || Precision::IsInfinite(Abs(xmax)) ||
153 Precision::IsInfinite(Abs(ymin)) || Precision::IsInfinite(Abs(ymax)) ||
154 Precision::IsInfinite(Abs(zmin)) || Precision::IsInfinite(Abs(zmax))) ) {
155
156 Extrema_ExtPElC anExt;
157 Extrema_POnCurv aPntOnLin;
158 Standard_Real aParOnLin;
159 Standard_Real lim = Precision::Infinite();
160 gp_Pnt aLimPntArray[8];
161
162 aLimPntArray[0].SetCoord(xmin, ymin, zmin);
163 aLimPntArray[1].SetCoord(xmax, ymin, zmin);
164 aLimPntArray[2].SetCoord(xmin, ymax, zmin);
165 aLimPntArray[3].SetCoord(xmax, ymax, zmin);
166 aLimPntArray[4].SetCoord(xmin, ymin, zmax);
167 aLimPntArray[5].SetCoord(xmax, ymin, zmax);
168 aLimPntArray[6].SetCoord(xmin, ymax, zmax);
169 aLimPntArray[7].SetCoord(xmax, ymax, zmax);
170
171 for(i = 0; i <= 7; i++) {
172 anExt.Perform(aLimPntArray[i], aLin, Precision::Confusion(), -lim, lim);
173 aPntOnLin = anExt.Point(1);
174 aParOnLin = aPntOnLin.Parameter();
175 tmin = Min(aParOnLin, tmin);
176 tmax = Max(aParOnLin, tmax);
177 }
178
179 }
180 else {
181 tmin = -1.e+50;
182 tmax = 1.e+50;
183 }
184
185
186 cfirst = Max(cfirst, tmin);
187 clast = Min(clast, tmax);
188
189 }
190
191
192
193 Extrema_GenExtCS Ext(C, *myS, NbT, NbU, NbV, cfirst, clast, ufirst, ulast,
194 vfirst, vlast, mytolC, mytolS);
195
196 myDone = Ext.IsDone();
197 if (myDone) {
198 Standard_Integer NbExt = Ext.NbExt();
199 Standard_Real T,U,V;
200 Extrema_POnCurv PC;
201 Extrema_POnSurf PS;
202 for (i = 1; i <= NbExt; i++) {
203 PC = Ext.PointOnCurve(i);
204 PS = Ext.PointOnSurface(i);
205 T = PC.Parameter();
206 PS.Parameter(U, V);
207 if (myS->IsUPeriodic())
208 U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
209 if (myS->IsVPeriodic())
210 V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());
211
212 if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
213 (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
214 (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
215 mySqDist.Append(Ext.SquareDistance(i));
216 myPOnC.Append(PC);
217 myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
218
219
220 }
221 }
222 }
223 return;
224
225 }
226#ifndef DEB
227 default:
228#endif
229 break;
230 }
231 break;
232 }
233// Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 Begin
234 case GeomAbs_Circle:
235 {
236 if(myStype == GeomAbs_Cylinder) {
237 myExtElCS.Perform(C.Circle(), myS->Cylinder());
238 break;
239 }
240 }
241 case GeomAbs_Hyperbola:
242 {
243 if(myCtype == GeomAbs_Hyperbola && myStype == GeomAbs_Plane) {
244// Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 End
245 myExtElCS.Perform(C.Hyperbola(), myS->Plane());
246 break;
247 }
248 }
249 default:
250 {
251 Extrema_GenExtCS Ext;
252 Ext.Initialize(*myS, NbU, NbV, mytolS);
253 if(myCtype == GeomAbs_Hyperbola) {
254 Standard_Real tmin = Max(-20., C.FirstParameter());
255 Standard_Real tmax = Min(20., C.LastParameter());
256 Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow
257 }
258 else {
259 if(myCtype == GeomAbs_Circle && NbT < 13) {
260 NbT = 13;
261 }
262 Ext.Perform(C, NbT, mytolC);
263 }
264
265 myDone = Ext.IsDone();
266 if (myDone) {
267 Standard_Integer NbExt = Ext.NbExt();
268 Standard_Real T,U,V;
269 Extrema_POnCurv PC;
270 Extrema_POnSurf PS;
271 for (i = 1; i <= NbExt; i++) {
272 PC = Ext.PointOnCurve(i);
273 PS = Ext.PointOnSurface(i);
274 T = PC.Parameter();
275 PS.Parameter(U, V);
276 if (C.IsPeriodic())
277 T = ElCLib::InPeriod(T, myucinf, myucinf+C.Period());
278 if (myS->IsUPeriodic())
279 U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
280 if (myS->IsVPeriodic())
281 V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());
282
283 if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
284 (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
285 (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
286 mySqDist.Append(Ext.SquareDistance(i));
287 PC.SetValues(T, PC.Value());
288 myPOnC.Append(PC);
289 myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
290 }
291 }
292 }
293 return;
294 }
295 break;
296 }
297
298 myDone = myExtElCS.IsDone();
299 if (myDone) {
300 myIsPar = myExtElCS.IsParallel();
301 if (myIsPar) {
302 mySqDist.Append(myExtElCS.SquareDistance(1));
303 }
304 else {
305 Standard_Integer NbExt = myExtElCS.NbExt();
306 Standard_Real U, V;
307 for (i = 1; i <= NbExt; i++) {
308 Extrema_POnCurv PC;
309 Extrema_POnSurf PS;
310 myExtElCS.Points(i, PC, PS);
311 Standard_Real Ucurve = PC.Parameter();
312 PS.Parameter(U, V);
313
314 if((myStype == GeomAbs_Sphere) || (myStype == GeomAbs_Cylinder)) {
c6541a0c 315 U = ElCLib::InPeriod(U, myuinf, myuinf+2.*M_PI);
7fd59977 316 }
317
318 if ((myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
319 (myvinf-V) <= mytolS && (V-myvsup) <= mytolS &&
320 (myucinf-Ucurve) <= mytolC && (Ucurve-myucsup) <= mytolC) {
321 mySqDist.Append(myExtElCS.SquareDistance(i));
322 myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
323 myPOnC.Append(PC);
324 }
325 }
326 }
327 }
328
329}
330
331
332Standard_Boolean Extrema_ExtCS::IsDone() const
333{
334 return myDone;
335}
336
337Standard_Boolean Extrema_ExtCS::IsParallel() const
338{
339 return myIsPar;
340}
341
342
343Standard_Real Extrema_ExtCS::SquareDistance(const Standard_Integer N) const
344{
345 if(!myDone) StdFail_NotDone::Raise();
346 if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
347 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
348 return mySqDist.Value(N);
349}
350
351
352Standard_Integer Extrema_ExtCS::NbExt() const
353{
354 if(!myDone) StdFail_NotDone::Raise();
355 return mySqDist.Length();
356}
357
358
359
360void Extrema_ExtCS::Points(const Standard_Integer N,
361 Extrema_POnCurv& P1,
362 Extrema_POnSurf& P2) const
363{
364 if(!myDone) StdFail_NotDone::Raise();
365 P1 = myPOnC.Value(N);
366 P2 = myPOnS.Value(N);
367}