1 // Created on: 1995-03-22
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
24 #define No_Standard_OutOfRange
26 #include <BRepTopAdaptor_FClass2d.ixx>
28 #include <TopoDS_Edge.hxx>
30 #include <BRep_Tool.hxx>
31 #include <TopAbs_Orientation.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TColgp_SequenceOfPnt2d.hxx>
34 #include <BRepTools_WireExplorer.hxx>
35 #include <Geom2dInt_Geom2dCurveTool.hxx>
36 #include <BRepAdaptor_Curve2d.hxx>
37 #include <TColgp_Array1OfPnt2d.hxx>
38 #include <BRepClass_FaceClassifier.hxx>
39 #include <CSLib_Class2d.hxx>
40 #include <GeomAbs_SurfaceType.hxx>
41 #include <BRepAdaptor_HSurface.hxx>
43 #include <BRepAdaptor_Curve.hxx>
48 #include <Precision.hxx>
63 class StatistiquesFClass2d {
65 long unsigned NbConstrShape;
66 long unsigned NbPerformInfinitePoint;
67 long unsigned NbPerform;
68 long unsigned NbTestOnRestriction;
69 long unsigned NbDestroy;
71 StatistiquesFClass2d() {
72 NbConstrShape=NbPerform=NbPerformInfinitePoint=NbDestroy=0;
74 ~StatistiquesFClass2d() {
75 printf("\n--- Statistiques BRepTopAdaptor:\n");
76 printf("\nConstructeur(Shape) : %10lu",NbConstrShape);
77 printf("\nPerformInfinitePoint: %10lu",NbPerformInfinitePoint);
78 printf("\nTestOnRestriction : %10lu",NbTestOnRestriction);
79 printf("\nPerform(pnt2d) : %10lu",NbPerform);
80 printf("\nDestroy : %10lu",NbDestroy);
84 static StatistiquesFClass2d STAT;
90 BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const Standard_Real TolUV)
91 : Toluv(TolUV), Face(aFace) {
97 //-- dead end on surfaces defined on more than one period
99 Face.Orientation(TopAbs_FORWARD);
100 Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
101 surf->ChangeSurface().Initialize(aFace,Standard_False);
104 TopAbs_Orientation Or;
105 Standard_Real u,du,Tole = 0.0,Tol=0.0;
106 BRepTools_WireExplorer WireExplorer;
107 TopExp_Explorer FaceExplorer;
109 Umin = Vmin = 0.0; //RealLast();
112 Standard_Integer BadWire=0;
113 for( FaceExplorer.Init(Face,TopAbs_WIRE); (FaceExplorer.More() && BadWire==0); FaceExplorer.Next() )
115 Standard_Integer nbpnts = 0;
116 TColgp_SequenceOfPnt2d SeqPnt2d;
117 Standard_Integer firstpoint = 1;
118 Standard_Real FlecheU = 0.0;
119 Standard_Real FlecheV = 0.0;
120 Standard_Boolean WireIsNotEmpty = Standard_False;
121 Standard_Integer NbEdges = 0;
123 TopExp_Explorer Explorer;
124 for( Explorer.Init(FaceExplorer.Current(),TopAbs_EDGE); Explorer.More(); Explorer.Next() ) NbEdges++;
126 gp_Pnt Ancienpnt3d(0,0,0);
127 Standard_Boolean Ancienpnt3dinitialise = Standard_False;
129 for( WireExplorer.Init(TopoDS::Wire(FaceExplorer.Current()),Face); WireExplorer.More(); WireExplorer.Next() )
133 edge = WireExplorer.Current();
134 Or = edge.Orientation();
135 if(Or == TopAbs_FORWARD || Or == TopAbs_REVERSED)
137 Standard_Real pfbid,plbid;
138 if(BRep_Tool::CurveOnSurface(edge,Face,pfbid,plbid).IsNull()) return;
139 BRepAdaptor_Curve2d C(edge,Face);
141 //-- ----------------------------------------
142 Standard_Boolean degenerated=Standard_False;
143 if(BRep_Tool::Degenerated(edge)) degenerated=Standard_True;
144 if(BRep_Tool::IsClosed(edge,Face)) degenerated=Standard_True;
146 TopExp::Vertices(edge,Va,Vb);
147 Standard_Real TolVertex1=0.,TolVertex=0.;
148 if (Va.IsNull()) degenerated=Standard_True;
149 else TolVertex1=BRep_Tool::Tolerance(Va);
150 if (Vb.IsNull()) degenerated=Standard_True;
151 else TolVertex=BRep_Tool::Tolerance(Vb);
152 if(TolVertex<TolVertex1) TolVertex=TolVertex1;
153 BRepAdaptor_Curve C3d;
155 if(Abs(plbid-pfbid) < 1.e-9) continue;
157 //if(degenerated==Standard_False)
158 // C3d.Initialize(edge,Face);
160 //-- Check cases when it was forgotten to code degenerated : PRO17410 (janv 99)
161 if(degenerated == Standard_False)
163 C3d.Initialize(edge,Face);
164 du=(plbid-pfbid)*0.1;
166 gp_Pnt P3da=C3d.Value(u);
167 degenerated=Standard_True;
172 gp_Pnt P3db=C3d.Value(u);
173 // if(P3da.SquareDistance(P3db)) { degenerated=Standard_False; break; }
174 if(P3da.SquareDistance(P3db) > Precision::Confusion()) { degenerated=Standard_False; break; }
180 //-- ----------------------------------------
182 Tole = BRep_Tool::Tolerance(edge);
183 if(Tole>Tol) Tol=Tole;
185 //Standard_Integer nbs = 1 + Geom2dInt_Geom2dCurveTool::NbSamples(C);
186 Standard_Integer nbs = Geom2dInt_Geom2dCurveTool::NbSamples(C);
187 //-- Attention to rational bsplines of degree 3. (ends of circles among others)
189 du = (plbid-pfbid)/(Standard_Real)(nbs-1);
191 if(Or==TopAbs_FORWARD) u = pfbid;
192 else { u = plbid; du=-du; }
194 //-- ------------------------------------------------------------
195 //-- Check distance uv between the start point of the edge
196 //-- and the last point registered in SeqPnt2d
197 //-- Try to remote the first point of the current edge
198 //-- from the last saved point
200 gp_Pnt2d Pnt2dDebutEdgeCourant=
204 //Standard_Real Baillement2dU=0;
205 //Standard_Real Baillement2dV=0;
207 if(nbpnts>1) printf("\nTolVertex %g ",TolVertex);
210 if(firstpoint==2) u+=du;
211 Standard_Integer Avant = nbpnts;
212 for(Standard_Integer e = firstpoint; e<=nbs; e++)
214 gp_Pnt2d P2d = C.Value(u);
215 if(P2d.X()<Umin) Umin = P2d.X();
216 if(P2d.X()>Umax) Umax = P2d.X();
217 if(P2d.Y()<Vmin) Vmin = P2d.Y();
218 if(P2d.Y()>Vmax) Vmax = P2d.Y();
220 Standard_Real dist3dptcourant_ancienpnt=1e+20;//RealLast();
222 if(degenerated==Standard_False)
225 if(nbpnts>1 && Ancienpnt3dinitialise) dist3dptcourant_ancienpnt = P3d.Distance(Ancienpnt3d);
227 Standard_Boolean IsRealCurve3d = Standard_True; //patch
228 if(dist3dptcourant_ancienpnt < Precision::Confusion())
230 gp_Pnt MidP3d = C3d.Value( u-du/2. );
231 if (P3d.Distance( MidP3d ) < Precision::Confusion()) IsRealCurve3d = Standard_False;
235 if(degenerated==Standard_False) { Ancienpnt3d=P3d; Ancienpnt3dinitialise=Standard_True; }
237 SeqPnt2d.Append(P2d);
240 else { static int mm=0; printf("\npoint p%d %g %g %g",++mm,P3d.X(),P3d.Y(),P3d.Z()); }
243 Standard_Integer ii = nbpnts;
244 //-- printf("\n nbpnts:%4d u=%7.5g FlecheU=%7.5g FlecheV=%7.5g ii=%3d Avant=%3d ",nbpnts,u,FlecheU,FlecheV,ii,Avant);
246 // Modified by Sergey KHROMOV - Fri Apr 19 09:46:12 2002 Begin
247 if(ii>(Avant+4) && SeqPnt2d(ii-2).SquareDistance(SeqPnt2d(ii)))
248 // Modified by Sergey KHROMOV - Fri Apr 19 09:46:13 2002 End
250 gp_Lin2d Lin(SeqPnt2d(ii-2),gp_Dir2d(gp_Vec2d(SeqPnt2d(ii-2),SeqPnt2d(ii))));
251 Standard_Real ul = ElCLib::Parameter(Lin,SeqPnt2d(ii-1));
252 gp_Pnt2d Pp = ElCLib::Value(ul,Lin);
253 Standard_Real dU = Abs(Pp.X()-SeqPnt2d(ii-1).X());
254 Standard_Real dV = Abs(Pp.Y()-SeqPnt2d(ii-1).Y());
255 //-- printf(" (du=%7.5g dv=%7.5g)",dU,dV);
256 if(dU>FlecheU) FlecheU = dU;
257 if(dV>FlecheV) FlecheV = dV;
260 if(firstpoint==1) firstpoint=2;
261 WireIsNotEmpty = Standard_True;
262 }//if(Or==FORWARD,REVERSED
263 } //-- Edges -> for(Ware.Explorer
266 { //-- on compte ++ with a normal explorer and with the Wire Explorer
271 cout << "*** BRepTopAdaptor_Fclass2d ** Wire Probablement FAUX **" << endl;
272 cout << "*** WireExplorer does not find all edges " << endl;
273 cout << "*** Connect old classifier" << endl;
276 TColgp_Array1OfPnt2d PClass(1,2);
277 //// modified by jgv, 28.04.2009 ////
278 PClass.Init(gp_Pnt2d(0.,0.));
279 /////////////////////////////////////
280 TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
284 else if(WireIsNotEmpty)
286 //Standard_Real anglep=0,anglem=0;
287 TColgp_Array1OfPnt2d PClass(1,nbpnts);
288 Standard_Real square = 0.0;
290 //-------------------------------------------------------------------
291 //-- ** The mode of calculation was somewhat changed
292 //-- Before Oct 31 97 , the total angle of
293 //-- rotation of the wire was evaluated on all angles except for the last
294 //-- ** Now, exactly the angle of rotation is evaluated
295 //-- If a value remote from 2PI or -2PI is found, it means that there is
296 //-- an uneven number of loops
300 // Standard_Integer im2=nbpnts-2;
301 Standard_Integer im1=nbpnts-1;
302 Standard_Integer im0=1;
303 // PClass(im2)=SeqPnt2d.Value(im2);
304 PClass(im1)=SeqPnt2d.Value(im1);
305 PClass(nbpnts)=SeqPnt2d.Value(nbpnts);
308 // for(Standard_Integer ii=1; ii<nbpnts; ii++,im0++,im1++,im2++)
309 for(Standard_Integer ii=1; ii<nbpnts; ii++,im0++,im1++)
311 // if(im2>=nbpnts) im2=1;
312 if(im1>=nbpnts) im1=1;
313 PClass(ii)=SeqPnt2d.Value(ii);
314 // gp_Vec2d A(PClass(im2),PClass(im1));
315 // gp_Vec2d B(PClass(im1),PClass(im0));
316 // Standard_Real N = A.Magnitude() * B.Magnitude();
318 square += (PClass(im0).X()-PClass(im1).X())*(PClass(im0).Y()+PClass(im1).Y())*.5;
320 // if(N>1e-16){ Standard_Real a=A.Angle(B); angle+=a; }
326 if(FlecheU<Toluv) FlecheU = Toluv;
327 if(FlecheV<Toluv) FlecheV = Toluv;
328 //-- cout<<" U:"<<FlecheU<<" V:"<<FlecheV<<endl;
329 TabClass.Append((void *)new CSLib_Class2d(PClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
331 // if((angle<2 && angle>-2)||(angle>10)||(angle<-10))
334 // TabOrien.Append(-1);
337 // cout << "*** BRepTopAdaptor_Fclass2d ** Wire Probably FALSE **" << endl;
338 // cout << "*** Total rotation angle of the wire : " << angle << endl;
339 // cout << "*** Connect the old classifier" << endl;
342 // else TabOrien.Append(((angle>0.0)? 1 : 0));
343 TabOrien.Append(((square < 0.0)? 1 : 0));
349 cout << "*** BRepTopAdaptor_Fclass2d ** Wire Probably FALSE **" << endl;
350 cout << "*** The sample wire contains less than 3 points" << endl;
351 cout << "*** Connect the old classifier" << endl;
355 TColgp_Array1OfPnt2d xPClass(1,2);
356 xPClass(1) = SeqPnt2d(1);
357 xPClass(2) = SeqPnt2d(2);
358 TabClass.Append((void *)new CSLib_Class2d(xPClass,FlecheU,FlecheV,Umin,Vmin,Umax,Vmax));
360 }//else if(WareIsNotEmpty
363 Standard_Integer nbtabclass = TabClass.Length();
367 //-- If an error was detected on a wire: set all TabOrien to -1
368 if(BadWire) TabOrien(1)=-1;
370 if( surf->GetType()==GeomAbs_Cone
371 || surf->GetType()==GeomAbs_Cylinder
372 || surf->GetType()==GeomAbs_Torus
373 || surf->GetType()==GeomAbs_Sphere
374 || surf->GetType()==GeomAbs_SurfaceOfRevolution)
377 Standard_Real uuu=M_PI+M_PI-(Umax-Umin);
379 U1 = 0.0; // modified by NIZHNY-OFV Thu May 31 14:24:10 2001 ---> //Umin-uuu*0.5;
380 U2 = 2*M_PI; // modified by NIZHNY-OFV Thu May 31 14:24:35 2001 ---> //U1+M_PI+M_PI;
384 if(surf->GetType()==GeomAbs_Torus)
386 Standard_Real uuu=M_PI+M_PI-(Vmax-Vmin);
388 V1 = 0.0; // modified by NIZHNY-OFV Thu May 31 14:24:55 2001 ---> //Vmin-uuu*0.5;
389 V2 = 2*M_PI; // modified by NIZHNY-OFV Thu May 31 14:24:59 2001 ---> //V1+M_PI+M_PI;
395 TopAbs_State BRepTopAdaptor_FClass2d::PerformInfinitePoint() const {
397 STAT.NbPerformInfinitePoint++;
400 if(Umax==-RealLast() || Vmax==-RealLast() || Umin==RealLast() || Vmin==RealLast()) {
403 gp_Pnt2d P(Umin-(Umax-Umin),Vmin-(Vmax-Vmin));
404 return(Perform(P,Standard_False));
407 TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv,
408 const Standard_Boolean RecadreOnPeriodic) const
414 Standard_Integer dedans;
415 Standard_Integer nbtabclass = TabClass.Length();
421 //-- U1 is the First Param and U2 in this case is U1+Period
422 Standard_Real u=_Puv.X();
423 Standard_Real v=_Puv.Y();
424 Standard_Real uu = u, vv = v;
426 Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
427 surf->ChangeSurface().Initialize( Face, Standard_False );
428 const Standard_Boolean IsUPer = surf->IsUPeriodic();
429 const Standard_Boolean IsVPer = surf->IsVPeriodic();
430 const Standard_Real uperiod = IsUPer ? surf->UPeriod() : 0.0;
431 const Standard_Real vperiod = IsVPer ? surf->VPeriod() : 0.0;
432 TopAbs_State Status = TopAbs_UNKNOWN;
433 Standard_Boolean urecadre = Standard_False, vrecadre = Standard_False;
435 if (RecadreOnPeriodic)
468 if(TabOrien(1)!=-1) {
469 for(Standard_Integer n=1; n<=nbtabclass; n++) {
470 Standard_Integer cur = ((CSLib_Class2d *)TabClass(n))->SiDans(Puv);
489 BRepClass_FaceClassifier aClassifier;
490 Standard_Real m_Toluv = (Toluv > 4.0) ? 4.0 : Toluv;
491 //aClassifier.Perform(Face,Puv,Toluv);
492 aClassifier.Perform(Face,Puv,m_Toluv);
493 Status = aClassifier.State();
502 else { //-- TabOrien(1)=-1 False Wire
503 BRepClass_FaceClassifier aClassifier;
504 aClassifier.Perform(Face,Puv,Toluv);
505 Status = aClassifier.State();
508 if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
510 if (Status == TopAbs_IN || Status == TopAbs_ON)
516 urecadre = Standard_True;
521 if (u > Umax || !IsUPer)
526 vrecadre = Standard_True;
534 if (v > Vmax || !IsVPer)
540 TopAbs_State BRepTopAdaptor_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv,
541 const Standard_Real Tol,
542 const Standard_Boolean RecadreOnPeriodic) const
545 STAT.NbConstrShape++;
548 Standard_Integer dedans;
549 Standard_Integer nbtabclass = TabClass.Length();
555 //-- U1 is the First Param and U2 in this case is U1+Period
556 Standard_Real u=_Puv.X();
557 Standard_Real v=_Puv.Y();
558 Standard_Real uu = u, vv = v;
560 Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
561 surf->ChangeSurface().Initialize( Face, Standard_False );
562 const Standard_Boolean IsUPer = surf->IsUPeriodic();
563 const Standard_Boolean IsVPer = surf->IsVPeriodic();
564 const Standard_Real uperiod = IsUPer ? surf->UPeriod() : 0.0;
565 const Standard_Real vperiod = IsVPer ? surf->VPeriod() : 0.0;
566 TopAbs_State Status = TopAbs_UNKNOWN;
567 Standard_Boolean urecadre = Standard_False, vrecadre = Standard_False;
569 if (RecadreOnPeriodic)
602 if(TabOrien(1)!=-1) {
603 for(Standard_Integer n=1; n<=nbtabclass; n++) {
604 Standard_Integer cur = ((CSLib_Class2d *)TabClass(n))->SiDans_OnMode(Puv,Tol);
632 else { //-- TabOrien(1)=-1 False Wire
633 BRepClass_FaceClassifier aClassifier;
634 aClassifier.Perform(Face,Puv,Tol);
635 Status = aClassifier.State();
638 if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
640 if (Status == TopAbs_IN || Status == TopAbs_ON)
646 urecadre = Standard_True;
651 if (u > Umax || !IsUPer)
656 vrecadre = Standard_True;
664 if (v > Vmax || !IsVPer)
671 void BRepTopAdaptor_FClass2d::Destroy() {
676 Standard_Integer nbtabclass = TabClass.Length();
677 for(Standard_Integer d=1; d<=nbtabclass;d++) {
679 delete ((CSLib_Class2d *)TabClass(d));
687 #include <Standard_ConstructionError.hxx>
690 //const BRepTopAdaptor_FClass2d & BRepTopAdaptor_FClass2d::Copy(const BRepTopAdaptor_FClass2d& Other) const {
691 const BRepTopAdaptor_FClass2d & BRepTopAdaptor_FClass2d::Copy(const BRepTopAdaptor_FClass2d& ) const {
692 cerr<<"Copy not allowed in BRepTopAdaptor_FClass2d"<<endl;
693 Standard_ConstructionError::Raise();