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