1 // Created on: 1994-10-21
2 // Created by: Bruno DUMORTIER
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.
19 #include <BRepFill_TrimSurfaceTool.ixx>
21 #include <Precision.hxx>
23 #include <Adaptor3d_SurfaceOfRevolution.hxx>
24 #include <AppParCurves_MultiCurve.hxx>
25 #include <BRepFill_ComputeCLine.hxx>
26 #include <BRepFill_MultiLine.hxx>
27 #include <BRepIntCurveSurface_Inter.hxx>
28 #include <BRepFill_ApproxSeewing.hxx>
29 #include <BRep_Tool.hxx>
31 #include <BSplCLib.hxx>
34 #include <gp_Sphere.hxx>
35 #include <gp_Cone.hxx>
36 #include <gp_Torus.hxx>
37 #include <gp_Cylinder.hxx>
38 #include <Geom2dInt_GInter.hxx>
39 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
40 #include <Geom2dAdaptor_Curve.hxx>
41 #include <Geom2d_BSplineCurve.hxx>
42 #include <Geom2d_TrimmedCurve.hxx>
43 #include <GeomAdaptor_Surface.hxx>
44 #include <GeomAdaptor_HCurve.hxx>
45 #include <Geom_Plane.hxx>
46 #include <Geom_SurfaceOfRevolution.hxx>
47 #include <Geom_BSplineCurve.hxx>
48 #include <Geom_TrimmedCurve.hxx>
49 #include <GeomProjLib.hxx>
50 #include <IntRes2d_IntersectionPoint.hxx>
51 #include <IntRes2d_IntersectionSegment.hxx>
52 #include <Precision.hxx>
53 #include <StdFail_NotDone.hxx>
54 #include <Standard_NotImplemented.hxx>
55 #include <TColgp_Array1OfPnt.hxx>
56 #include <TColStd_Array1OfReal.hxx>
57 #include <TColStd_Array1OfInteger.hxx>
58 #include <TopAbs_State.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopExp_Explorer.hxx>
65 #include <DrawTrSurf.hxx>
69 static Standard_Boolean Affich = Standard_False;
70 static Standard_Integer NBCALL = 1;
73 //=======================================================================
74 //function : BRepFill_TrimSurfaceTool
75 //purpose : Initialisation with two neighbor faces
76 // Edge1 and Edge2 are parallel edges corresponding
77 // to minimum iso on F1 and F2 respectively.
78 // ie Edge1 is Umin or VMin on F1.
79 // Inv1 and Inv2 show if Edge1 and Edge2 are
81 //=======================================================================
83 BRepFill_TrimSurfaceTool::BRepFill_TrimSurfaceTool
84 (const Handle(Geom2d_Curve)& Bis,
85 const TopoDS_Face& Face1,
86 const TopoDS_Face& Face2,
87 const TopoDS_Edge& Edge1,
88 const TopoDS_Edge& Edge2,
89 const Standard_Boolean Inv1,
90 const Standard_Boolean Inv2 ) :
101 cout << " ---------->TrimSurfaceTool : NBCALL = " << NBCALL << endl;
106 sprintf(name,"FACE1_%d",NBCALL);
107 DBRep::Set(name,myFace1);
109 sprintf(name,"FACE2_%d",NBCALL);
110 DBRep::Set(name,myFace2);
112 sprintf(name,"EDGE1_%d",NBCALL);
113 DBRep::Set(name,myEdge1);
115 sprintf(name,"EDGE2_%d",NBCALL);
116 DBRep::Set(name,myEdge2);
118 sprintf(name,"BISSEC_%d",NBCALL);
119 DrawTrSurf::Set(name,myBis);
127 //=======================================================================
129 //purpose : Order the sequence of points by increasing x.
130 //=======================================================================
132 static void Bubble(TColgp_SequenceOfPnt& Seq)
134 Standard_Boolean Invert = Standard_True;
135 Standard_Integer NbPoints = Seq.Length();
137 Invert = Standard_False;
138 for ( Standard_Integer i = 1; i < NbPoints; i++) {
139 gp_Pnt P1 = Seq.Value(i);
140 gp_Pnt P2 = Seq.Value(i+1);
143 Invert = Standard_True;
150 //=======================================================================
151 //function : EvalPhase
153 //=======================================================================
155 static Standard_Real EvalPhase(const TopoDS_Edge& Edge,
156 const TopoDS_Face& Face,
157 const GeomAdaptor_Surface& GAS,
160 gp_Pnt2d PE1,PE2,PF1,PF2;
162 Standard_Real V = 0.;
163 BRep_Tool::UVPoints(Edge,Face,PE1,PE2);
165 TopExp_Explorer Exp(Face,TopAbs_EDGE);
166 for (; Exp.More(); Exp.Next()) {
167 if ( !TopoDS::Edge(Exp.Current()).IsSame(Edge)) {
168 BRep_Tool::UVPoints(TopoDS::Edge(Exp.Current()),Face,PF1,PF2);
169 V = ( Abs(PF1.Y() - VDeg) > Abs(PF2.Y() - VDeg)) ? PF1.Y() : PF2.Y();
173 gp_Pnt P = GAS.Value(0., V);
175 if ( gp_Vec(Axis.Location(), P).Dot(Axis.XDirection()) < 0.)
182 //=======================================================================
183 //function : EvalParameters
185 //=======================================================================
187 static void EvalParameters(const TopoDS_Edge& Edge,
188 const TopoDS_Face& Face,
189 const Handle(Geom2d_Curve)& Bis ,
190 TColgp_SequenceOfPnt& Seq )
192 Standard_Boolean Degener = BRep_Tool::Degenerated(Edge);
193 // return curves 3d associated to edges.
197 Handle(Geom_TrimmedCurve) CT;
198 Handle(Geom_Plane) Plane = new Geom_Plane(0,0,1,0);
200 Geom2dInt_GInter Intersector;
202 Standard_Integer NbPoints, NbSegments;
203 Standard_Real U1, U2;
206 // Standard_Real Tol = Precision::Intersection();
207 // modified by NIZHNY-EAP Wed Dec 22 15:00:51 1999 ___BEGIN___
208 Standard_Real Tol = 1.e-6; // BRepFill_Precision();
209 Standard_Real TolC = 0.;
212 Handle(Geom_Curve) C = BRep_Tool::Curve(Edge,L,f,l);
213 CT = new Geom_TrimmedCurve(C,f,l);
214 CT->Transform(L.Transformation());
215 // projection of 3d curves in the plane xOy
216 Handle(Geom2d_Curve) C2d = GeomProjLib::Curve2d(CT,Plane);
218 Geom2dAdaptor_Curve AC(C2d);
219 Geom2dAdaptor_Curve ABis(Bis);
221 Intersector = Geom2dInt_GInter(ABis, AC, TolC, Tol);
223 if ( !Intersector.IsDone()) {
224 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
227 NbPoints = Intersector.NbPoints();
230 // try to elongate curves and enlarge tolerance
232 // don't do it rightaway from the beginning in order not to get
233 // extra solutions those would cause *Exception*: incoherent intersection
235 GeomAbs_CurveType CType = AC.GetType(), BisType = ABis.GetType();
236 Standard_Boolean canElongateC = !(CType == GeomAbs_BezierCurve ||
237 CType == GeomAbs_BSplineCurve ||
238 CType == GeomAbs_OtherCurve);
239 Standard_Boolean canElongateBis = !(BisType == GeomAbs_BezierCurve ||
240 BisType == GeomAbs_BSplineCurve ||
241 BisType == GeomAbs_OtherCurve);
243 Handle(Geom2d_TrimmedCurve) TBis = Handle(Geom2d_TrimmedCurve)::DownCast(Bis);
244 Handle(Geom2d_TrimmedCurve) TC2d = Handle(Geom2d_TrimmedCurve)::DownCast(C2d);
247 TC2d->SetTrim(TC2d->FirstParameter() - Tol, TC2d->LastParameter() + Tol);
250 if (canElongateBis) {
251 TBis->SetTrim(TBis->FirstParameter() - Tol, TBis->LastParameter() + Tol);
254 Intersector = Geom2dInt_GInter(ABis, AC, TolC, Tol*10);
256 if ( !Intersector.IsDone()) {
257 StdFail_NotDone::Raise("BRepFill_TrimSurfaceTool::IntersectWith");
260 NbPoints = Intersector.NbPoints();
262 // modified by NIZHNY-EAP Wed Dec 22 15:00:56 1999 ___END___
265 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
266 U1 = Intersector.Point(i).ParamOnFirst();
267 U2 = Intersector.Point(i).ParamOnSecond();
268 P = gp_Pnt(U1,U2,0.);
273 NbSegments = Intersector.NbSegments();
275 if (NbSegments > 0) {
277 cout << " IntersectWith : " << NbSegments
278 << " Segments of intersection" << endl;
280 IntRes2d_IntersectionSegment Seg;
281 for ( Standard_Integer i = 1; i <= NbSegments; i++) {
282 Seg = Intersector.Segment(i);
283 U1 = Seg.FirstPoint().ParamOnFirst();
284 U1 += Seg.LastPoint().ParamOnFirst();
286 U2 = Seg.FirstPoint().ParamOnSecond();
287 U2 += Seg.LastPoint().ParamOnSecond();
289 P = gp_Pnt(U1,U2,0.);
293 // Order the sequence by increasing parameter on the bissectrice.
296 // modified by NIZHNY-EAP Fri Dec 24 18:47:24 1999 ___BEGIN___
297 // Remove double points
299 for ( Standard_Integer i = 1; i < NbPoints; i++) {
302 if ( P2.X()-P1.X() < Tol ) {
303 // cout<<"REMOVE "<<P1.X()<<endl;
308 // modified by NIZHNY-EAP Fri Dec 24 18:47:28 1999 ___END___
311 // the edge is degenerated : the point and it is found if it is
312 // on the bissectrice.
314 gp_Pnt P3d = BRep_Tool::Pnt( TopExp::FirstVertex(Edge));
315 gp_Pnt2d P2d( P3d.X(), P3d.Y());
317 Standard_Real UBis = Bis->FirstParameter();
318 gp_Pnt2d PBis = Bis->Value( UBis);
320 // modified by NIZHNY-EAP Wed Jan 12 11:41:30 2000 ___BEGIN___
321 // inside gp_Pnt2d::Distance
322 // Infinite * Infinite => Exception: DefaultNumericError
323 // Case encounered: UBis < Precision::Infinite()
324 // but PBis.X() > Precision::Infinite()
325 if (Precision::IsPositiveInfinite(Abs(PBis.X())) ||
326 Precision::IsPositiveInfinite(Abs(PBis.Y())) ||
327 PBis.Distance(P2d) > Tol) {
328 // modified by NIZHNY-EAP Wed Jan 12 11:41:40 2000 ___END___
329 UBis = Bis->LastParameter();
330 if (UBis >= Precision::Infinite()) return;
331 PBis = Bis->Value( UBis);
332 if ( PBis.Distance(P2d) > Tol) return;
335 // evaluate parameter intersection.
336 Handle(Geom_Surface) GS = BRep_Tool::Surface(Face);
337 GeomAdaptor_Surface GAS(GS);
340 Standard_Real Phase = 0.;
342 switch ( GAS.GetType()) {
345 Axis = GAS.Sphere().Position(); break;
347 //----------------------------------------------------------
348 // if myFace1 is not at the same side of the apex as the point
349 // of parameter 0 0 on the cone => phase = M_PI.
350 //----------------------------------------------------------
351 Axis = GAS.Cone().Position();
352 Phase = EvalPhase(Edge,Face,GAS,Axis);
356 Axis = GAS.Torus().Position(); break;
357 case GeomAbs_Cylinder:
358 Axis = GAS.Cylinder().Position(); break;
359 case GeomAbs_SurfaceOfRevolution: {
360 //----------------------------------------------------------
361 // if myFace1 is not at the same side of the apex as the point
362 // of parameter 0 0 on the cone => phase = M_PI.
363 //----------------------------------------------------------
364 Handle(Geom_SurfaceOfRevolution) GSRev =
365 Handle(Geom_SurfaceOfRevolution)::DownCast(GS);
366 Handle(GeomAdaptor_HCurve) HC =
367 new GeomAdaptor_HCurve(GSRev->BasisCurve());
368 Adaptor3d_SurfaceOfRevolution ASRev(HC,GAS.AxeOfRevolution());
370 Phase = EvalPhase(Edge,Face,GAS,Axis);
374 Standard_NotImplemented::Raise(" BRepFill_TrimSurfaceTool");
377 gp_Vec2d D12d = Bis->DN(UBis,1);
378 gp_Vec D1( D12d.X(), D12d.Y(), 0.);
380 Standard_Real U = Axis.XDirection().
381 AngleWithRef(D1,Axis.XDirection()^Axis.YDirection());
383 if ( U < 0.) U += 2*M_PI;
385 P = gp_Pnt(Bis->FirstParameter(), U, 0.);
391 //=======================================================================
392 //function : IntersectWith
394 //=======================================================================
396 void BRepFill_TrimSurfaceTool::IntersectWith
397 (const TopoDS_Edge& EdgeOnF1,
398 const TopoDS_Edge& EdgeOnF2,
399 TColgp_SequenceOfPnt& Points )
403 TColgp_SequenceOfPnt Points2;
405 EvalParameters(EdgeOnF1, myFace1, myBis, Points);
406 EvalParameters(EdgeOnF2, myFace2, myBis, Points2);
408 StdFail_NotDone_Raise_if
409 ( Points.Length() != Points2.Length(),
410 "BRepFill_TrimSurfaceTool::IntersectWith: incoherent intersection");
413 Standard_Integer NbPoints = Points.Length();
414 for ( Standard_Integer i = 1; i <= NbPoints; i++) {
416 PSeq.SetZ((Points2.Value(i)).Y());
417 Points.SetValue(i,PSeq);
418 // cout<<"BisPar "<<PSeq.X()<<endl;
423 //=======================================================================
424 //function : IsOnFace
426 //=======================================================================
428 Standard_Boolean BRepFill_TrimSurfaceTool::IsOnFace
429 (const gp_Pnt2d& Point) const
431 gp_Pnt P( Point.X(), Point.Y(), 0.);
432 gp_Lin Line( P, gp::DZ());
434 BRepIntCurveSurface_Inter Inter;
436 // eval if is on face 1
437 // modified by NIZHNY-EAP Fri Jan 21 09:49:09 2000 ___BEGIN___
438 Inter.Init(myFace1, Line,1e-6);//Precision::PConfusion());
439 if (Inter.More()) return Standard_True;
441 // eval if is on face 2
442 Inter.Init(myFace2, Line, 1e-6);//Precision::PConfusion());
444 // modified by NIZHNY-EAP Fri Jan 21 09:49:14 2000 ___END___
448 //=======================================================================
451 //=======================================================================
453 Standard_Real BRepFill_TrimSurfaceTool::ProjOn(const gp_Pnt2d& Point,
454 const TopoDS_Edge& Edge) const
461 Handle(Geom_Curve) C1 = BRep_Tool::Curve(Edge,L,f,l);
462 Handle(Geom_TrimmedCurve) CT = new Geom_TrimmedCurve(C1,f,l);
463 CT->Transform(L.Transformation());
465 // projection of curves 3d in the plane xOy
466 Handle(Geom_Plane) Plane = new Geom_Plane(0,0,1,0);
467 Handle(Geom2d_Curve) C2d = GeomProjLib::Curve2d(CT,Plane);
469 // evaluate the projection of the point on the curve.
470 Geom2dAPI_ProjectPointOnCurve Projector(Point, C2d);
472 Standard_Real Dist = Projector.LowerDistance();
473 if ( Dist > Precision::Confusion() ) {
474 cout << " *** WARNING TrimSurfaceTool: *** " << endl;
475 cout << " --> the point is not on the edge" <<endl;
476 cout << " distance = " << Dist << endl;
480 Standard_Real U = Projector.LowerDistanceParameter();
485 //=======================================================================
488 //=======================================================================
490 void BRepFill_TrimSurfaceTool::Project
491 (const Standard_Real U1,
492 const Standard_Real U2,
493 Handle(Geom_Curve)& Curve,
494 Handle(Geom2d_Curve)& PCurve1,
495 Handle(Geom2d_Curve)& PCurve2,
496 GeomAbs_Shape& Cont) const
498 Handle(Geom2d_TrimmedCurve) CT =
499 new Geom2d_TrimmedCurve(myBis,U1,U2);
500 BRepFill_MultiLine ML(myFace1,myFace2,
501 myEdge1,myEdge2,myInv1,myInv2,CT);
503 Cont = ML.Continuity();
505 if ( ML.IsParticularCase()) {
506 ML.Curves(Curve,PCurve1,PCurve2);
509 BRepFill_ApproxSeewing AppSeew(ML);
511 Curve = AppSeew.Curve();
512 PCurve1 = AppSeew.CurveOnF1();
513 PCurve2 = AppSeew.CurveOnF2();