0022765: Sewing produced invalid shape from attached compond with tolerance 0.1
[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)) {
52 myState=3; //-- in ds le cas solide sans face
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*/) {
66 //-- Idee : On prend un point A dans la face1 et un point B dans la face B
67 //-- ( si on a une seule face , on prend 2 points dans la meme face.)
68 //--
69 //-- On intersecte la droite AB avec le solide et on s interesse a la transition du
70 //-- premier point. Si le solide a une seule face et que la droite AB ne le coupe pas
71 //-- on ne peut pas decider.
72
bd05fabf 73 if(aSE.Reject(gp_Pnt(0,0,0))) {
7fd59977 74 myState=3; //-- in ds le cas solide sans face
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
S
84 gp_Dir aDN1, aDN2;
85 TopoDS_Face aF, aF1, aF2;
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; ) {
93 aF =*((TopoDS_Face*)&aSE.CurrentFace());
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)) {
235 myState=3; //-- in ds le cas solide sans face
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 //-- --------------------------------------------------------------------------------
249 //-- ON calcule l intersection avec la face la plus proche au sens des boites
250 //-- englobantes en priorite de facon a avoir un parmin le plus faible possible.
251 //-- optimisation pour assurer le plus de rejections possibles avec les autres
252 //-- faces.
7fd59977 253 Standard_Integer iFlag;
254 //
255
256 // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 Begin
257 // If found line passes through a bound of any face, it means that the line
258 // is not found properly and it is necessary to repeat whole procedure.
259 // That's why the main loop while is added.
260 Standard_Boolean isFaultyLine = Standard_True;
261 Standard_Integer anIndFace = 0;
262 Standard_Real parmin;
263
264 while (isFaultyLine) {
265 if (anIndFace == 0) {
266 iFlag = SolidExplorer.Segment(P,L,Par);
267 } else {
268 iFlag = SolidExplorer.OtherSegment(P,L,Par);
269 }
270
271 Standard_Integer aCurInd = SolidExplorer.GetFaceSegmentIndex();
272
273 if (aCurInd > anIndFace) {
274 anIndFace = aCurInd;
275 } else {
276 myState = 1;
277
278 return;
279 }
280 // Modified by skv - Thu Sep 4 11:22:10 2003 OCC578 End
281
282 if (iFlag==1) {
283 // IsOnFace
284 // iFlag==1 i.e face is Infinite
285 myState=2;
286
287 return;
288 }
289 //SolidExplorer.Segment(P,L,Par);
7fd59977 290 //
291 //process results from uncorrected shells
292 //
7fd59977 293 //if(Par > 1.e+100 && L.Direction().IsParallel(gp_Dir(0.,0.,1.),1.e-8)) {
294 if (iFlag==2) {
7fd59977 295 myState = 4;
296 return;
297 }
298 //-- BRepClass3d_Intersector3d Intersector3d;
299
300 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
301 // Check if the point is ON surface but OUT of the face.
302 // Just skip this face because it is bad for classification.
303 if (iFlag == 3)
304 continue;
305
306 isFaultyLine = Standard_False;
307// Standard_Real parmin = RealLast();
308
309// for(SolidExplorer.InitShell();
310// SolidExplorer.MoreShell();
311// SolidExplorer.NextShell()) {
312 parmin = RealLast();
313
314 for(SolidExplorer.InitShell();
315 SolidExplorer.MoreShell() && !isFaultyLine;
316 SolidExplorer.NextShell()) {
317// Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
318
319 if(SolidExplorer.RejectShell(L) == Standard_False) {
320
321// Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
322// for(SolidExplorer.InitFace();
323// SolidExplorer.MoreFace();
324// SolidExplorer.NextFace()) {
325 for(SolidExplorer.InitFace();
326 SolidExplorer.MoreFace() && !isFaultyLine;
327 SolidExplorer.NextFace()) {
328// Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
329
330 if(SolidExplorer.RejectFace(L) == Standard_False) {
331
332 //-- Intersector3d.Perform(L,Par,Tol,SolidExplorer.CurrentFace());
333 TopoDS_Shape aLocalShape = SolidExplorer.CurrentFace();
334 TopoDS_Face f = TopoDS::Face(aLocalShape);
335 // TopoDS_Face f = TopoDS::Face(SolidExplorer.CurrentFace());
336 IntCurvesFace_Intersector& Intersector3d = SolidExplorer.Intersector(f);
337
338 // MSV Oct 25, 2001: prolong segment, since there are cases when
339 // the intersector does not find intersection points with the original
340 // segment due to rough triangulation of a parametrized surface
341 Standard_Real addW = Max(10*Tol, 0.01*Par);
342 Standard_Real AddW = addW;
343
344 Bnd_Box aBoxF = Intersector3d.Bounding();
345
346 // MSV 23.09.2004: the box must be finite in order to
347 // correctly prolong the segment to its bounds
348 if (!aBoxF.IsVoid() && !aBoxF.IsWhole()) {
349 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
350 aBoxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
351
352 Standard_Real boxaddW = GetAddToParam(L,Par,aBoxF);
353 addW = Max(addW,boxaddW);
354 }
355
356 Standard_Real minW = -AddW;//-addW;
357 Standard_Real maxW = Min(Par*10,Par+addW);//Par+addW;
358 //cout << "range [" << minW << "," << maxW << "]" << endl << endl;
359 Intersector3d.Perform(L,minW,maxW);
360 //Intersector3d.Perform(L,-Tol,Par+10.0*Tol);
361 if(Intersector3d.IsDone()) {
362 Standard_Integer i;
363 for (i=1; i <= Intersector3d.NbPnt(); i++) {
364 if(Abs(Intersector3d.WParameter(i)) < Abs(parmin)) {
365
366 parmin = Intersector3d.WParameter(i);
367 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
368 TopAbs_State aState = Intersector3d.State(i);
369 // Modified by skv - Thu Sep 4 12:46:33 2003 OCC578 End
370 if(Abs(parmin)<=Tol) {
371 myState = 2;
372 myFace = f;
373 }
374 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
375 // Treatment of case TopAbs_ON separately.
376
377 else if(aState==TopAbs_IN) {
378 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 End
379
380 //-- The intersection point between the line and a face F
381 // -- of the solid is in the face F
382
383 IntCurveSurface_TransitionOnCurve tran = Intersector3d.Transition(i);
384 if (tran == IntCurveSurface_Tangent) {
385#ifdef DEB
386 cout<<"*Probleme ds BRepClass3d_SClassifier.cxx"<<endl;
387#endif
388 continue; // ignore this point
389 }
390 // if parmin is negative we should reverse transition
391 if (parmin < 0)
392 tran = (tran == IntCurveSurface_Out
393 ? IntCurveSurface_In : IntCurveSurface_Out);
394 if(tran == IntCurveSurface_Out) {
395 //-- The line is going from inside the solid to outside
396 //-- the solid.
397 myState = 3; //-- IN --
398 }
399 else /* if(tran == IntCurveSurface_In) */ {
400 myState = 4; //-- OUT --
401 }
402 myFace = f;
403 }
404 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 Begin
405 // If the state is TopAbs_ON, it is necessary to chose
406 // another line and to repeat the whole procedure.
407 else if(aState==TopAbs_ON) {
408 isFaultyLine = Standard_True;
409
410 break;
411 }
412 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 End
413 }
414 else {
415 //-- No point has been found by the Intersector3d.
416 //-- Or a Point has been found with a greater parameter.
417 }
418 } //-- loop by intersection points
419 } //-- Face has not been rejected
420 else {
421 myState = 1;
422 }
423 }
424 } //-- Exploration of the faces
425 } //-- Shell has not been rejected
426 else {
427 myState=1;
428 }
429 } //-- Exploration of the shells
430
431 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 Begin
432 // The end of main loop.
433 }
434 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 End
435
436#ifdef DEB
437 //#################################################
438 SolidExplorer.DumpSegment(P,L,parmin,State());
439 //#################################################
440#endif
441
442 } //-- Solid has not been rejected
443 else {
444 myState = 1;
445 }
446}
447
448
449TopAbs_State BRepClass3d_SClassifier::State() const {
450 if(myState==2) return(TopAbs_ON);
451 if(myState==4) return(TopAbs_OUT); //--
452 else if(myState==3) return(TopAbs_IN); //--
453 return(TopAbs_OUT);
454}
455
456TopoDS_Face BRepClass3d_SClassifier::Face() const {
457 return(myFace);
458}
459
460Standard_Boolean BRepClass3d_SClassifier::Rejected() const {
461 return(myState==1);
462}
463
464
465Standard_Boolean BRepClass3d_SClassifier::IsOnAFace() const {
466 return(myState==2);
467}
468
469
470void BRepClass3d_SClassifier::ForceIn() {
471 myState=3;
472}
473
474void BRepClass3d_SClassifier::ForceOut() {
475 myState=4;
476}
477
478Standard_Real GetAddToParam(const gp_Lin& L,
479 const Standard_Real P,
480 const Bnd_Box& B)
481{
482 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
483 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
484 Standard_Real x[2] = {aXmin,aXmax}, y[2] = {aYmin,aYmax}, z[2] = {aZmin,aZmax};
485 Standard_Integer i = 0, j = 0, k = 0;
486 Standard_Real Par = P;
487 for(i = 0 ; i < 2; i++) {
488 for(j = 0; j < 2; j++) {
489 for(k = 0; k < 2; k++) {
490 Standard_Real X = fabs(x[i]-L.Location().X());
491 Standard_Real Y = fabs(y[j]-L.Location().Y());
492 Standard_Real Z = fabs(z[k]-L.Location().Z());
493 if(X < 1.e+20 && Y < 1.e+20 && Z < 1.e+20) {
494 gp_Pnt aP(x[i],y[j],z[k]);
495 Standard_Real par = ElCLib::Parameter(L,aP);
496 if(par > Par)
497 Par = par;
498 }
499 else
500 return 1.e+20;
501 }
502 }
503 }
504 return Par - P;
505}
bd05fabf
S
506//=======================================================================
507//function : FaceNormal
508//purpose :
509//=======================================================================
510void FaceNormal (const TopoDS_Face& aF,
511 const Standard_Real U,
512 const Standard_Real V,
513 gp_Dir& aDN)
514{
515 gp_Pnt aPnt ;
516 gp_Vec aD1U, aD1V, aN;
517 Handle(Geom_Surface) aS;
518
519 aS=BRep_Tool::Surface(aF);
520 aS->D1 (U, V, aPnt, aD1U, aD1V);
521 aN=aD1U.Crossed(aD1V);
522 aN.Normalize();
523 aDN.SetXYZ(aN.XYZ());
524 if (aF.Orientation() == TopAbs_REVERSED){
525 aDN.Reverse();
526 }
527 return;
528}