1 // Created on: 1994-02-09
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <TopOpeBRepTool_ShapeTool.ixx>
19 #include <BRep_Tool.hxx>
23 #include <Geom_Surface.hxx>
24 #include <TopLoc_Location.hxx>
25 #include <Precision.hxx>
26 #include <Standard_ProgramError.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <Geom_Curve.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Face.hxx>
32 #include <gp_Dir2d.hxx>
33 #include <Geom2d_Line.hxx>
34 #include <BRepTools.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <BRepLProp_CLProps.hxx>
37 #include <GeomAdaptor_Surface.hxx>
38 #include <TopOpeBRepTool_EXPORT.hxx>
39 #include <TopOpeBRepTool_2d.hxx>
41 //=======================================================================
42 //function : Tolerance
44 //=======================================================================
46 Standard_Real TopOpeBRepTool_ShapeTool::Tolerance(const TopoDS_Shape& S)
48 if ( S.IsNull() ) return 0. ;
50 switch (S.ShapeType()) {
51 case TopAbs_FACE : tol = BRep_Tool::Tolerance(TopoDS::Face(S)); break;
52 case TopAbs_EDGE : tol = BRep_Tool::Tolerance(TopoDS::Edge(S)); break;
53 case TopAbs_VERTEX : tol = BRep_Tool::Tolerance(TopoDS::Vertex(S)); break;
54 default : Standard_ProgramError::Raise
55 ("TopOpeBRepTool_ShapeTool : Shape has no tolerance"); break;
61 //=======================================================================
64 //=======================================================================
66 gp_Pnt TopOpeBRepTool_ShapeTool::Pnt(const TopoDS_Shape& S)
68 if ( S.ShapeType() != TopAbs_VERTEX ) {
69 Standard_ProgramError::Raise("TopOpeBRepTool_ShapeTool::Pnt");
72 return BRep_Tool::Pnt(TopoDS::Vertex(S));
76 #include <Geom_OffsetCurve.hxx>
77 #include <Geom_TrimmedCurve.hxx>
79 //=======================================================================
80 //function : BASISCURVE
82 //=======================================================================
83 Handle(Geom_Curve) TopOpeBRepTool_ShapeTool::BASISCURVE(const Handle(Geom_Curve)& C)
85 Handle(Standard_Type) T = C->DynamicType();
86 if ( T == STANDARD_TYPE(Geom_OffsetCurve) )
87 return BASISCURVE(Handle(Geom_OffsetCurve)::DownCast(C)->BasisCurve());
88 else if ( T == STANDARD_TYPE(Geom_TrimmedCurve) )
89 return BASISCURVE(Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve());
93 Handle(Geom_Curve) TopOpeBRepTool_ShapeTool::BASISCURVE(const TopoDS_Edge& E)
96 Handle(Geom_Curve) C = BRep_Tool::Curve(E, f, l);
97 if ( C.IsNull() ) return C;
101 #include <Geom_OffsetSurface.hxx>
102 #include <Geom_RectangularTrimmedSurface.hxx>
103 #include <Geom_SurfaceOfRevolution.hxx>
104 #include <Geom_SurfaceOfLinearExtrusion.hxx>
107 //=======================================================================
108 //function : BASISSURFACE
110 //=======================================================================
111 Handle(Geom_Surface) TopOpeBRepTool_ShapeTool::BASISSURFACE(const Handle(Geom_Surface)& S)
113 Handle(Standard_Type) T = S->DynamicType();
114 if ( T == STANDARD_TYPE(Geom_OffsetSurface) )
115 return BASISSURFACE(Handle(Geom_OffsetSurface)::DownCast(S)->BasisSurface());
116 else if ( T == STANDARD_TYPE(Geom_RectangularTrimmedSurface) )
117 return BASISSURFACE(Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface());
121 Handle(Geom_Surface) TopOpeBRepTool_ShapeTool::BASISSURFACE(const TopoDS_Face& F)
123 TopLoc_Location L;Handle(Geom_Surface) S = BRep_Tool::Surface(F,L);
124 return BASISSURFACE(S);
127 //=======================================================================
128 //function : UVBOUNDS
130 //=======================================================================
131 void TopOpeBRepTool_ShapeTool::UVBOUNDS
132 (const Handle(Geom_Surface)& S,
133 Standard_Boolean& UPeriodic,
134 Standard_Boolean& VPeriodic,
135 Standard_Real& Umin, Standard_Real& Umax,
136 Standard_Real& Vmin, Standard_Real& Vmax)
138 const Handle(Geom_Surface) BS = BASISSURFACE(S);
139 Handle(Standard_Type) T = BS->DynamicType();
141 if ( T == STANDARD_TYPE(Geom_SurfaceOfRevolution) ) {
142 Handle(Geom_SurfaceOfRevolution)
143 SR = Handle(Geom_SurfaceOfRevolution)::DownCast(BS);
144 Handle(Geom_Curve) C = BASISCURVE(SR->BasisCurve());
145 if (C->IsPeriodic()) {
146 UPeriodic = Standard_False;
147 VPeriodic = Standard_True;
148 Vmin = C->FirstParameter(); Vmax = C->LastParameter();
151 else if ( T == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) ) {
152 Handle(Geom_SurfaceOfLinearExtrusion)
153 SE = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(BS);
154 Handle(Geom_Curve) C = BASISCURVE(SE->BasisCurve());
155 if (C->IsPeriodic()) {
156 UPeriodic = Standard_True;
157 Umin = C->FirstParameter(); Umax = C->LastParameter();
158 VPeriodic = Standard_False;
162 UPeriodic = BS->IsUPeriodic();
163 VPeriodic = BS->IsVPeriodic();
164 BS->Bounds(Umin,Umax,Vmin,Vmax);
168 void TopOpeBRepTool_ShapeTool::UVBOUNDS
169 (const TopoDS_Face& F,
170 Standard_Boolean& UPeriodic, Standard_Boolean& VPeriodic,
171 Standard_Real& Umin, Standard_Real& Umax,
172 Standard_Real& Vmin, Standard_Real& Vmax)
174 TopLoc_Location L;Handle(Geom_Surface) S = BRep_Tool::Surface(F,L);
175 UVBOUNDS(S, UPeriodic, VPeriodic, Umin, Umax, Vmin, Vmax);
178 //=======================================================================
179 //function : AdjustOnPeriodic
181 //=======================================================================
183 void TopOpeBRepTool_ShapeTool::AdjustOnPeriodic(const TopoDS_Shape& F,
187 TopoDS_Face FF = TopoDS::Face(F);
189 const Handle(Geom_Surface) Surf = BRep_Tool::Surface(FF,Loc);
191 // Standard_Real Ufirst,Ulast,Vfirst,Vlast;
192 Standard_Boolean isUperio,isVperio;
193 isUperio = Surf->IsUPeriodic();
194 isVperio = Surf->IsVPeriodic();
196 // exit if surface supporting F is not periodic on U or V
197 if (!isUperio && !isVperio) return;
199 Standard_Real UFfirst,UFlast,VFfirst,VFlast;
200 BRepTools::UVBounds(FF,UFfirst,UFlast,VFfirst,VFlast);
202 Standard_Real tol = Precision::PConfusion();
205 Standard_Real Uperiod = Surf->UPeriod();
207 // Standard_Real ubid = UFfirst;
209 // ElCLib::AdjustPeriodic(UFfirst,UFfirst + Uperiod,tol,ubid,u);
210 if (Abs(u - UFfirst-Uperiod) > tol)
211 u = ElCLib::InPeriod(u,UFfirst,UFfirst + Uperiod);
214 Standard_Real Vperiod = Surf->VPeriod();
216 // Standard_Real vbid = VFfirst;
218 // ElCLib::AdjustPeriodic(VFfirst,VFfirst + Vperiod,tol,vbid,v);
219 if (Abs(v - VFfirst-Vperiod) > tol)
220 v = ElCLib::InPeriod(v,VFfirst,VFfirst + Vperiod);
225 //=======================================================================
228 //=======================================================================
230 Standard_Boolean TopOpeBRepTool_ShapeTool::Closed(const TopoDS_Shape& S1,
231 const TopoDS_Shape& S2)
233 const TopoDS_Edge& E = TopoDS::Edge(S1);
234 const TopoDS_Face& F = TopoDS::Face(S2);
235 Standard_Boolean brepclosed = BRep_Tool::IsClosed(E,F);
237 Standard_Integer n = 0;
238 for ( TopExp_Explorer x(F,TopAbs_EDGE); x.More(); x.Next() )
239 if ( x.Current().IsSame(E) ) n++;
240 if ( n < 2 ) return Standard_False;
241 else return Standard_True;
243 return Standard_False;
248 extern Standard_Boolean TopOpeBRepTool_GettraceVC();
249 extern Standard_Boolean TopOpeBRepTool_GettraceNYI();
253 inline Standard_Boolean PARINBOUNDS(const Standard_Real par,
254 const Standard_Real first,
255 const Standard_Real last,
256 const Standard_Real tol)
258 Standard_Boolean b = ( ((first+tol) <= par) && (par <= (last-tol)) );
262 inline Standard_Boolean PARONBOUND(const Standard_Real par,
263 const Standard_Real bound,
264 const Standard_Real tol)
266 Standard_Boolean b = ( ((bound-tol) <= par) && (par <= (bound+tol)) );
271 Standard_Real ADJUST(const Standard_Real par,
272 const Standard_Real first,
273 const Standard_Real last,
274 const Standard_Real tol)
276 Standard_Real period = last - first, periopar = par;
278 if (PARINBOUNDS(par,first,last,tol)) {
279 periopar = par + period;
281 else if (PARONBOUND(par,first,tol)) {
282 periopar = par + period;
284 else if (PARONBOUND(par,last,tol)) {
285 periopar = par - period;
291 //=======================================================================
292 //function : PeriodizeParameter
294 //=======================================================================
296 Standard_Real TopOpeBRepTool_ShapeTool::PeriodizeParameter
297 (const Standard_Real par,
298 const TopoDS_Shape& EE,
299 const TopoDS_Shape& FF)
301 Standard_Real periopar = par;
302 if ( ! TopOpeBRepTool_ShapeTool::Closed(EE,FF) ) return periopar;
304 TopoDS_Edge E = TopoDS::Edge(EE);
305 TopoDS_Face F = TopoDS::Face(FF);
308 const Handle(Geom_Surface) Surf = BRep_Tool::Surface(F,Loc);
309 Standard_Boolean isUperio = Surf->IsUPeriodic();
310 Standard_Boolean isVperio = Surf->IsVPeriodic();
311 if (!isUperio && !isVperio) return periopar;
313 Standard_Real Ufirst,Ulast,Vfirst,Vlast;
314 Surf->Bounds(Ufirst,Ulast,Vfirst,Vlast);
316 Standard_Real first,last,tolpc;
317 const Handle(Geom2d_Curve) PC = FC2D_CurveOnSurface(E,F,first,last,tolpc);
318 if (PC.IsNull()) Standard_ProgramError::Raise("ShapeTool::PeriodizeParameter : no 2d curve");
320 Handle(Standard_Type) TheType = PC->DynamicType();
321 if (TheType == STANDARD_TYPE(Geom2d_Line)) {
323 const Handle(Geom2d_Line)& HL = *((Handle(Geom2d_Line)*)&PC);
324 const gp_Dir2d& D = HL->Direction();
326 Standard_Real tol = Precision::Angular();
327 Standard_Boolean isoU = Standard_False, isoV = Standard_False;
328 if (D.IsParallel(gp_Dir2d(0.,1.),tol)) isoU = Standard_True;
329 else if (D.IsParallel(gp_Dir2d(1.,0.),tol)) isoV = Standard_True;
331 periopar = ADJUST(par,Ufirst,Ulast,tol);
334 periopar = ADJUST(par,Vfirst,Vlast,tol);
338 if (TopOpeBRepTool_GettraceVC()) {
339 cout<<"TopOpeBRepTool_ShapeTool PC on edge is ";
340 if (isoU) cout<<"isoU f,l "<<Ufirst<<" "<<Ulast<<endl;
341 else if (isoV) cout<<"isoV f,l "<<Vfirst<<" "<<Vlast<<endl;
342 else cout<<"not isoU, not isoV"<<endl;
343 cout<<"par = "<<par<<" --> "<<periopar<<endl;
354 //=======================================================================
355 //function : ShapesSameOriented
357 //=======================================================================
359 Standard_Boolean TopOpeBRepTool_ShapeTool::ShapesSameOriented
360 (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
362 Standard_Boolean so = Standard_True;
364 Standard_Boolean sam = S1.IsSame(S2);
366 const TopAbs_Orientation o1 = S1.Orientation();
367 const TopAbs_Orientation o2 = S2.Orientation();
368 if ((o1 == TopAbs_FORWARD || o1 == TopAbs_REVERSED) &&
369 (o2 == TopAbs_FORWARD || o2 == TopAbs_REVERSED)) {
375 TopAbs_ShapeEnum t1 = S1.ShapeType(), t2 = S2.ShapeType();
376 if ( (t1 == TopAbs_SOLID) && (t2 == TopAbs_SOLID) ) {
379 else if ( (t1 == TopAbs_FACE) && (t2 == TopAbs_FACE) ) {
380 so = FacesSameOriented(S1,S2);
382 else if ( (t1 == TopAbs_EDGE) && (t2 == TopAbs_EDGE) ) {
383 so = EdgesSameOriented(S1,S2);
385 else if ( (t1 == TopAbs_VERTEX) && (t2 == TopAbs_VERTEX) ) {
386 TopAbs_Orientation o1 = S1.Orientation();
387 TopAbs_Orientation o2 = S2.Orientation();
388 if (o1==TopAbs_EXTERNAL||o1==TopAbs_INTERNAL||o2==TopAbs_EXTERNAL||o2==TopAbs_INTERNAL)
397 //=======================================================================
398 //function : SurfacesSameOriented
400 //=======================================================================
402 Standard_Boolean TopOpeBRepTool_ShapeTool::SurfacesSameOriented
403 (const BRepAdaptor_Surface& S1,const BRepAdaptor_Surface& Sref)
405 const BRepAdaptor_Surface& S2 = Sref;
406 GeomAbs_SurfaceType ST1 = S1.GetType();
407 GeomAbs_SurfaceType ST2 = S2.GetType();
409 Standard_Boolean so = Standard_True;
411 if (ST1 == GeomAbs_Plane && ST2 == GeomAbs_Plane) {
413 Standard_Real u1 = S1.FirstUParameter();
414 Standard_Real v1 = S1.FirstVParameter();
415 gp_Pnt p1; gp_Vec d1u,d1v; S1.D1(u1,v1,p1,d1u,d1v);
416 gp_Vec n1 = d1u.Crossed(d1v);
418 Standard_Real u2 = S2.FirstUParameter();
419 Standard_Real v2 = S2.FirstVParameter();
420 gp_Pnt p2; gp_Vec d2u,d2v; S2.D1(u2,v2,p2,d2u,d2v);
421 gp_Vec n2 = d2u.Crossed(d2v);
423 Standard_Real d = n1.Dot(n2);
426 else if (ST1 == GeomAbs_Cylinder && ST2 == GeomAbs_Cylinder) {
428 // On peut projeter n'importe quel point.
429 // prenons donc l'origine
430 Standard_Real u1 = 0.;
431 Standard_Real v1 = 0.;
432 gp_Pnt p1; gp_Vec d1u,d1v; S1.D1(u1,v1,p1,d1u,d1v);
433 gp_Vec n1 = d1u.Crossed(d1v);
435 Handle(Geom_Surface) HS2 = S2.Surface().Surface();
436 HS2 = Handle(Geom_Surface)::DownCast(HS2->Transformed(S2.Trsf()));
437 gp_Pnt2d p22d; Standard_Real dp2;
438 Standard_Boolean ok = FUN_tool_projPonS(p1,HS2,p22d,dp2);
439 if ( !ok ) return so; // NYI : raise
441 Standard_Real u2 = p22d.X();
442 Standard_Real v2 = p22d.Y();
443 gp_Pnt p2; gp_Vec d2u,d2v; S2.D1(u2,v2,p2,d2u,d2v);
444 gp_Vec n2 = d2u.Crossed(d2v);
446 Standard_Real d = n1.Dot(n2);
450 // prendre u1,v1 et projeter sur 2 pour calcul des normales
453 if (TopOpeBRepTool_GettraceNYI()) {
454 cout<<"TopOpeBRepTool_ShapeTool::SurfacesSameOriented surfaces non traitees : NYI";
464 //=======================================================================
465 //function : FacesSameOriented
467 //=======================================================================
469 Standard_Boolean TopOpeBRepTool_ShapeTool::FacesSameOriented
470 (const TopoDS_Shape& S1, const TopoDS_Shape& Sref)
472 const TopoDS_Shape& S2 = Sref;
473 const TopoDS_Face& F1 = TopoDS::Face(S1);
474 const TopoDS_Face& F2 = TopoDS::Face(S2);
475 TopAbs_Orientation o1 = F1.Orientation();
476 TopAbs_Orientation o2 = F2.Orientation();
477 if ( o1 == TopAbs_EXTERNAL || o1 == TopAbs_INTERNAL ||
478 o2 == TopAbs_EXTERNAL || o2 == TopAbs_INTERNAL ) {
479 return Standard_True;
482 Standard_Boolean computerestriction = Standard_False;
483 BRepAdaptor_Surface BAS1(F1,computerestriction);
484 BRepAdaptor_Surface BAS2(F2,computerestriction);
485 Standard_Boolean so = F1.IsSame(F2) || SurfacesSameOriented(BAS1,BAS2);
486 Standard_Boolean b = so;
487 if ( o1 != o2 ) b = !so;
492 //=======================================================================
493 //function : CurvesSameOriented
495 //=======================================================================
497 Standard_Boolean TopOpeBRepTool_ShapeTool::CurvesSameOriented
498 (const BRepAdaptor_Curve& C1, const BRepAdaptor_Curve& Cref)
500 const BRepAdaptor_Curve& C2 = Cref;
501 GeomAbs_CurveType CT1 = C1.GetType();
502 GeomAbs_CurveType CT2 = C2.GetType();
503 Standard_Boolean so = Standard_True;
505 if (CT1 == GeomAbs_Line && CT2 == GeomAbs_Line) {
506 Standard_Real p1 = C1.FirstParameter();
507 gp_Dir t1,n1; Standard_Real c1; EdgeData(C1,p1,t1,n1,c1);
508 Standard_Real p2 = C2.FirstParameter();
509 gp_Dir t2,n2; Standard_Real c2; EdgeData(C2,p2,t2,n2,c2);
510 Standard_Real d = t1.Dot(t2);
514 // prendre p1 et projeter sur 2 pour calcul des normales
517 if (TopOpeBRepTool_GettraceNYI()) {
518 cout<<"TopOpeBRepTool_ShapeTool::CurvesSameOriented non lineaires : NYI";
527 //=======================================================================
528 //function : EdgesSameOriented
530 //=======================================================================
532 Standard_Boolean TopOpeBRepTool_ShapeTool::EdgesSameOriented
533 (const TopoDS_Shape& S1, const TopoDS_Shape& Sref)
535 const TopoDS_Shape& S2 = Sref;
536 const TopoDS_Edge& E1 = TopoDS::Edge(S1);
537 const TopoDS_Edge& E2 = TopoDS::Edge(S2);
538 TopAbs_Orientation o1 = E1.Orientation();
539 TopAbs_Orientation o2 = E2.Orientation();
540 if ( o1 == TopAbs_EXTERNAL || o1 == TopAbs_INTERNAL ||
541 o2 == TopAbs_EXTERNAL || o2 == TopAbs_INTERNAL ) {
542 return Standard_True;
544 BRepAdaptor_Curve BAC1(E1);
545 BRepAdaptor_Curve BAC2(E2);
546 Standard_Boolean so = CurvesSameOriented(BAC1,BAC2);
547 Standard_Boolean b = so;
548 if ( o1 != o2 ) b = !so;
553 //=======================================================================
554 //function : EdgeData
556 //=======================================================================
558 Standard_Real TopOpeBRepTool_ShapeTool::EdgeData
559 (const BRepAdaptor_Curve& BAC, const Standard_Real P,
560 gp_Dir& T, gp_Dir& N, Standard_Real& C)
563 Standard_Real tol = Precision::Angular();
565 BRepLProp_CLProps BL(BAC,P,2,tol);
569 // xpu150399 cto900R4
570 Standard_Real tol1 = Epsilon(0.), tol2 = RealLast();
571 Standard_Real tolm = Max(tol,Max(tol1,tol2));
573 if ( Abs(C) > tolm ) BL.Normal(N);
578 //=======================================================================
579 //function : EdgeData
581 //=======================================================================
583 Standard_Real TopOpeBRepTool_ShapeTool::EdgeData
584 (const TopoDS_Shape& E, const Standard_Real P,
585 gp_Dir& T, gp_Dir& N, Standard_Real& C)
587 BRepAdaptor_Curve BAC(TopoDS::Edge(E));
588 Standard_Real d = EdgeData(BAC,P,T,N,C);
593 //=======================================================================
594 //function : Resolution3dU
596 //=======================================================================
598 Standard_Real TopOpeBRepTool_ShapeTool::Resolution3dU(const Handle(Geom_Surface)& SU,
599 const Standard_Real Tol2d)
601 GeomAdaptor_Surface GAS(SU);
602 Standard_Real r3dunit = 0.00001; // petite valeur (1.0 -> RangeError sur un tore)
603 Standard_Real ru = GAS.UResolution(r3dunit);
604 Standard_Real r3du = r3dunit*(Tol2d/ru);
609 //=======================================================================
610 //function : Resolution3dV
612 //=======================================================================
614 Standard_Real TopOpeBRepTool_ShapeTool::Resolution3dV(const Handle(Geom_Surface)& SU,
615 const Standard_Real Tol2d)
617 GeomAdaptor_Surface GAS(SU);
618 Standard_Real r3dunit = 0.00001; // petite valeur (1.0 -> RangeError sur un tore)
619 Standard_Real rv = GAS.VResolution(r3dunit);
620 Standard_Real r3dv = r3dunit*(Tol2d/rv);
625 //=======================================================================
626 //function : Resolution3d
628 //=======================================================================
630 Standard_Real TopOpeBRepTool_ShapeTool::Resolution3d(const Handle(Geom_Surface)& SU,
631 const Standard_Real Tol2d)
633 Standard_Real ru = Resolution3dU(SU,Tol2d);
634 Standard_Real rv = Resolution3dV(SU,Tol2d);
635 Standard_Real r = Max(ru,rv);
640 //=======================================================================
641 //function : Resolution3d
643 //=======================================================================
645 Standard_Real TopOpeBRepTool_ShapeTool::Resolution3d(const TopoDS_Face& F,
646 const Standard_Real Tol2d)
648 TopLoc_Location L; const Handle(Geom_Surface)& SU = BRep_Tool::Surface(F,L);
649 Standard_Real r = Resolution3d(SU,Tol2d);