0024624: Lost word in license statement in source files
[occt.git] / src / BRepClass3d / BRepClass3d_SClassifier.cxx
CommitLineData
b311480e 1// Created on: 1996-07-15
2// Created by: Laurent BUCHARD
3// Copyright (c) 1996-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
17// Modified by skv - Thu Sep 4 11:22:05 2003 OCC578
18
19#include <BRepClass3d_SClassifier.ixx>
20
21#include <gp_Pnt.hxx>
22#include <gp_Lin.hxx>
23#include <gp_Vec.hxx>
24#include <BRepClass3d_Intersector3d.hxx>
25#include <TopoDS.hxx>
26
27#include <IntCurvesFace_Intersector.hxx>
28// modified by NIZHNY-MKK Mon Jun 21 15:13:40 2004
29#include <Precision.hxx>
30#include <ElCLib.hxx>
bd05fabf
S
31#include <Geom_Surface.hxx>
32#include <BRep_Tool.hxx>
be7c077a 33#include <math_RealRandom.hxx>
34#include <BRepTopAdaptor_FClass2d.hxx>
7fd59977 35
bd05fabf 36static
be7c077a 37 Standard_Boolean FaceNormal (const TopoDS_Face& aF,
38 const Standard_Real U,
39 const Standard_Real V,
40 gp_Dir& aDN);
7fd59977 41
bd05fabf
S
42static
43 Standard_Real GetAddToParam(const gp_Lin& L,const Standard_Real P,const Bnd_Box& B);
7fd59977 44
45
bd05fabf
S
46
47//=======================================================================
48//function : BRepClass3d_SClassifier
49//purpose :
50//=======================================================================
7fd59977 51BRepClass3d_SClassifier::BRepClass3d_SClassifier()
52{
53}
54
55
bd05fabf
S
56//=======================================================================
57//function : BRepClass3d_SClassifier
58//purpose :
59//=======================================================================
7fd59977 60BRepClass3d_SClassifier::BRepClass3d_SClassifier(BRepClass3d_SolidExplorer& S,
61 const gp_Pnt& P,
62 const Standard_Real Tol) {
63 if(S.Reject(P)) {
c898afce 64 myState=3; //-- in ds solid case without face
7fd59977 65 }
66 else {
67 Perform(S,P,Tol);
68 }
69}
70
71
bd05fabf
S
72//=======================================================================
73//function : PerformInfinitePoint
74//purpose :
75//=======================================================================
76void BRepClass3d_SClassifier::PerformInfinitePoint(BRepClass3d_SolidExplorer& aSE,
7fd59977 77 const Standard_Real /*Tol*/) {
7fd59977 78
be7c077a 79 //Take a normal to the first extracted face in its random inner point
80 //and intersect this reversed normal with the faces of the solid.
81 //If the min.par.-intersection point is
82 // a) inner point of a face
83 // b) transition is not TANGENT
84 // (the line does not touch the face but pierces it)
85 //then set <myState> to IN or OUT according to transition
86 //else take the next random point inside the min.par.-intersected face
87 //and continue
88
bd05fabf 89 if(aSE.Reject(gp_Pnt(0,0,0))) {
c898afce 90 myState=3; //-- in ds solid case without face
7fd59977 91 return;
92 }
bd05fabf
S
93 //
94 //------------------------------------------------------------
95 // 1
be7c077a 96 Standard_Boolean bFound;
97 Standard_Real aParam, aU = 0., aV = 0.;
98 gp_Pnt aPoint;
99 gp_Dir aDN;
100
101 math_RealRandom RandomGenerator(0.1, 0.9);
7fd59977 102 myFace.Nullify();
be7c077a 103 myState=2;
104
105 aSE.InitShell();
106 if (aSE.MoreShell())
107 {
108 aSE.InitFace();
109 if (aSE.MoreFace())
110 {
e450f818 111 TopoDS_Face aF = aSE.CurrentFace();
be7c077a 112 TopAbs_State aState = TopAbs_OUT;
113 IntCurveSurface_TransitionOnCurve aTransition = IntCurveSurface_Tangent;
114 TopoDS_Face MinFace = aF;
115 for (;;)
7fd59977 116 {
be7c077a 117 aParam = RandomGenerator.Next();
118 bFound = aSE.FindAPointInTheFace(aF, aPoint, aU, aV, aParam);
119 if (!bFound)
120 return;
121
122 if (!FaceNormal(aF, aU, aV, aDN))
123 continue;
124 gp_Lin aLin(aPoint, -aDN);
125 Standard_Real parmin = RealLast();
126 for (aSE.InitShell();aSE.MoreShell();aSE.NextShell()) {
127 if (aSE.RejectShell(aLin) == Standard_False) {
128 for (aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) {
129 if (aSE.RejectFace(aLin) == Standard_False) {
130 TopoDS_Shape aLocalShape = aSE.CurrentFace();
131 TopoDS_Face CurFace = TopoDS::Face(aLocalShape);
132 IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(CurFace);
133 Intersector3d.Perform(aLin,-RealLast(),parmin);
134
135 if(Intersector3d.IsDone()) {
136 if(Intersector3d.NbPnt()) {
137 Standard_Integer imin = 1;
138 for (Standard_Integer i = 2; i <= Intersector3d.NbPnt(); i++)
139 if (Intersector3d.WParameter(i) < Intersector3d.WParameter(imin))
140 imin = i;
141 parmin = Intersector3d.WParameter(imin);
142 aState = Intersector3d.State(imin);
143 aTransition = Intersector3d.Transition(imin);
144 MinFace = CurFace;
145 }
146 }
147 }
148 }
149 }
150 else
151 myState = 1;
152 } //end of loop on the whole solid
153
154 if (aState == TopAbs_IN)
155 {
156 if (aTransition == IntCurveSurface_Out) {
157 //-- The line is going from inside the solid to outside
158 //-- the solid.
159 myState = 3; //-- IN --
160 return;
161 }
162 else if (aTransition == IntCurveSurface_In) {
163 myState = 4; //-- OUT --
164 return;
165 }
166 }
167 aF = MinFace;
7fd59977 168 }
be7c077a 169 } //if (aSE.MoreFace())
170 } //if (aSE.MoreShell())
7fd59977 171}
be7c077a 172
7fd59977 173//=======================================================================
174//function : Perform
175//purpose :
176//=======================================================================
bd05fabf
S
177void BRepClass3d_SClassifier::Perform(BRepClass3d_SolidExplorer& SolidExplorer,
178 const gp_Pnt& P,
179 const Standard_Real Tol)
7fd59977 180{
181
182
183 if(SolidExplorer.Reject(P)) {
c898afce 184 myState=3; //-- in ds solid case without face
7fd59977 185 return;
186 }
187
188
189 myFace.Nullify();
190 myState = 0;
191 if(SolidExplorer.Reject(P) == Standard_False) {
192 gp_Lin L;
193 Standard_Real Par;
194 //-- We compute the intersection betwwen the line builded in the Solid Explorer
195 //-- and the shape.
196
197 //-- --------------------------------------------------------------------------------
c898afce
Y
198 //-- Calculate intersection with the face closest to the direction of bounding boxes
199 //-- by priority so that to have the smallest possible parmin.
200 //-- optimization to produce as much as possible rejections with other faces.
7fd59977 201 Standard_Integer iFlag;
202 //
203
204 // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 Begin
205 // If found line passes through a bound of any face, it means that the line
206 // is not found properly and it is necessary to repeat whole procedure.
207 // That's why the main loop while is added.
208 Standard_Boolean isFaultyLine = Standard_True;
209 Standard_Integer anIndFace = 0;
1d47d8d0 210 Standard_Real parmin = 0.;
7fd59977 211
212 while (isFaultyLine) {
213 if (anIndFace == 0) {
214 iFlag = SolidExplorer.Segment(P,L,Par);
215 } else {
216 iFlag = SolidExplorer.OtherSegment(P,L,Par);
217 }
218
219 Standard_Integer aCurInd = SolidExplorer.GetFaceSegmentIndex();
220
221 if (aCurInd > anIndFace) {
222 anIndFace = aCurInd;
223 } else {
224 myState = 1;
225
226 return;
227 }
228 // Modified by skv - Thu Sep 4 11:22:10 2003 OCC578 End
229
230 if (iFlag==1) {
231 // IsOnFace
232 // iFlag==1 i.e face is Infinite
233 myState=2;
234
235 return;
236 }
237 //SolidExplorer.Segment(P,L,Par);
7fd59977 238 //
239 //process results from uncorrected shells
240 //
7fd59977 241 //if(Par > 1.e+100 && L.Direction().IsParallel(gp_Dir(0.,0.,1.),1.e-8)) {
242 if (iFlag==2) {
7fd59977 243 myState = 4;
244 return;
245 }
246 //-- BRepClass3d_Intersector3d Intersector3d;
247
248 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
249 // Check if the point is ON surface but OUT of the face.
250 // Just skip this face because it is bad for classification.
251 if (iFlag == 3)
252 continue;
253
254 isFaultyLine = Standard_False;
255// Standard_Real parmin = RealLast();
256
257// for(SolidExplorer.InitShell();
258// SolidExplorer.MoreShell();
259// SolidExplorer.NextShell()) {
260 parmin = RealLast();
261
262 for(SolidExplorer.InitShell();
263 SolidExplorer.MoreShell() && !isFaultyLine;
264 SolidExplorer.NextShell()) {
265// Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
266
267 if(SolidExplorer.RejectShell(L) == Standard_False) {
268
269// Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
270// for(SolidExplorer.InitFace();
271// SolidExplorer.MoreFace();
272// SolidExplorer.NextFace()) {
273 for(SolidExplorer.InitFace();
274 SolidExplorer.MoreFace() && !isFaultyLine;
275 SolidExplorer.NextFace()) {
276// Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
277
278 if(SolidExplorer.RejectFace(L) == Standard_False) {
279
280 //-- Intersector3d.Perform(L,Par,Tol,SolidExplorer.CurrentFace());
281 TopoDS_Shape aLocalShape = SolidExplorer.CurrentFace();
282 TopoDS_Face f = TopoDS::Face(aLocalShape);
283 // TopoDS_Face f = TopoDS::Face(SolidExplorer.CurrentFace());
284 IntCurvesFace_Intersector& Intersector3d = SolidExplorer.Intersector(f);
285
286 // MSV Oct 25, 2001: prolong segment, since there are cases when
287 // the intersector does not find intersection points with the original
288 // segment due to rough triangulation of a parametrized surface
289 Standard_Real addW = Max(10*Tol, 0.01*Par);
290 Standard_Real AddW = addW;
291
292 Bnd_Box aBoxF = Intersector3d.Bounding();
293
294 // MSV 23.09.2004: the box must be finite in order to
295 // correctly prolong the segment to its bounds
296 if (!aBoxF.IsVoid() && !aBoxF.IsWhole()) {
297 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
298 aBoxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
299
300 Standard_Real boxaddW = GetAddToParam(L,Par,aBoxF);
301 addW = Max(addW,boxaddW);
302 }
303
304 Standard_Real minW = -AddW;//-addW;
305 Standard_Real maxW = Min(Par*10,Par+addW);//Par+addW;
306 //cout << "range [" << minW << "," << maxW << "]" << endl << endl;
307 Intersector3d.Perform(L,minW,maxW);
308 //Intersector3d.Perform(L,-Tol,Par+10.0*Tol);
309 if(Intersector3d.IsDone()) {
310 Standard_Integer i;
311 for (i=1; i <= Intersector3d.NbPnt(); i++) {
312 if(Abs(Intersector3d.WParameter(i)) < Abs(parmin)) {
313
314 parmin = Intersector3d.WParameter(i);
315 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
316 TopAbs_State aState = Intersector3d.State(i);
317 // Modified by skv - Thu Sep 4 12:46:33 2003 OCC578 End
318 if(Abs(parmin)<=Tol) {
319 myState = 2;
320 myFace = f;
321 }
322 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
323 // Treatment of case TopAbs_ON separately.
324
325 else if(aState==TopAbs_IN) {
326 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 End
327
328 //-- The intersection point between the line and a face F
329 // -- of the solid is in the face F
330
331 IntCurveSurface_TransitionOnCurve tran = Intersector3d.Transition(i);
332 if (tran == IntCurveSurface_Tangent) {
333#ifdef DEB
c898afce 334 cout<<"*Problem ds BRepClass3d_SClassifier.cxx"<<endl;
7fd59977 335#endif
336 continue; // ignore this point
337 }
338 // if parmin is negative we should reverse transition
339 if (parmin < 0)
340 tran = (tran == IntCurveSurface_Out
341 ? IntCurveSurface_In : IntCurveSurface_Out);
342 if(tran == IntCurveSurface_Out) {
343 //-- The line is going from inside the solid to outside
344 //-- the solid.
345 myState = 3; //-- IN --
346 }
347 else /* if(tran == IntCurveSurface_In) */ {
348 myState = 4; //-- OUT --
349 }
350 myFace = f;
351 }
352 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 Begin
353 // If the state is TopAbs_ON, it is necessary to chose
354 // another line and to repeat the whole procedure.
355 else if(aState==TopAbs_ON) {
356 isFaultyLine = Standard_True;
357
358 break;
359 }
360 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 End
361 }
362 else {
363 //-- No point has been found by the Intersector3d.
364 //-- Or a Point has been found with a greater parameter.
365 }
366 } //-- loop by intersection points
367 } //-- Face has not been rejected
368 else {
369 myState = 1;
370 }
371 }
372 } //-- Exploration of the faces
373 } //-- Shell has not been rejected
374 else {
375 myState=1;
376 }
377 } //-- Exploration of the shells
378
379 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 Begin
380 // The end of main loop.
381 }
382 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 End
383
384#ifdef DEB
385 //#################################################
386 SolidExplorer.DumpSegment(P,L,parmin,State());
387 //#################################################
388#endif
389
390 } //-- Solid has not been rejected
391 else {
392 myState = 1;
393 }
394}
395
396
397TopAbs_State BRepClass3d_SClassifier::State() const {
398 if(myState==2) return(TopAbs_ON);
399 if(myState==4) return(TopAbs_OUT); //--
400 else if(myState==3) return(TopAbs_IN); //--
401 return(TopAbs_OUT);
402}
403
404TopoDS_Face BRepClass3d_SClassifier::Face() const {
405 return(myFace);
406}
407
408Standard_Boolean BRepClass3d_SClassifier::Rejected() const {
409 return(myState==1);
410}
411
412
413Standard_Boolean BRepClass3d_SClassifier::IsOnAFace() const {
414 return(myState==2);
415}
416
417
418void BRepClass3d_SClassifier::ForceIn() {
419 myState=3;
420}
421
422void BRepClass3d_SClassifier::ForceOut() {
423 myState=4;
424}
425
426Standard_Real GetAddToParam(const gp_Lin& L,
427 const Standard_Real P,
428 const Bnd_Box& B)
429{
430 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
431 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
432 Standard_Real x[2] = {aXmin,aXmax}, y[2] = {aYmin,aYmax}, z[2] = {aZmin,aZmax};
433 Standard_Integer i = 0, j = 0, k = 0;
434 Standard_Real Par = P;
435 for(i = 0 ; i < 2; i++) {
436 for(j = 0; j < 2; j++) {
437 for(k = 0; k < 2; k++) {
438 Standard_Real X = fabs(x[i]-L.Location().X());
439 Standard_Real Y = fabs(y[j]-L.Location().Y());
440 Standard_Real Z = fabs(z[k]-L.Location().Z());
441 if(X < 1.e+20 && Y < 1.e+20 && Z < 1.e+20) {
442 gp_Pnt aP(x[i],y[j],z[k]);
443 Standard_Real par = ElCLib::Parameter(L,aP);
444 if(par > Par)
445 Par = par;
446 }
447 else
448 return 1.e+20;
449 }
450 }
451 }
452 return Par - P;
453}
bd05fabf
S
454//=======================================================================
455//function : FaceNormal
456//purpose :
457//=======================================================================
be7c077a 458Standard_Boolean FaceNormal (const TopoDS_Face& aF,
459 const Standard_Real U,
460 const Standard_Real V,
461 gp_Dir& aDN)
bd05fabf
S
462{
463 gp_Pnt aPnt ;
464 gp_Vec aD1U, aD1V, aN;
465 Handle(Geom_Surface) aS;
466
467 aS=BRep_Tool::Surface(aF);
468 aS->D1 (U, V, aPnt, aD1U, aD1V);
469 aN=aD1U.Crossed(aD1V);
be7c077a 470 if (aN.Magnitude() <= gp::Resolution())
471 return Standard_False;
472
bd05fabf
S
473 aN.Normalize();
474 aDN.SetXYZ(aN.XYZ());
475 if (aF.Orientation() == TopAbs_REVERSED){
476 aDN.Reverse();
477 }
be7c077a 478 return Standard_True;
bd05fabf 479}