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