0b608df55c1846436cb086b7b5e6274faee6e68d
[occt.git] / src / BRepTopAdaptor / BRepTopAdaptor_TopolTool.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Adaptor2d_HCurve2d.hxx>
17 #include <Adaptor3d_HSurface.hxx>
18 #include <Adaptor3d_HVertex.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_HCurve2d.hxx>
21 #include <BRepAdaptor_HSurface.hxx>
22 #include <BRepClass_FaceClassifier.hxx>
23 #include <BRepClass_FaceExplorer.hxx>
24 #include <BRepTopAdaptor_FClass2d.hxx>
25 #include <BRepTopAdaptor_HVertex.hxx>
26 #include <BRepTopAdaptor_TopolTool.hxx>
27 #include <Geom_BezierSurface.hxx>
28 #include <Geom_BSplineSurface.hxx>
29 #include <gp_Pnt.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <Precision.hxx>
32 #include <Standard_ConstructionError.hxx>
33 #include <Standard_DomainError.hxx>
34 #include <Standard_NotImplemented.hxx>
35 #include <Standard_Type.hxx>
36 #include <TColgp_Array2OfPnt.hxx>
37 #include <TopoDS.hxx>
38
39 IMPLEMENT_STANDARD_RTTIEXT(BRepTopAdaptor_TopolTool,Adaptor3d_TopolTool)
40
41 static 
42   void Analyse(const TColgp_Array2OfPnt& array2,
43                const Standard_Integer nbup,
44                const Standard_Integer nbvp,
45                Standard_Integer& myNbSamplesU,
46                Standard_Integer& myNbSamplesV); 
47 //=======================================================================
48 //function : BRepTopAdaptor_TopolTool
49 //purpose  : 
50 //=======================================================================
51   BRepTopAdaptor_TopolTool::BRepTopAdaptor_TopolTool () : myFClass2d(NULL)
52 {
53   myNbSamplesU=-1;
54 }
55
56 //=======================================================================
57 //function : BRepTopAdaptor_TopolTool
58 //purpose  : 
59 //=======================================================================
60   BRepTopAdaptor_TopolTool::BRepTopAdaptor_TopolTool(const Handle(Adaptor3d_HSurface)& S) 
61 : myFClass2d(NULL)
62 {
63   Initialize(S);
64   //myS = S;
65 }
66 //=======================================================================
67 //function : Initialize
68 //purpose  : 
69 //=======================================================================
70   void BRepTopAdaptor_TopolTool::Initialize()
71 {
72   throw Standard_NotImplemented("BRepTopAdaptor_TopolTool::Initialize()");
73 }
74 //=======================================================================
75 //function : Initialize
76 //purpose  : 
77 //=======================================================================
78   void BRepTopAdaptor_TopolTool::Initialize(const Handle(Adaptor3d_HSurface)& S)
79 {
80   Handle(BRepAdaptor_HSurface) brhs = 
81     Handle(BRepAdaptor_HSurface)::DownCast(S);
82   if (brhs.IsNull()) {throw Standard_ConstructionError();}
83   TopoDS_Shape s_wnt = ((BRepAdaptor_Surface *)&(brhs->Surface()))->Face();
84   s_wnt.Orientation(TopAbs_FORWARD);
85   myFace = TopoDS::Face(s_wnt);
86   if(myFClass2d != NULL) { 
87     delete (BRepTopAdaptor_FClass2d *)myFClass2d;
88   } 
89   myFClass2d = NULL;
90   myNbSamplesU=-1;
91   myS = S;
92   myCurves.Clear();
93   TopExp_Explorer ex(myFace,TopAbs_EDGE);
94   for (; ex.More(); ex.Next()) {
95     Handle(BRepAdaptor_HCurve2d) aCurve = new BRepAdaptor_HCurve2d
96       (BRepAdaptor_Curve2d(TopoDS::Edge(ex.Current()),myFace));
97     myCurves.Append(aCurve);
98   }
99   myCIterator = TColStd_ListIteratorOfListOfTransient();
100 }
101 //=======================================================================
102 //function : Initialize
103 //purpose  : 
104 //=======================================================================
105   void BRepTopAdaptor_TopolTool::Initialize(const Handle(Adaptor2d_HCurve2d)& C)
106 {
107   myCurve = Handle(BRepAdaptor_HCurve2d)::DownCast(C);
108   if (myCurve.IsNull()) {throw Standard_ConstructionError();}
109 }
110 //=======================================================================
111 //function : Init
112 //purpose  : 
113 //=======================================================================
114   void BRepTopAdaptor_TopolTool::Init ()
115 {
116   myCIterator.Initialize(myCurves);
117 }
118 //=======================================================================
119 //function : More
120 //purpose  : 
121 //=======================================================================
122   Standard_Boolean BRepTopAdaptor_TopolTool::More ()
123 {
124   return myCIterator.More();
125 }
126 //=======================================================================
127 //function : Next
128 //purpose  : 
129 //=======================================================================
130   void BRepTopAdaptor_TopolTool::Next()
131 {
132   myCIterator.Next();
133 }
134 //=======================================================================
135 //function : Value
136 //purpose  : 
137 //=======================================================================
138   Handle(Adaptor2d_HCurve2d) BRepTopAdaptor_TopolTool::Value ()
139 {
140   return Handle(Adaptor2d_HCurve2d)::DownCast(myCIterator.Value());
141 }
142 //modified by NIZNHY-PKV Tue Mar 27 14:23:40 2001 f
143 //=======================================================================
144 //function : Edge
145 //purpose  : 
146 //=======================================================================
147   Standard_Address BRepTopAdaptor_TopolTool::Edge () const
148 {
149   Handle(BRepAdaptor_HCurve2d) aHCurve =
150     Handle(BRepAdaptor_HCurve2d)::DownCast(myCIterator.Value());
151   const BRepAdaptor_Curve2d& aCurve = (const BRepAdaptor_Curve2d&)aHCurve->Curve2d();
152   return Standard_Address (& aCurve.Edge());
153 }
154
155 //modified by NIZNHY-PKV Tue Mar 27 14:23:43 2001 t
156 //=======================================================================
157 //function : InitVertexIterator
158 //purpose  : 
159 //=======================================================================
160   void BRepTopAdaptor_TopolTool::InitVertexIterator ()
161 {
162   myVIterator.Init(((BRepAdaptor_Curve2d *)&(myCurve->Curve2d()))->Edge(),TopAbs_VERTEX);
163 }
164 //=======================================================================
165 //function : NextVertex
166 //purpose  : 
167 //=======================================================================
168   Standard_Boolean BRepTopAdaptor_TopolTool::MoreVertex ()
169 {
170   return myVIterator.More();
171 }
172
173   void BRepTopAdaptor_TopolTool::NextVertex ()
174 {
175   myVIterator.Next();
176 }
177 //=======================================================================
178 //function : Vertex
179 //purpose  : 
180 //=======================================================================
181   Handle(Adaptor3d_HVertex) BRepTopAdaptor_TopolTool::Vertex ()
182 {
183   return new 
184     BRepTopAdaptor_HVertex(TopoDS::Vertex(myVIterator.Current()),myCurve);
185 }
186   
187 //=======================================================================
188 //function : Classify
189 //purpose  : 
190 //=======================================================================
191   TopAbs_State BRepTopAdaptor_TopolTool::Classify(const gp_Pnt2d& P,
192                                                   const Standard_Real Tol,
193                                                   const Standard_Boolean RecadreOnPeriodic)
194 {
195   if(myFace.IsNull())
196     return TopAbs_UNKNOWN;
197   if(myFClass2d == NULL) { 
198     myFClass2d = (void *) new BRepTopAdaptor_FClass2d(myFace,Tol);
199   } 
200   return(((BRepTopAdaptor_FClass2d *)myFClass2d)->Perform(P,RecadreOnPeriodic));
201 }
202
203 //=======================================================================
204 //function : IsThePointOn
205 //purpose  : 
206 //=======================================================================
207   Standard_Boolean BRepTopAdaptor_TopolTool::IsThePointOn(const gp_Pnt2d& P,
208                                                           const Standard_Real Tol,
209                                                           const Standard_Boolean RecadreOnPeriodic)
210 {
211   if(myFClass2d == NULL) { 
212     myFClass2d = (void *) new BRepTopAdaptor_FClass2d(myFace,Tol);
213   } 
214   return(TopAbs_ON==((BRepTopAdaptor_FClass2d *)myFClass2d)->TestOnRestriction(P,Tol,RecadreOnPeriodic));
215 }
216
217 //=======================================================================
218 //function : Destroy
219 //purpose  : 
220 //=======================================================================
221   void BRepTopAdaptor_TopolTool::Destroy() 
222
223   if(myFClass2d != NULL) { 
224     delete (BRepTopAdaptor_FClass2d *)myFClass2d;
225     myFClass2d=NULL;
226   }
227 }
228 //=======================================================================
229 //function : Orientation
230 //purpose  : 
231 //=======================================================================
232   TopAbs_Orientation BRepTopAdaptor_TopolTool::Orientation  (const Handle(Adaptor2d_HCurve2d)& C)
233 {
234   Handle(BRepAdaptor_HCurve2d) brhc =
235     Handle(BRepAdaptor_HCurve2d)::DownCast(C);
236   return ((BRepAdaptor_Curve2d *)&(brhc->Curve2d()))->Edge().Orientation(); 
237 }
238 //=======================================================================
239 //function : Orientation
240 //purpose  : 
241 //=======================================================================
242   TopAbs_Orientation BRepTopAdaptor_TopolTool::Orientation  (const Handle(Adaptor3d_HVertex)& C)
243 {
244  return Adaptor3d_TopolTool::Orientation(C); 
245 }
246 //-- ============================================================
247 //-- methods  used for samples
248 //-- ============================================================ 
249
250 //=======================================================================
251 //function : Analyse
252 //purpose  : 
253 //=======================================================================
254 void Analyse(const TColgp_Array2OfPnt& array2,
255              const Standard_Integer nbup,
256              const Standard_Integer nbvp,
257              Standard_Integer& myNbSamplesU,
258              Standard_Integer& myNbSamplesV) 
259
260   gp_Vec Vi,Vip1;
261   Standard_Integer sh,nbch,i,j;
262   
263   sh = 1;
264   nbch = 0;
265   if(nbvp>2) { 
266     for(i=2;i<nbup;i++) { 
267       const gp_Pnt& A=array2.Value(i,1);
268       const gp_Pnt& B=array2.Value(i,2);
269       const gp_Pnt& C=array2.Value(i,3);
270       Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
271                   C.Y()-B.Y()-B.Y()+A.Y(),
272                   C.Z()-B.Z()-B.Z()+A.Z());
273       Standard_Integer locnbch=0;
274       for(j=3; j<nbvp;j++) {  //-- test
275         const gp_Pnt& Ax=array2.Value(i,j-1);
276         const gp_Pnt& Bx=array2.Value(i,j);
277         const gp_Pnt& Cx=array2.Value(i,j+1);
278         Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
279                       Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
280                       Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
281         Standard_Real pd = Vi.Dot(Vip1);
282         Vi=Vip1;
283         if(pd>1.0e-7 || pd<-1.0e-7) {  
284           if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
285           else {        if(sh==1) {  sh=-1; locnbch++;  }  }
286         }
287       }
288       if(locnbch>nbch) { 
289         nbch=locnbch; 
290       }
291     }
292   }
293   myNbSamplesV = nbch+5;
294   
295
296   nbch=0;
297   if(nbup>2) { 
298     for(j=2;j<nbvp;j++) { 
299       const gp_Pnt& A=array2.Value(1,j);
300       const gp_Pnt& B=array2.Value(2,j);
301       const gp_Pnt& C=array2.Value(3,j);
302       Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
303                   C.Y()-B.Y()-B.Y()+A.Y(),
304                   C.Z()-B.Z()-B.Z()+A.Z());
305       Standard_Integer locnbch=0;
306       for(i=3; i<nbup;i++) {  //-- test
307         const gp_Pnt& Ax=array2.Value(i-1,j);
308         const gp_Pnt& Bx=array2.Value(i,j);
309         const gp_Pnt& Cx=array2.Value(i+1,j);
310         Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
311                     Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
312                     Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
313         Standard_Real pd = Vi.Dot(Vip1);
314         Vi=Vip1;
315         if(pd>1.0e-7 || pd<-1.0e-7) {  
316           if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
317           else {        if(sh==1) {  sh=-1; locnbch++;  }  }
318         }
319       }
320       if(locnbch>nbch) nbch=locnbch;
321     }  
322   }
323   myNbSamplesU = nbch+5;
324 }  
325
326
327
328
329 //=======================================================================
330 //function : ComputeSamplePoints
331 //purpose  : 
332 //=======================================================================
333   void BRepTopAdaptor_TopolTool::ComputeSamplePoints() 
334
335   Standard_Real uinf,usup,vinf,vsup;
336   uinf = myS->FirstUParameter();  usup = myS->LastUParameter();
337   vinf = myS->FirstVParameter();  vsup = myS->LastVParameter();
338   if (usup < uinf) { Standard_Real temp=uinf; uinf=usup; usup=temp; }
339   if (vsup < vinf) { Standard_Real temp=vinf; vinf=vsup; vsup=temp; }
340   if (uinf == RealFirst() && usup == RealLast()) { uinf=-1.e5; usup=1.e5; }
341   else if (uinf == RealFirst()) { uinf=usup-2.e5; }
342   else if (usup == RealLast()) {  usup=uinf+2.e5; }
343   
344   if (vinf == RealFirst() && vsup == RealLast()) { vinf=-1.e5; vsup=1.e5; }
345   else if (vinf == RealFirst()) { vinf=vsup-2.e5;  }
346   else if (vsup == RealLast()) {  vsup=vinf+2.e5;  }
347   
348   Standard_Integer nbsu,nbsv;
349   GeomAbs_SurfaceType typS = myS->GetType();
350   switch(typS) { 
351   case GeomAbs_Plane:          { nbsv=2; nbsu=2; } break;
352   case GeomAbs_BezierSurface:  { nbsv=3+myS->NbVPoles(); nbsu=3+myS->NbUPoles();  } break;
353   case GeomAbs_BSplineSurface: {
354     nbsv = myS->NbVKnots();     nbsv*= myS->VDegree();     if(nbsv < 4) nbsv=4;    
355     nbsu = myS->NbUKnots();     nbsu*= myS->UDegree();     if(nbsu < 4) nbsu=4;
356   }
357     break;
358   case GeomAbs_Cylinder:
359   case GeomAbs_Cone:
360   case GeomAbs_Sphere:
361   case GeomAbs_Torus:                 { 
362     //-- Set 15 for 2pi
363     //-- Not enough ->25 for 2pi
364     nbsu = (Standard_Integer)(8*(usup-uinf));
365     nbsv = (Standard_Integer)(7*(vsup-vinf));
366     if(nbsu<5) nbsu=5;
367     if(nbsv<5) nbsv=5;
368     if(nbsu>30) nbsu=30; //modif HRT buc60462
369     if(nbsv>15) nbsv=15;
370     //-- printf("\n nbsu=%d nbsv=%d\n",nbsu,nbsv);
371   }     break;
372   case GeomAbs_SurfaceOfRevolution:
373   case GeomAbs_SurfaceOfExtrusion:    { nbsv = 15; nbsu=25; }     break;
374   default:                            { nbsu = 10; nbsv=10; }    break;
375   }
376   
377   //-- If the number of points is too great, analyze 
378   //-- 
379   //-- 
380   
381   if(nbsu<10) nbsu=10;
382   if(nbsv<10) nbsv=10;
383   
384   myNbSamplesU = nbsu;
385   myNbSamplesV = nbsv;
386   
387   //-- printf("\n BRepTopAdaptor_TopolTool NbSu=%d NbSv=%d ",nbsu,nbsv);
388   if(nbsu>10 || nbsv>10) { 
389     if(typS == GeomAbs_BSplineSurface) { 
390       const Handle(Geom_BSplineSurface)& Bspl = myS->BSpline();
391       Standard_Integer nbup = Bspl->NbUPoles();
392       Standard_Integer nbvp = Bspl->NbVPoles();
393       TColgp_Array2OfPnt array2(1,nbup,1,nbvp);
394       Bspl->Poles(array2);
395       Analyse(array2,nbup,nbvp,myNbSamplesU,myNbSamplesV);
396       nbsu=myNbSamplesU;
397       nbsv=myNbSamplesV;
398       //-- printf("\n Apres analyse BSPline  NbSu=%d NbSv=%d ",myNbSamplesU,myNbSamplesV);
399     }
400     else if(typS == GeomAbs_BezierSurface) { 
401       const Handle(Geom_BezierSurface)& Bez = myS->Bezier();
402       Standard_Integer nbup = Bez->NbUPoles();
403       Standard_Integer nbvp = Bez->NbVPoles();
404       TColgp_Array2OfPnt array2(1,nbup,1,nbvp);
405       Bez->Poles(array2);
406       Analyse(array2,nbup,nbvp,myNbSamplesU,myNbSamplesV);
407       nbsu=myNbSamplesU;
408       nbsv=myNbSamplesV;
409       //-- printf("\n Apres analyse Bezier  NbSu=%d NbSv=%d ",myNbSamplesU,myNbSamplesV);
410     }
411   }
412  
413   if(nbsu<10) nbsu=10;
414   if(nbsv<10) nbsv=10;
415   
416   myNbSamplesU = nbsu;
417   myNbSamplesV = nbsv; 
418   
419   myU0 = uinf;
420   myV0 = vinf;
421   
422   myDU = (usup-uinf)/(myNbSamplesU+1);
423   myDV = (vsup-vinf)/(myNbSamplesV+1);
424 }
425 //=======================================================================
426 //function : NbSamplesU
427 //purpose  : 
428 //=======================================================================
429   Standard_Integer BRepTopAdaptor_TopolTool::NbSamplesU() 
430
431   if(myNbSamplesU <0) { 
432     ComputeSamplePoints();
433   }
434   return(myNbSamplesU);
435 }
436 //=======================================================================
437 //function : NbSamplesV
438 //purpose  : 
439 //=======================================================================
440   Standard_Integer BRepTopAdaptor_TopolTool::NbSamplesV() 
441
442   if(myNbSamplesU <0) { 
443     ComputeSamplePoints();    
444   }
445   return(myNbSamplesV);
446 }
447 //=======================================================================
448 //function : NbSamples
449 //purpose  : 
450 //=======================================================================
451   Standard_Integer BRepTopAdaptor_TopolTool::NbSamples()
452
453   if(myNbSamplesU <0) { 
454     ComputeSamplePoints();    
455   }
456   return(myNbSamplesU*myNbSamplesV);
457 }
458
459 //=======================================================================
460 //function : SamplePoint
461 //purpose  : 
462 //=======================================================================
463   void BRepTopAdaptor_TopolTool::SamplePoint(const Standard_Integer i,
464                                              gp_Pnt2d& P2d,
465                                              gp_Pnt& P3d)
466
467   Standard_Integer iv = 1 + i/myNbSamplesU;
468   Standard_Integer iu = 1+ i-(iv-1)*myNbSamplesU;
469   Standard_Real u=myU0+iu*myDU;
470   Standard_Real v=myV0+iv*myDV;
471   P2d.SetCoord(u,v);
472   P3d=myS->Value(u,v);
473 }
474 //=======================================================================
475 //function : DomainIsInfinite
476 //purpose  : 
477 //=======================================================================
478   Standard_Boolean BRepTopAdaptor_TopolTool::DomainIsInfinite() 
479 {
480   Standard_Real uinf,usup,vinf,vsup;
481   uinf = myS->FirstUParameter();  usup = myS->LastUParameter();
482   vinf = myS->FirstVParameter();  vsup = myS->LastVParameter();
483   if(Precision::IsNegativeInfinite(uinf)) return(Standard_True);
484   if(Precision::IsPositiveInfinite(usup)) return(Standard_True);
485   if(Precision::IsNegativeInfinite(vinf)) return(Standard_True);
486   if(Precision::IsPositiveInfinite(vsup)) return(Standard_True);
487   return(Standard_False);  
488 }
489
490 //=======================================================================
491 //function : Has3d
492 //purpose  : 
493 //=======================================================================
494
495 Standard_Boolean BRepTopAdaptor_TopolTool::Has3d() const
496 {
497   return Standard_True;
498 }
499
500 //=======================================================================
501 //function : Tol3d
502 //purpose  : 
503 //=======================================================================
504
505 Standard_Real BRepTopAdaptor_TopolTool::Tol3d(const Handle(Adaptor2d_HCurve2d)& C) const
506 {
507   Handle(BRepAdaptor_HCurve2d) brhc = Handle(BRepAdaptor_HCurve2d)::DownCast(C);
508   if (brhc.IsNull())
509     throw Standard_DomainError("BRepTopAdaptor_TopolTool: arc has no 3d representation");
510   const BRepAdaptor_Curve2d& brc = (const BRepAdaptor_Curve2d &)brhc->Curve2d();
511   const TopoDS_Edge& edge = brc.Edge();
512   if (edge.IsNull())
513     throw Standard_DomainError("BRepTopAdaptor_TopolTool: arc has no 3d representation");
514   return BRep_Tool::Tolerance(edge);
515 }
516
517 //=======================================================================
518 //function : Tol3d
519 //purpose  : 
520 //=======================================================================
521
522 Standard_Real BRepTopAdaptor_TopolTool::Tol3d(const Handle(Adaptor3d_HVertex)& V) const
523 {
524   Handle(BRepTopAdaptor_HVertex) brhv = Handle(BRepTopAdaptor_HVertex)::DownCast(V);
525   if (brhv.IsNull())
526     throw Standard_DomainError("BRepTopAdaptor_TopolTool: vertex has no 3d representation");
527   const TopoDS_Vertex& ver = brhv->Vertex();
528   if (ver.IsNull())
529     throw Standard_DomainError("BRepTopAdaptor_TopolTool: vertex has no 3d representation");
530   return BRep_Tool::Tolerance(ver);
531 }
532
533 //=======================================================================
534 //function : Pnt
535 //purpose  : 
536 //=======================================================================
537
538 gp_Pnt BRepTopAdaptor_TopolTool::Pnt(const Handle(Adaptor3d_HVertex)& V) const
539 {
540   Handle(BRepTopAdaptor_HVertex) brhv = Handle(BRepTopAdaptor_HVertex)::DownCast(V);
541   if (brhv.IsNull())
542     throw Standard_DomainError("BRepTopAdaptor_TopolTool: vertex has no 3d representation");
543   const TopoDS_Vertex& ver = brhv->Vertex();
544   if (ver.IsNull())
545     throw Standard_DomainError("BRepTopAdaptor_TopolTool: vertex has no 3d representation");
546   return BRep_Tool::Pnt(ver);
547 }