1 // Created on: 1996-04-23
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-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 <BRepFeat.ixx>
19 //#include <BRepAlgo_Cut.hxx>
21 #include <BRepBuilderAPI.hxx>
22 #include <BRepAdaptor_Curve.hxx>
23 #include <TopExp_Explorer.hxx>
24 #include <TopTools_MapOfShape.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRep_Builder.hxx>
27 #include <Geom_Curve.hxx>
28 #include <Geom_TrimmedCurve.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
30 #include <Extrema_ExtPC.hxx>
31 #include <GeomAdaptor_Curve.hxx>
32 #include <BRepLProp.hxx>
34 #include <TopoDS_Vertex.hxx>
35 #include <TopoDS_Face.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Shell.hxx>
38 #include <TopoDS_Solid.hxx>
39 #include <Precision.hxx>
40 #include <GCPnts_QuasiUniformDeflection.hxx>
41 #include <BRepTopAdaptor_FClass2d.hxx>
42 #include <Geom2dAdaptor_Curve.hxx>
43 #include <GeomProjLib.hxx>
44 #include <gp_Vec2d.hxx>
45 #include <BRepTools.hxx>
46 #include <Geom_Surface.hxx>
47 #include <Bnd_Box.hxx>
48 #include <BRepBndLib.hxx>
49 #include <BRepLib_MakeFace.hxx>
50 #include <Geom_RectangularTrimmedSurface.hxx>
51 #include <Geom_Plane.hxx>
52 #include <Geom_CylindricalSurface.hxx>
53 #include <Geom_ConicalSurface.hxx>
54 #include <LocOpe_CSIntersector.hxx>
55 #include <LocOpe_PntFace.hxx>
56 #include <LocOpe_BuildShape.hxx>
58 #include <TColGeom_SequenceOfCurve.hxx>
63 #define NECHANTBARYC 11
65 //=======================================================================
66 //function : SampleEdges
68 //=======================================================================
70 void BRepFeat::SampleEdges(const TopoDS_Shape& theShape,
71 TColgp_SequenceOfPnt& theSeq)
73 LocOpe::SampleEdges(theShape,theSeq);
78 //=======================================================================
79 //function : Barycenter
80 //purpose : Calcul du barycentre des edges d'un shape
81 //=======================================================================
83 void BRepFeat::Barycenter(const TopoDS_Shape& S,
86 TopTools_MapOfShape theMap;
87 TopExp_Explorer exp(S,TopAbs_EDGE);
90 Standard_Real f,l,prm;
92 Standard_Integer i, nbp= 0;
94 for (; exp.More(); exp.Next()) {
95 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
96 if (!theMap.Add(edg)) {
99 if (!BRep_Tool::Degenerated(edg)) {
100 C = BRep_Tool::Curve(edg,Loc,f,l);
101 C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
102 for (i=1;i<NECHANTBARYC; i++) {
103 prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
104 Bar += C->Value(prm).XYZ();
110 for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
111 if (theMap.Add(exp.Current())) {
112 Bar += (BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()))).XYZ();
117 Bar.Divide((Standard_Real)nbp);
122 //=======================================================================
123 //function : ParametricBarycenter
124 //purpose : Calcul du barycentre "parametrique" shape sur une courbe
125 //=======================================================================
127 Standard_Real BRepFeat::ParametricBarycenter(const TopoDS_Shape& S,
128 const Handle(Geom_Curve)& CC)
130 TopTools_MapOfShape theMap;
131 TopExp_Explorer exp(S,TopAbs_EDGE);
133 Handle(Geom_Curve) C;
134 Standard_Real f,l,prm;
135 Standard_Integer i, nbp= 0;
136 GeomAdaptor_Curve TheCurve(CC);
138 extpc.Initialize(TheCurve,CC->FirstParameter(),CC->LastParameter());
139 Standard_Real parbar = 0;
141 for (; exp.More(); exp.Next()) {
142 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
143 if (!theMap.Add(edg)) {
146 if (!BRep_Tool::Degenerated(edg)) {
147 C = BRep_Tool::Curve(edg,Loc,f,l);
148 C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
149 for (i=1;i<NECHANTBARYC; i++) {
150 prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
151 gp_Pnt pone = C->Value(prm);
152 // On projette sur CC
154 if (extpc.IsDone() && extpc.NbExt() >= 1) {
155 Standard_Real Dist2Min = extpc.SquareDistance(1);
156 Standard_Integer kmin = 1;
157 for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
158 Standard_Real Dist2 = extpc.SquareDistance(k);
159 if (Dist2 < Dist2Min) {
165 Standard_Real prmp = extpc.Point(kmin).Parameter();
172 for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
173 if (theMap.Add(exp.Current())) {
174 gp_Pnt pone = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()));
175 // On projette sur CC
177 if (extpc.IsDone() && extpc.NbExt() >= 1) {
178 Standard_Real Dist2Min = extpc.SquareDistance(1);
179 for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
180 Standard_Real Dist2 = extpc.SquareDistance(k);
181 if (Dist2 < Dist2Min) {
190 parbar /=((Standard_Real)nbp);
195 //=======================================================================
196 //function : ParametricBarycenter
197 //purpose : Calcul du barycentre "parametrique" shape sur une courbe
198 //=======================================================================
200 void BRepFeat::ParametricMinMax(const TopoDS_Shape& S,
201 const Handle(Geom_Curve)& CC,
202 Standard_Real& prmin,
203 Standard_Real& prmax,
204 Standard_Real& prbmin,
205 Standard_Real& prbmax,
206 Standard_Boolean& flag,
207 const Standard_Boolean Ori)
209 LocOpe_CSIntersector ASI(S);
210 TColGeom_SequenceOfCurve scur;
213 if(ASI.IsDone() && ASI.NbPoints(1) >=1) {
215 prmin = Min(ASI.Point(1,1).Parameter(),
216 ASI.Point(1, ASI.NbPoints(1)).Parameter());
217 prmax = Max(ASI.Point(1,1).Parameter(),
218 ASI.Point(1, ASI.NbPoints(1)).Parameter());
221 TopAbs_Orientation Ori = ASI.Point(1,1).Orientation();
222 if (Ori == TopAbs_FORWARD) {
223 prmin = ASI.Point(1,1).Parameter();
224 prmax = ASI.Point(1, ASI.NbPoints(1)).Parameter();
227 prmax = ASI.Point(1,1).Parameter();
228 prmin = ASI.Point(1, ASI.NbPoints(1)).Parameter();
231 flag = Standard_True;
236 flag = Standard_False;
239 TopTools_MapOfShape theMap;
240 TopExp_Explorer exp(S,TopAbs_EDGE);
242 Handle(Geom_Curve) C;
243 Standard_Real f,l,prm;
244 // Standard_Integer i, nbp= 0;
246 GeomAdaptor_Curve TheCurve(CC);
248 extpc.Initialize(TheCurve,CC->FirstParameter(),CC->LastParameter());
250 prbmax = RealFirst();
251 for (; exp.More(); exp.Next()) {
252 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
253 if (!theMap.Add(edg)) {
256 if (!BRep_Tool::Degenerated(edg)) {
257 C = BRep_Tool::Curve(edg,Loc,f,l);
258 C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
259 for (i=1;i<NECHANTBARYC; i++) {
260 prm = ((NECHANTBARYC-i)*f + i*l)/NECHANTBARYC;
261 gp_Pnt pone = C->Value(prm);
262 // On projette sur CC
264 if (extpc.IsDone() && extpc.NbExt() >= 1) {
265 Standard_Real Dist2Min = extpc.SquareDistance(1);
266 Standard_Integer kmin = 1;
267 for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
268 Standard_Real Dist2 = extpc.SquareDistance(k);
269 if (Dist2 < Dist2Min) {
274 Standard_Real prmp = extpc.Point(kmin).Parameter();
275 if (prmp <= prbmin) {
278 if (prmp >= prbmax) {
286 for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
287 if (theMap.Add(exp.Current())) {
288 gp_Pnt pone = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()));
289 // On projette sur CC
291 if (extpc.IsDone() && extpc.NbExt() >= 1) {
292 Standard_Real Dist2Min = extpc.SquareDistance(1);
293 Standard_Integer kmin = 1;
294 for (Standard_Integer k=2; k<=extpc.NbExt(); k++) {
295 Standard_Real Dist2 = extpc.SquareDistance(k);
296 if (Dist2 < Dist2Min) {
301 Standard_Real prmp = extpc.Point(kmin).Parameter();
302 if (prmp <= prbmin) {
305 if (prmp >= prbmax) {
316 //=======================================================================
319 //=======================================================================
321 static Standard_Boolean IsIn (BRepTopAdaptor_FClass2d& FC,
322 Geom2dAdaptor_Curve AC)
324 Standard_Real Def = 100*Precision::Confusion();
325 GCPnts_QuasiUniformDeflection QU(AC,Def);
327 for (Standard_Integer i = 1; i <= QU.NbPoints(); i++) {
328 gp_Pnt2d P = AC.Value(QU.Parameter(i));
329 if (FC.Perform(P, Standard_False) == TopAbs_OUT) {
330 return Standard_False;
333 return Standard_True;
337 //=======================================================================
338 //function : PutInBoundsU
339 //purpose : Recadre la courbe 2d dans les bounds de la face
340 //=======================================================================
345 static void PutInBoundsU (Standard_Real umin,
348 Standard_Real period,
351 Handle(Geom2d_Curve)& C2d)
353 gp_Pnt2d Pf = C2d->Value(f);
354 gp_Pnt2d Pl = C2d->Value(l);
355 gp_Pnt2d Pm = C2d->Value(0.34*f + 0.66*l);
356 Standard_Real minC = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X());
357 Standard_Real maxC = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X());
358 Standard_Real du = 0.;
359 if (minC< umin - eps) {
360 du = (int((umin - minC)/period) + 1)*period;
362 if (minC > umax + eps) {
363 du = -(int((minC - umax)/period) + 1)*period;
368 minC += du; maxC += du;
370 // Ajuste au mieux la courbe dans le domaine.
371 if (maxC > umax +100*eps) {
372 Standard_Real d1 = maxC - umax;
373 Standard_Real d2 = umin - minC + period;
374 if (d2 < d1) du =-period;
383 //=======================================================================
384 //function : PutInBoundsU
385 //purpose : Recadre la courbe 2d dans les bounds de la face
386 //=======================================================================
391 static void PutInBoundsV (Standard_Real vmin,
394 Standard_Real period,
397 Handle(Geom2d_Curve)& C2d)
399 gp_Pnt2d Pf = C2d->Value(f);
400 gp_Pnt2d Pl = C2d->Value(l);
401 gp_Pnt2d Pm = C2d->Value(0.34*f + 0.66*l);
402 Standard_Real minC = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y());
403 Standard_Real maxC = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y());
404 Standard_Real dv = 0.;
405 if (minC< vmin - eps) {
406 dv = (int((vmin - minC)/period) + 1)*period;
408 if (minC > vmax + eps) {
409 dv = -(int((minC - vmax)/period) + 1)*period;
414 minC += dv; maxC += dv;
416 // Ajuste au mieux la courbe dans le domaine.
417 if (maxC > vmax +100*eps) {
418 Standard_Real d1 = maxC - vmax;
419 Standard_Real d2 = vmin - minC + period;
420 if (d2 < d1) dv =-period;
429 //=======================================================================
430 //function : IsInside
432 //=======================================================================
435 Standard_Boolean BRepFeat::IsInside(const TopoDS_Face& F1,
436 const TopoDS_Face& F2)
439 exp.Init(F1, TopAbs_EDGE);
441 Standard_Real umin,umax,vmin,vmax, uperiod=0, vperiod=0;
442 Standard_Integer flagu = 0, flagv = 0;
443 TopLoc_Location L; // Recup S avec la location pour eviter la copie.
444 Handle (Geom_Surface) S = BRep_Tool::Surface(F2);
445 // Standard_Real periodu, periodv;
446 BRepTools::UVBounds(F2,umin,umax,vmin,vmax);
448 if (S->IsUPeriodic()) {
450 uperiod = S->UPeriod();
453 if (S->IsVPeriodic()) {
455 vperiod = S->VPeriod();
457 TopoDS_Shape aLocalShape = F2.Oriented(TopAbs_FORWARD);
458 BRepTopAdaptor_FClass2d FC (TopoDS::Face(aLocalShape),Precision::Confusion());
459 // BRepTopAdaptor_FClass2d FC (TopoDS::Face(F2.Oriented(TopAbs_FORWARD)),
460 // Precision::Confusion());
461 for(; exp.More(); exp.Next()) {
463 Handle(Geom_Curve) C0 = BRep_Tool::Curve(TopoDS::Edge(exp.Current()),f1,l1);
464 Handle(Geom2d_Curve) C = GeomProjLib::Curve2d(C0,f1,l1,S);
465 TopoDS_Edge E = TopoDS::Edge(exp.Current());
466 if(flagu == 1 || flagv == 1) {
467 Standard_Real eps = BRep_Tool::Tolerance(E);
468 BRep_Tool::Range(E,f1,l1);
469 if(flagu == 1) PutInBoundsU(umin, umax, eps, uperiod, f1, l1, C);
470 if(flagv == 1) PutInBoundsV(vmin, vmax, eps, vperiod, f1, l1, C);
472 Geom2dAdaptor_Curve AC(C,f1,l1);
474 return Standard_False;
477 return Standard_True;
482 //=======================================================================
483 //function : FaceUntil
485 //=======================================================================
488 void BRepFeat::FaceUntil(const TopoDS_Shape& Sbase,
492 BRepBndLib::Add(Sbase,B);
493 Standard_Real c[6], bnd;
494 B.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
496 for(Standard_Integer i = 1 ; i < 6; i++) {
497 if(c[i] > bnd) bnd = c[i];
502 Handle(Geom_Surface) s = BRep_Tool::Surface(FUntil);
503 Handle(Standard_Type) styp = s->DynamicType();
504 if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
505 s = Handle(Geom_RectangularTrimmedSurface)::DownCast(s)->BasisSurface();
506 styp = s->DynamicType();
508 Handle(Geom_RectangularTrimmedSurface) str;
509 if (styp == STANDARD_TYPE(Geom_Plane)) {
510 str = new Geom_RectangularTrimmedSurface
511 (s, bnd, -bnd, bnd, -bnd, Standard_True, Standard_True);
513 else if (styp == STANDARD_TYPE(Geom_CylindricalSurface)) {
514 str = new Geom_RectangularTrimmedSurface
515 (s, bnd, -bnd, Standard_False, Standard_True);
517 else if (styp == STANDARD_TYPE(Geom_ConicalSurface)) {
518 str = new Geom_RectangularTrimmedSurface
519 (s, bnd, -bnd, Standard_False, Standard_True);
526 FUntil = BRepLib_MakeFace(str, Precision::Confusion());
531 //=======================================================================
534 //=======================================================================
536 TopoDS_Solid BRepFeat::Tool(const TopoDS_Shape& SRef,
537 const TopoDS_Face& Fac,
538 const TopAbs_Orientation Orf)
540 TopTools_ListOfShape lfaces;
541 // for (TopExp_Explorer exp(SRef,TopAbs_FACE); exp.More(); exp.Next()) {
542 TopExp_Explorer exp(SRef,TopAbs_FACE) ;
543 for ( ; exp.More(); exp.Next()) {
544 if (exp.Current().ShapeType() == TopAbs_FACE) {
545 lfaces.Append(exp.Current());
549 LocOpe_BuildShape bs(lfaces);
550 const TopoDS_Shape& Res = bs.Shape();
552 if (Res.ShapeType() == TopAbs_SHELL) {
554 Sh = TopoDS::Shell(Res);
556 else if (Res.ShapeType() == TopAbs_SOLID) {
557 exp.Init(Res,TopAbs_SHELL);
558 Sh = TopoDS::Shell(exp.Current());
571 Sh.Orientation(TopAbs_FORWARD);
573 TopAbs_Orientation orient = TopAbs_FORWARD;
575 for (exp.Init(Sh,TopAbs_FACE); exp.More(); exp.Next()) {
576 if (exp.Current().IsSame(Fac)) {
577 orient = exp.Current().Orientation();
582 Standard_Boolean reverse = Standard_False;
583 if ((orient == Fac.Orientation() && Orf == TopAbs_REVERSED) ||
584 (orient != Fac.Orientation() && Orf == TopAbs_FORWARD)) {
585 reverse = Standard_True;
600 //=======================================================================
602 //purpose : Print the error Description of a StatusError on a stream.
603 //=======================================================================
605 Standard_OStream& BRepFeat::Print(const BRepFeat_StatusError se,
612 case BRepFeat_BadDirect :
613 s << "Directions must be opposite";
615 case BRepFeat_BadIntersect :
616 s << "Intersection failure";
618 case BRepFeat_EmptyBaryCurve :
619 s << "Empty BaryCurve";
621 case BRepFeat_EmptyCutResult :
622 s << "Failure in Cut : Empty resulting shape";
624 case BRepFeat_FalseSide :
625 s << "Verify plane and wire orientation";
627 case BRepFeat_IncDirection :
628 s << "Incoherent Direction for shapes From and Until";
630 case BRepFeat_IncSlidFace :
631 s << "Sliding face not in Base shape";
633 case BRepFeat_IncParameter :
634 s << "Incoherent Parameter : shape Until before shape From";
636 case BRepFeat_IncTypes :
637 s << "Invalid option for faces From and Until : 1 Support and 1 not";
639 case BRepFeat_IntervalOverlap :
640 s << "Shapes From and Until overlap";
642 case BRepFeat_InvFirstShape :
643 s << "Invalid First shape : more than 1 face";
645 case BRepFeat_InvOption :
646 s << "Invalid option";
648 case BRepFeat_InvShape :
649 s << "Invalid shape";
651 case BRepFeat_LocOpeNotDone :
652 s << "Local Operation not done";
654 case BRepFeat_LocOpeInvNotDone :
655 s << "Local Operation : intersection line conflict";
657 case BRepFeat_NoExtFace :
658 s << "No Extreme faces";
660 case BRepFeat_NoFaceProf :
661 s << "No Face Profile";
663 case BRepFeat_NoGluer :
664 s << "Gluer Failure";
666 case BRepFeat_NoIntersectF :
667 s << "No intersection between Feature and shape From";
669 case BRepFeat_NoIntersectU :
670 s << "No intersection between Feature and shape Until";
672 case BRepFeat_NoParts :
673 s << "No parts of tool kept";
675 case BRepFeat_NoProjPt :
676 s << "No projection points";
678 case BRepFeat_NotInitialized :
679 s << "Fields not initialized";
681 case BRepFeat_NotYetImplemented :
682 s << "Not yet implemented";
684 case BRepFeat_NullRealTool :
685 s << "Real Tool : Null DPrism";
687 case BRepFeat_NullToolF :
688 s << "Null Tool : Invalid type for shape Form";
690 case BRepFeat_NullToolU :
691 s << "Null Tool : Invalid type for shape Until";