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