0027117: BRepClass3d_SolidClassifier doesn't take into account vertex/edge/face toler...
[occt.git] / src / IntCurvesFace / IntCurvesFace_Intersector.cxx
1 // Created on: 1996-06-03
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #define OPTIMISATION 1 
18
19 #include <Adaptor3d_HCurve.hxx>
20 #include <Adaptor3d_HSurfaceTool.hxx>
21 #include <Bnd_BoundSortBox.hxx>
22 #include <Bnd_Box.hxx>
23 #include <BRepAdaptor_HSurface.hxx>
24 #include <BRepClass_FaceClassifier.hxx>
25 #include <BRepTopAdaptor_TopolTool.hxx>
26 #include <Geom_Line.hxx>
27 #include <GeomAdaptor_Curve.hxx>
28 #include <GeomAdaptor_HCurve.hxx>
29 #include <gp_Lin.hxx>
30 #include <gp_Pnt.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <IntCurvesFace_Intersector.hxx>
33 #include <IntCurveSurface_HInter.hxx>
34 #include <IntCurveSurface_IntersectionPoint.hxx>
35 #include <IntCurveSurface_SequenceOfPnt.hxx>
36 #include <IntCurveSurface_TheHCurveTool.hxx>
37 #include <IntCurveSurface_ThePolygonOfHInter.hxx>
38 #include <IntCurveSurface_ThePolyhedronOfHInter.hxx>
39 #include <IntCurveSurface_ThePolyhedronToolOfHInter.hxx>
40 #include <Intf_Tool.hxx>
41 #include <TopAbs.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <BRep_Tool.hxx>
44 #include <TopoDS.hxx>
45 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
46 //=======================================================================
47 //function : SurfaceType
48 //purpose  : 
49 //=======================================================================
50 GeomAbs_SurfaceType IntCurvesFace_Intersector::SurfaceType() const 
51
52   return(Adaptor3d_HSurfaceTool::GetType(Hsurface));
53 }
54 //=======================================================================
55 //function : IntCurvesFace_Intersector
56 //purpose  : 
57 //=======================================================================
58 IntCurvesFace_Intersector::IntCurvesFace_Intersector(const TopoDS_Face& Face,
59                                                      const Standard_Real aTol,
60                                                      const Standard_Boolean aRestr,
61                                                      const Standard_Boolean UseBToler)
62                                                     
63
64   Tol(aTol),
65   done(Standard_False),
66   nbpnt(0),
67   PtrOnPolyhedron(NULL),
68   PtrOnBndBounding(NULL),
69   myUseBoundTol (UseBToler)
70
71   BRepAdaptor_Surface surface;
72   face = Face;
73   surface.Initialize(Face, aRestr);
74   Hsurface = new BRepAdaptor_HSurface(surface);
75   myTopolTool = new BRepTopAdaptor_TopolTool(Hsurface);
76   
77   GeomAbs_SurfaceType SurfaceType = Adaptor3d_HSurfaceTool::GetType(Hsurface);
78   if(   (SurfaceType != GeomAbs_Plane) 
79      && (SurfaceType != GeomAbs_Cylinder)
80      && (SurfaceType != GeomAbs_Cone) 
81      && (SurfaceType != GeomAbs_Sphere)
82      && (SurfaceType != GeomAbs_Torus)) {
83     Standard_Integer nbsu,nbsv;
84     Standard_Real U0,V0,U1,V1;
85     U0 = Hsurface->FirstUParameter();
86     U1 = Hsurface->LastUParameter();
87     V0 = Hsurface->FirstVParameter();
88     V1 = Hsurface->LastVParameter();
89
90     Standard_Real aURes = Hsurface->UResolution(1.0);
91     Standard_Real aVRes = Hsurface->VResolution(1.0);
92
93     // Checking correlation between number of samples and length of the face along each axis
94     const Standard_Real aTresh = 100.0;
95     const Standard_Integer aMinSamples = 10;
96     const Standard_Integer aMaxSamples = 40;
97     const Standard_Integer aMaxSamples2 = aMaxSamples * aMaxSamples;
98     Standard_Real dU = (U1 - U0) / aURes;
99     Standard_Real dV = (V1 - V0) / aVRes;
100     nbsu = myTopolTool->NbSamplesU();
101     nbsv = myTopolTool->NbSamplesV();
102     if (nbsu > aMaxSamples) nbsu = aMaxSamples;
103     if (nbsv > aMaxSamples) nbsv = aMaxSamples;
104
105     if (Max(dU, dV) > Min(dU, dV) * aTresh)
106     {
107       nbsu = (Standard_Integer)(Sqrt(dU / dV) * aMaxSamples);
108       if (nbsu < aMinSamples) nbsu = aMinSamples;
109       nbsv = aMaxSamples2 / nbsu;
110       if (nbsv < aMinSamples)
111       {
112         nbsv = aMinSamples;
113         nbsu = aMaxSamples2 / aMinSamples;
114       }
115     }
116     PtrOnPolyhedron = (IntCurveSurface_ThePolyhedronOfHInter *)
117         new IntCurveSurface_ThePolyhedronOfHInter(Hsurface,nbsu,nbsv,U0,V0,U1,V1);
118   }
119 }
120 //=======================================================================
121 //function : InternalCall
122 //purpose  : 
123 //=======================================================================
124 void IntCurvesFace_Intersector::InternalCall(const IntCurveSurface_HInter &HICS,
125                                              const Standard_Real parinf,
126                                              const Standard_Real parsup) 
127 {
128   if(HICS.IsDone() && HICS.NbPoints() > 0) {
129     //Calculate tolerance for 2d classifier
130     Standard_Real mintol3d = BRep_Tool::Tolerance(face);
131     Standard_Real maxtol3d = mintol3d;
132     Standard_Real mintol2d = Tol, maxtol2d = Tol;
133     TopExp_Explorer anExp(face, TopAbs_EDGE);
134     for(; anExp.More(); anExp.Next())
135     {
136       Standard_Real curtol = BRep_Tool::Tolerance(TopoDS::Edge(anExp.Current()));
137       mintol3d = Min(mintol3d, curtol);
138       maxtol3d = Max(maxtol3d, curtol);
139     }
140     Standard_Real minres = Max(Hsurface->UResolution(mintol3d), Hsurface->VResolution(mintol3d));
141     Standard_Real maxres = Max(Hsurface->UResolution(maxtol3d), Hsurface->VResolution(maxtol3d));
142     mintol2d = Max(minres, Tol); 
143     maxtol2d = Max(maxres, Tol);
144     //
145     Handle(BRepTopAdaptor_TopolTool) anAdditionalTool;
146     for(Standard_Integer index=HICS.NbPoints(); index>=1; index--) {  
147       const IntCurveSurface_IntersectionPoint& HICSPointindex = HICS.Point(index);
148       gp_Pnt2d Puv(HICSPointindex.U(),HICSPointindex.V());
149
150       //TopAbs_State currentstate = myTopolTool->Classify(Puv,Tol);
151       TopAbs_State currentstate = myTopolTool->Classify(Puv, !myUseBoundTol ? 0 : mintol2d);
152       if(myUseBoundTol && currentstate == TopAbs_OUT && maxtol2d > mintol2d) {
153         if(anAdditionalTool.IsNull())
154         {
155           anAdditionalTool = new BRepTopAdaptor_TopolTool(Hsurface);
156         }
157         currentstate = anAdditionalTool->Classify(Puv,maxtol2d);
158         if(currentstate == TopAbs_ON)
159         {
160           currentstate = TopAbs_OUT;
161           //Find out nearest edge and it's tolerance
162           anExp.Init(face, TopAbs_EDGE);
163           for(; anExp.More(); anExp.Next())
164           {
165             TopoDS_Edge anE = TopoDS::Edge(anExp.Current());
166             Standard_Real curtol = BRep_Tool::Tolerance(anE);
167             Standard_Real tol2d = Max(Hsurface->UResolution(curtol), Hsurface->VResolution(curtol));
168             tol2d = Max(tol2d, Tol);
169             Standard_Real f, l;
170             Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnSurface(anE, face, f, l);
171             Geom2dAPI_ProjectPointOnCurve aProj(Puv, aPC, f, l);
172             if(aProj.NbPoints() > 0)
173             {
174               Standard_Real d = aProj.LowerDistance();
175               if(d <= tol2d)
176               {
177                 //Nearest edge is found, state is really ON
178                 currentstate = TopAbs_ON;
179                 break;
180               }
181             }
182           }
183         }
184       }
185       if(currentstate==TopAbs_IN || currentstate==TopAbs_ON) { 
186         Standard_Real HICSW = HICSPointindex.W();
187         if(HICSW >= parinf && HICSW <= parsup ) { 
188           Standard_Real U          = HICSPointindex.U();
189           Standard_Real V          = HICSPointindex.V();
190           Standard_Real W          = HICSW; 
191           IntCurveSurface_TransitionOnCurve transition = HICSPointindex.Transition();
192           gp_Pnt pnt        = HICSPointindex.Pnt();
193           //      state      = currentstate;
194           //  Modified by skv - Wed Sep  3 16:14:10 2003 OCC578 Begin
195           Standard_Integer anIntState = (currentstate == TopAbs_IN) ? 0 : 1;
196           //  Modified by skv - Wed Sep  3 16:14:11 2003 OCC578 End
197
198           if(transition != IntCurveSurface_Tangent && face.Orientation()==TopAbs_REVERSED) { 
199             if(transition == IntCurveSurface_In) 
200               transition = IntCurveSurface_Out;
201             else 
202               transition = IntCurveSurface_In;
203           }
204           //----- Insertion du point 
205           if(nbpnt==0) { 
206             IntCurveSurface_IntersectionPoint PPP(pnt,U,V,W,transition);
207             SeqPnt.Append(PPP);
208             //  Modified by skv - Wed Sep  3 16:14:10 2003 OCC578 Begin
209             mySeqState.Append(anIntState);
210             //  Modified by skv - Wed Sep  3 16:14:11 2003 OCC578 End
211           }
212           else { 
213             Standard_Integer i = 1;
214             Standard_Integer b = nbpnt+1;                    
215             while(i<=nbpnt) {
216               const IntCurveSurface_IntersectionPoint& Pnti=SeqPnt.Value(i);
217               Standard_Real wi = Pnti.W();
218               if(wi >= W) { b=i; i=nbpnt; }
219               i++;
220             }
221             IntCurveSurface_IntersectionPoint PPP(pnt,U,V,W,transition);
222             //  Modified by skv - Wed Sep  3 16:14:10 2003 OCC578 Begin
223             //      if(b>nbpnt)          { SeqPnt.Append(PPP); } 
224             //      else if(b>0)             { SeqPnt.InsertBefore(b,PPP); } 
225             if(b>nbpnt) {
226               SeqPnt.Append(PPP);
227               mySeqState.Append(anIntState);
228             } else if(b>0) {
229               SeqPnt.InsertBefore(b,PPP);
230               mySeqState.InsertBefore(b, anIntState);
231             }
232             //  Modified by skv - Wed Sep  3 16:14:11 2003 OCC578 End
233           }
234
235
236           nbpnt++;
237         } 
238       } //-- classifier state is IN or ON
239     } //-- Loop on Intersection points.
240   } //-- HICS.IsDone()
241 }
242 //=======================================================================
243 //function : Perform
244 //purpose  : 
245 //=======================================================================
246 void IntCurvesFace_Intersector::Perform(const gp_Lin& L,
247                                         const Standard_Real ParMin,
248                                         const Standard_Real ParMax)
249
250   done = Standard_True;
251   SeqPnt.Clear();
252   mySeqState.Clear();
253   nbpnt = 0;
254   
255   IntCurveSurface_HInter HICS; 
256   Handle(Geom_Line) geomline = new Geom_Line(L);
257   GeomAdaptor_Curve LL(geomline);
258   Handle(GeomAdaptor_HCurve) HLL  = new GeomAdaptor_HCurve(LL);
259   Standard_Real parinf=ParMin;
260   Standard_Real parsup=ParMax;
261   //
262   if(PtrOnPolyhedron == NULL) { 
263     HICS.Perform(HLL,Hsurface);
264   }
265   else { 
266     Intf_Tool bndTool;
267     Bnd_Box   boxLine;
268     bndTool.LinBox
269       (L,
270        ((IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron)->Bounding(),
271        boxLine);
272     if(bndTool.NbSegments() == 0) 
273       return;
274     for(Standard_Integer nbseg=1; nbseg<= bndTool.NbSegments(); nbseg++) { 
275       Standard_Real pinf = bndTool.BeginParam(nbseg);
276       Standard_Real psup = bndTool.EndParam(nbseg);
277       Standard_Real pppp = 0.05*(psup-pinf);
278       pinf-=pppp;
279       psup+=pppp;
280       if((psup - pinf)<1e-10) { pinf-=1e-10; psup+=1e-10; } 
281       if(nbseg==1) { parinf=pinf; parsup=psup; }
282       else { 
283         if(parinf>pinf) parinf = pinf;
284         if(parsup<psup) parsup = psup;
285       }
286     }
287     if(parinf>ParMax) { return; } 
288     if(parsup<ParMin) { return; }
289     if(parinf<ParMin) parinf=ParMin;
290     if(parsup>ParMax) parsup=ParMax;
291     if(parinf>(parsup-1e-9)) return; 
292     IntCurveSurface_ThePolygonOfHInter polygon(HLL,
293                                                parinf,
294                                                parsup,
295                                                2);
296 #if OPTIMISATION
297     if(PtrOnBndBounding==NULL) { 
298       PtrOnBndBounding = (Bnd_BoundSortBox *) new Bnd_BoundSortBox();
299       IntCurveSurface_ThePolyhedronOfHInter *thePolyh=
300         (IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron;
301       ((Bnd_BoundSortBox *)(PtrOnBndBounding))->
302         Initialize(IntCurveSurface_ThePolyhedronToolOfHInter::Bounding(*thePolyh),
303                    IntCurveSurface_ThePolyhedronToolOfHInter::ComponentsBounding(*thePolyh));
304     }
305     HICS.Perform(HLL,
306                  polygon,
307                  Hsurface,
308                  *((IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron),
309                  *((Bnd_BoundSortBox *)PtrOnBndBounding));
310 #else
311     HICS.Perform(HLL,
312                  polygon,
313                  Hsurface,
314                  *((IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron));
315 #endif
316   }
317   
318   InternalCall(HICS,parinf,parsup);
319 }
320 //=======================================================================
321 //function : Perform
322 //purpose  : 
323 //=======================================================================
324 void IntCurvesFace_Intersector::Perform(const Handle(Adaptor3d_HCurve)& HCu,
325                                         const Standard_Real ParMin,
326                                         const Standard_Real ParMax) 
327
328   done = Standard_True;
329   SeqPnt.Clear();
330   //  Modified by skv - Wed Sep  3 16:14:10 2003 OCC578 Begin
331   mySeqState.Clear();
332   //  Modified by skv - Wed Sep  3 16:14:11 2003 OCC578 End
333   nbpnt = 0;
334   IntCurveSurface_HInter            HICS; 
335   
336   //-- 
337   Standard_Real parinf=ParMin;
338   Standard_Real parsup=ParMax;
339
340   if(PtrOnPolyhedron == NULL) { 
341     HICS.Perform(HCu,Hsurface);
342   }
343   else { 
344     parinf = IntCurveSurface_TheHCurveTool::FirstParameter(HCu);
345     parsup = IntCurveSurface_TheHCurveTool::LastParameter(HCu);
346     if(parinf<ParMin) parinf = ParMin;
347     if(parsup>ParMax) parsup = ParMax;
348     if(parinf>(parsup-1e-9)) return; 
349     Standard_Integer nbs;
350     nbs = IntCurveSurface_TheHCurveTool::NbSamples(HCu,parinf,parsup);
351     
352     IntCurveSurface_ThePolygonOfHInter polygon(HCu,
353                                                parinf,
354                                                parsup,
355                                                nbs);
356 #if OPTIMISATION
357     if(PtrOnBndBounding==NULL) { 
358       PtrOnBndBounding = (Bnd_BoundSortBox *) new Bnd_BoundSortBox();
359       IntCurveSurface_ThePolyhedronOfHInter *thePolyh=(IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron;
360       ((Bnd_BoundSortBox *)(PtrOnBndBounding))->Initialize(IntCurveSurface_ThePolyhedronToolOfHInter::Bounding(*thePolyh),
361                                                            IntCurveSurface_ThePolyhedronToolOfHInter::ComponentsBounding(*thePolyh));
362     }
363     HICS.Perform(HCu,
364                  polygon,
365                  Hsurface,
366                  *((IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron),
367                  *((Bnd_BoundSortBox *)PtrOnBndBounding));
368 #else
369     HICS.Perform(HCu,
370                  polygon,
371                  Hsurface,
372                  *((IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron));
373 #endif
374   }
375   InternalCall(HICS,parinf,parsup);
376 }
377
378 //============================================================================
379 Bnd_Box IntCurvesFace_Intersector::Bounding() const {
380   if(PtrOnPolyhedron !=NULL) {
381     return(((IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron)->Bounding());
382   }
383   else { 
384     Bnd_Box B;
385     return(B);
386   }
387 }
388 TopAbs_State IntCurvesFace_Intersector::ClassifyUVPoint(const gp_Pnt2d& Puv) const { 
389   TopAbs_State state = myTopolTool->Classify(Puv,1e-7);
390   return(state);
391 }
392 //============================================================================
393 void IntCurvesFace_Intersector::Destroy() { 
394   if(PtrOnPolyhedron !=NULL) { 
395     delete (IntCurveSurface_ThePolyhedronOfHInter *)PtrOnPolyhedron;
396     PtrOnPolyhedron = NULL;
397   }
398   if(PtrOnBndBounding !=NULL) { 
399     delete (Bnd_BoundSortBox *)PtrOnBndBounding;
400     PtrOnBndBounding=NULL;
401   }
402 }
403
404  void IntCurvesFace_Intersector::SetUseBoundToler(Standard_Boolean UseBToler)
405  {
406    myUseBoundTol = UseBToler;
407  }
408
409  Standard_Boolean IntCurvesFace_Intersector::GetUseBoundToler() const
410  {
411    return myUseBoundTol;
412  }
413