1 // Created on: 1998-04-21
2 // Created by: Stephanie HUMEAU
3 // Copyright (c) 1998-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.
18 #include <Adaptor3d_HCurve.hxx>
19 #include <Adaptor3d_HSurface.hxx>
20 #include <Geom_Line.hxx>
21 #include <Geom_Surface.hxx>
22 #include <GeomAdaptor_HCurve.hxx>
23 #include <GeomAdaptor_HSurface.hxx>
24 #include <GeomFill_DraftTrihedron.hxx>
25 #include <GeomFill_FunctionDraft.hxx>
26 #include <GeomFill_LocationDraft.hxx>
27 #include <GeomFill_LocationLaw.hxx>
28 #include <GeomFill_Tensor.hxx>
29 #include <GeomFill_TrihedronLaw.hxx>
34 #include <IntCurveSurface_HInter.hxx>
35 #include <IntCurveSurface_Intersection.hxx>
36 #include <IntCurveSurface_IntersectionPoint.hxx>
37 #include <math_FunctionSetWithDerivatives.hxx>
38 #include <math_Gauss.hxx>
39 #include <math_Matrix.hxx>
40 #include <math_NewtonFunctionSetRoot.hxx>
41 #include <math_Vector.hxx>
42 #include <Standard_NotImplemented.hxx>
43 #include <Standard_OutOfRange.hxx>
44 #include <Standard_Type.hxx>
46 IMPLEMENT_STANDARD_RTTIEXT(GeomFill_LocationDraft,GeomFill_LocationLaw)
48 //==================================================================
49 //Function: GeomFill_LocationDraft
50 //Purpose : constructor
51 //==================================================================
52 GeomFill_LocationDraft::GeomFill_LocationDraft
53 (const gp_Dir& Direction,
54 const Standard_Real Angle)
56 myDir = Direction; // direction de depouille
58 myAngle = Angle; // angle de depouille (teta prime)
61 myLaw = new (GeomFill_DraftTrihedron)(myDir, Angle); // triedre
62 myNbPts = 41; // nb de points utilises pour les calculs
63 myPoles2d = new (TColgp_HArray1OfPnt2d)(1, 2*myNbPts);
64 Intersec = Standard_False; //intersection avec surface d'arret ?
65 WithTrans = Standard_False;
70 //==================================================================
73 //==================================================================
74 Handle(GeomFill_LocationLaw) GeomFill_LocationDraft::Copy() const
76 Handle(GeomFill_TrihedronLaw) law;
78 Handle(GeomFill_LocationDraft) copy =
79 new (GeomFill_LocationDraft) (myDir,myAngle);
80 copy->SetCurve(myCurve);
81 copy->SetStopSurf(mySurf);
82 if (WithTrans) copy->SetTrsf(Trans);
87 //==================================================================
90 //==================================================================
91 void GeomFill_LocationDraft::SetTrsf(const gp_Mat& Transfo)
97 WithTrans = Standard_False; // Au cas ou Trans = I
98 for (Standard_Integer ii=1; ii<=3 && !WithTrans ; ii++)
99 for (Standard_Integer jj=1; jj<=3 && !WithTrans; jj++)
100 if (Abs(Aux.Value(ii, jj)) > 1.e-14) WithTrans = Standard_True;
103 //==================================================================
105 //Purpose : Calcul des poles sur la surfaces d'arret (intersection
106 // entre la generatrice et la surface en myNbPts points de la section)
107 //==================================================================
108 void GeomFill_LocationDraft::SetCurve(const Handle(Adaptor3d_HCurve)& C)
117 //==================================================================
118 //Function: SetStopSurf
120 //==================================================================
121 void GeomFill_LocationDraft::SetStopSurf(const Handle(Adaptor3d_HSurface)& Surf)
127 //==================================================================
130 //==================================================================
131 void GeomFill_LocationDraft::SetAngle(const Standard_Real Angle)
134 myLaw->SetAngle(myAngle);
138 //==================================================================
140 //Purpose : Poses les jalon de l'intersection : depouille / Surface
141 //==================================================================
142 void GeomFill_LocationDraft::Prepare()
144 if (mySurf.IsNull()) {
145 Intersec = Standard_False;
149 Intersec = Standard_True;
151 Standard_Integer ii,jj;
152 Standard_Real f, l, t;
156 IntCurveSurface_IntersectionPoint P1,P2;
157 f = myCurve->FirstParameter();
158 l = myCurve->LastParameter();
160 for (ii=1; ii<=myNbPts; ii++)
162 t = Standard_Real(myNbPts - ii)*f + Standard_Real(ii - 1)*l;
169 D = Cos(myAngle)*B + Sin(myAngle)*N;
171 L = new (Geom_Line) (P, D);
173 IntCurveSurface_HInter Int; // intersection surface / generatrice
174 Handle(GeomAdaptor_HCurve) AC = new (GeomAdaptor_HCurve) (L);
175 Int.Perform(AC, mySurf); // calcul de l'intersection
177 if (Int.NbPoints() > 0) // il y a au moins 1 intersection
179 P1 = Int.Point(1); // 1er point d'intersection
181 for (jj=2 ; jj<=Int.NbPoints() ; jj++)
184 if(P1.W() > P2.W()) P1 = P2; // point le plus proche
187 gp_Pnt2d p (P1.W(), t); // point de la courbe
188 gp_Pnt2d q (P1.U(),P1.V()); // point sur la surface
189 myPoles2d->SetValue(2*ii-1,p); // point de la courbe (indice impair)
190 myPoles2d->SetValue(2*ii,q); // point sur la surface (indice pair)
193 {// au moins un point ou il n'y a pas intersection
194 Intersec = Standard_False;
200 //==================================================================
202 //Purpose : return the path
203 //==================================================================
204 const Handle(Adaptor3d_HCurve)& GeomFill_LocationDraft::GetCurve() const
210 //==================================================================
213 //==================================================================
214 Standard_Boolean GeomFill_LocationDraft::D0(const Standard_Real Param,
222 myTrimmed->D0(Param, P);
225 Ok = myLaw->D0(Param, T, N, B);
227 M.SetCols(N.XYZ(), B.XYZ(), T.XYZ());
233 return Standard_True;
236 //==================================================================
238 //Purpose : calcul de l'intersection (C0) sur la surface
239 //==================================================================
240 Standard_Boolean GeomFill_LocationDraft::D0(const Standard_Real Param,
243 TColgp_Array1OfPnt2d& Poles2d)
246 // gp_Vec D,T,N,B,DT,DN,DB;
250 myCurve->D0(Param, P);
252 Ok = myLaw->D0(Param, T, N, B);
254 M.SetCols(N.XYZ(), B.XYZ(), T.XYZ());
260 if (Intersec == Standard_True) {
261 // la generatrice intersecte la surface d'arret
263 D = Cos(myAngle)*B + Sin(myAngle)*N;
265 Handle(Geom_Line) L = new (Geom_Line) (P, D);
266 Handle(GeomAdaptor_HCurve) G = new (GeomAdaptor_HCurve) (L);
268 Standard_Real t1,t2,Paramt1,t2Param;
269 Standard_Real U0=0,V0=0,W0=0;
271 Standard_Integer ii = 1;
273 // on recherche l'intervalle auquel appartient Param
274 while (ii<2*myNbPts && myPoles2d->Value(ii).Coord(2) < Param) ii=ii+2;
276 if (ii<2*myNbPts && !IsEqual(myPoles2d->Value(ii).Coord(2),Param))
279 // interpolation lineaire pour initialiser le germe de la recherche
280 t1 = myPoles2d->Value(ii).Coord(2);
281 t2 = myPoles2d->Value(ii-2).Coord(2);
283 Paramt1 = (Param-t1) / (t2-t1);
284 t2Param = (t2-Param) / (t2-t1);
286 W0 = myPoles2d->Value(ii-2).Coord(1)*Paramt1
287 + myPoles2d->Value(ii).Coord(1)*t2Param;
288 U0 = myPoles2d->Value(ii-1).Coord(1)*Paramt1
289 + myPoles2d->Value(ii+1).Coord(1)*t2Param;
290 V0 = myPoles2d->Value(ii-1).Coord(2)*Paramt1
291 + myPoles2d->Value(ii+1).Coord(2)*t2Param;
293 // on est sur un param ou les points ont deja ete calcules
294 else if (ii<2*myNbPts && IsEqual(myPoles2d->Value(ii).Coord(2) ,Param))
296 W0 = myPoles2d->Value(ii).Coord(1);
297 U0 = myPoles2d->Value(ii+1).Coord(1);
298 V0 = myPoles2d->Value(ii+1).Coord(2);
301 // recherche de la solution (pt d'intersection generatrice / surface)
309 math_Vector XTol(1,3);
313 Standard_Real FTol = 0.0000001;
314 Standard_Integer Iter = 100;
316 // fonction dont il faut trouver la racine : G(W)-S(U,V)=0
317 GeomFill_FunctionDraft E(mySurf , G);
320 math_NewtonFunctionSetRoot Result(E, XTol, FTol, Iter);
321 Result.Perform(E, X);
326 Result.Root(R); // solution
328 gp_Pnt2d p (R(2), R(3)); // point sur la surface
329 gp_Pnt2d q (R(1), Param); // point de la courbe
330 Poles2d.SetValue(1,p);
331 Poles2d.SetValue(2,q);
334 return Standard_False;
338 // la generatrice n'intersecte pas la surface d'arret
339 return Standard_True;
342 //==================================================================
344 //Purpose : calcul de l'intersection (C1) sur la surface
345 //==================================================================
346 Standard_Boolean GeomFill_LocationDraft::D1(const Standard_Real Param,
351 TColgp_Array1OfPnt2d& Poles2d,
352 TColgp_Array1OfVec2d& DPoles2d)
355 gp_Vec D,T,N,B,DT,DN,DB;
358 myCurve->D1(Param, P, DV);
361 Ok = myLaw->D1(Param, T, DT, N, DN, B, DB);
362 if (!Ok) return Standard_False;
364 M.SetCols(N.XYZ(), B.XYZ(), T.XYZ());
365 DM.SetCols(DN.XYZ(), DB.XYZ(), DT.XYZ());
372 if (Intersec == Standard_True)
373 { // la generatrice intersecte la surface d'arret
375 D = Cos(myAngle)*B + Sin(myAngle)*N;
377 Handle(Geom_Line) L = new (Geom_Line) (P, D);
378 Handle(GeomAdaptor_HCurve) G = new (GeomAdaptor_HCurve) (L);
380 Standard_Real t1,t2,Paramt1,t2Param;
381 Standard_Real U0=0,V0=0,W0=0;
383 Standard_Integer ii = 1;
385 // recherche de la solution (pt d'intersection generatrice / surface)
387 // on recherche l'intervalle auquel appartient Param
388 while (ii < 2*myNbPts && myPoles2d->Value(ii).Coord(2) < Param) ii=ii+2;
391 if (ii < 2*myNbPts && !IsEqual(myPoles2d->Value(ii).Coord(2) ,Param))
393 // interpolation lineaire pour initialiser le germe de la recherche
394 t1 = myPoles2d->Value(ii).Coord(2);
395 t2 = myPoles2d->Value(ii-2).Coord(2);
397 Paramt1 = (Param-t1) / (t2-t1);
398 t2Param = (t2-Param) / (t2-t1);
400 W0 = myPoles2d->Value(ii-2).Coord(1)*Paramt1
401 + myPoles2d->Value(ii).Coord(1)*t2Param;
402 U0 = myPoles2d->Value(ii-1).Coord(1)*Paramt1
403 + myPoles2d->Value(ii+1).Coord(1)*t2Param;
404 V0 = myPoles2d->Value(ii-1).Coord(2)*Paramt1
405 + myPoles2d->Value(ii+1).Coord(2)*t2Param;
407 else if (ii<2*myNbPts && IsEqual(myPoles2d->Value(ii).Coord(2) ,Param))
409 W0 = myPoles2d->Value(ii).Coord(1);
410 U0 = myPoles2d->Value(ii+1).Coord(1);
411 V0 = myPoles2d->Value(ii+1).Coord(2);
421 math_Vector XTol(1,3);
425 Standard_Real FTol = 0.000001;
426 Standard_Integer Iter = 100;
429 // fonction dont il faut trouver la racine : G(W)-S(U,V)=0
430 GeomFill_FunctionDraft E(mySurf,G);
434 math_NewtonFunctionSetRoot Result(E, XTol, FTol, Iter);
435 Result.Perform(E, X);
440 Result.Root(R); // solution
442 gp_Pnt2d p (R(2), R(3)); // point sur la surface
443 gp_Pnt2d q (R(1), Param); // point de la courbe
444 Poles2d.SetValue(1,p);
445 Poles2d.SetValue(2,q);
447 // derivee de la fonction par rapport a Param
448 math_Vector DEDT(1,3,0);
449 E.DerivT(myTrimmed, Param, R(1), DN, myAngle, DEDT); // dE/dt => DEDT
451 math_Vector DSDT (1,3,0);
452 math_Matrix DEDX (1,3,1,3,0);
453 E.Derivatives(R, DEDX); // dE/dx au point R => DEDX
455 // resolution du syst. lin. : DEDX*DSDT = -DEDT
459 Ga.Solve (DEDT.Opposite(), DSDT); // resolution du syst. lin.
460 gp_Vec2d dp (DSDT(2), DSDT(3)); // surface
461 gp_Vec2d dq (DSDT(1), 1); // courbe
462 DPoles2d.SetValue(1, dp);
463 DPoles2d.SetValue(2, dq);
468 else {// la generatrice n'intersecte pas la surface d'arret
469 return Standard_False;
472 return Standard_True;
475 //==================================================================
477 //Purpose : calcul de l'intersection (C2) sur la surface
478 //==================================================================
479 Standard_Boolean GeomFill_LocationDraft::D2(const Standard_Real Param,
486 TColgp_Array1OfPnt2d& Poles2d,
487 TColgp_Array1OfVec2d& DPoles2d,
488 TColgp_Array1OfVec2d& D2Poles2d)
491 gp_Vec D,T,N,B,DT,DN,DB,D2T,D2N,D2B;
494 myCurve->D2(Param, P, DV, D2V);
497 Ok = myLaw->D2(Param, T, DT, D2T, N, DN, D2N, B, DB, D2B);
500 M.SetCols(N.XYZ(), B.XYZ(), T.XYZ());
501 DM.SetCols(DN.XYZ(), DB.XYZ(), DT.XYZ());
502 D2M.SetCols(D2N.XYZ(), D2B.XYZ(), D2T.XYZ());
509 if (Intersec == Standard_True)
510 {// la generatrice intersecte la surface d'arret
513 D = Cos(myAngle) * B + Sin(myAngle) * N;
515 Handle(Geom_Line) L = new (Geom_Line) (P, D);
516 Handle(GeomAdaptor_HCurve) G = new (GeomAdaptor_HCurve) (L);
518 Standard_Real t1,t2,Paramt1,t2Param;
519 Standard_Real U0=0,V0=0,W0=0;
521 Standard_Integer ii = 1;
523 // on recherche l'intervalle auquel appartient Param
524 while (ii<2*myNbPts && myPoles2d->Value(ii).Coord(2) < Param) ii=ii+2;
526 if (ii<2*myNbPts && !IsEqual(myPoles2d->Value(ii).Coord(2) ,Param))
529 // interpolation lineaire pour initialiser le germe de la recherche
530 t1 = myPoles2d->Value(ii).Coord(2);
531 t2 = myPoles2d->Value(ii-2).Coord(2);
533 Paramt1 = (Param-t1) / (t2-t1);
534 t2Param = (t2-Param) / (t2-t1);
536 W0 = myPoles2d->Value(ii-2).Coord(1)*Paramt1 +
537 myPoles2d->Value(ii).Coord(1)*t2Param;
538 U0 = myPoles2d->Value(ii-1).Coord(1)*Paramt1 +
539 myPoles2d->Value(ii+1).Coord(1)*t2Param;
540 V0 = myPoles2d->Value(ii-1).Coord(2)*Paramt1 +
541 myPoles2d->Value(ii+1).Coord(2)*t2Param;
543 else if (ii<2*myNbPts && IsEqual(myPoles2d->Value(ii).Coord(2) ,Param))
545 W0 = myPoles2d->Value(ii).Coord(1);
546 U0 = myPoles2d->Value(ii+1).Coord(1);
547 V0 = myPoles2d->Value(ii+1).Coord(2);
550 // recherche de la solution (pt d'intersection generatrice / surface)
558 math_Vector XTol(1,3);
562 Standard_Real FTol = 0.000001;
563 Standard_Integer Iter = 150;
566 // fonction dont il faut trouver la racine : G(W)-S(U,V)=0
567 GeomFill_FunctionDraft E(mySurf,G);
571 math_NewtonFunctionSetRoot Result (E, XTol, FTol, Iter);
572 Result.Perform(E, X);
577 Result.Root(R); // solution
580 gp_Pnt2d p (R(2), R(3)); // point sur la surface
581 gp_Pnt2d q (R(1), Param); // point de la courbe
582 Poles2d.SetValue(1,p);
583 Poles2d.SetValue(2,q);
586 // premiere derivee de la fonction
587 math_Vector DEDT(1,3,0);
588 E.DerivT(myTrimmed, Param, R(1), DN, myAngle, DEDT); // dE/dt => DEDT
590 math_Vector DSDT (1,3,0);
591 math_Matrix DEDX (1,3,1,3,0);
592 E.Derivatives(R, DEDX); // dE/dx => DEDX
594 // resolution du syst. lin.
595 math_Gauss Ga (DEDX);
598 Ga.Solve (DEDT.Opposite(), DSDT);
599 gp_Vec2d dp (DSDT(2), DSDT(3)); // surface
600 gp_Vec2d dq (DSDT(1), 1); // courbe
601 DPoles2d.SetValue(1, dp);
602 DPoles2d.SetValue(2, dq);
607 GeomFill_Tensor D2EDX2(3,3,3);
608 E.Deriv2X(R, D2EDX2); // d2E/dx2
610 math_Vector D2EDT2(1,3,0);
611 E.Deriv2T(myTrimmed, Param, R(1), D2N, myAngle ,D2EDT2); // d2E/dt2
613 math_Matrix D2EDTDX(1,3,1,3,0);
614 E.DerivTX(DN, myAngle, D2EDTDX); // d2E/dtdx
616 math_Vector D2SDT2(1,3,0); // d2s/dt2
617 math_Matrix aT(1,3,1,3,0);
618 D2EDX2.Multiply(DSDT,aT);
620 // resolution du syst. lin.
621 math_Gauss Ga1 (DEDX);
624 Ga1.Solve ( -aT*DSDT - 2*D2EDTDX*DSDT - D2EDT2 , D2SDT2);
625 gp_Vec2d d2p (D2SDT2(2), D2SDT2(3)); // surface
626 gp_Vec2d d2q (D2SDT2(1), 0); // courbe
627 D2Poles2d.SetValue(1, d2p);
628 D2Poles2d.SetValue(2, d2q);
630 else {// la generatrice n'intersecte pas la surface d'arret
631 return Standard_False;
636 return Standard_True;
639 //==================================================================
640 //Function : HasFirstRestriction
642 //==================================================================
643 Standard_Boolean GeomFill_LocationDraft::HasFirstRestriction() const
645 return Standard_False;
648 //==================================================================
649 //Function : HasLastRestriction
651 //==================================================================
652 Standard_Boolean GeomFill_LocationDraft::HasLastRestriction() const
655 if (Intersec == Standard_True) return Standard_True;
656 else return Standard_False;
659 //==================================================================
660 //Function : TraceNumber
662 //==================================================================
663 Standard_Integer GeomFill_LocationDraft::TraceNumber() const
665 if (Intersec == Standard_True) return 1;
669 //==================================================================
670 //Function:NbIntervals
672 //==================================================================
673 Standard_Integer GeomFill_LocationDraft::NbIntervals
674 (const GeomAbs_Shape S) const
676 return myLaw->NbIntervals(S);
679 //==================================================================
682 //==================================================================
683 void GeomFill_LocationDraft::Intervals(TColStd_Array1OfReal& T,
684 const GeomAbs_Shape S) const
686 myLaw->Intervals(T, S);
689 //==================================================================
690 //Function:SetInterval
692 //==================================================================
693 void GeomFill_LocationDraft::SetInterval(const Standard_Real First,
694 const Standard_Real Last)
696 myLaw->SetInterval( First, Last);
697 myTrimmed = myCurve->Trim( First, Last, 0);
699 //==================================================================
700 //Function: GetInterval
702 //==================================================================
703 void GeomFill_LocationDraft::GetInterval(Standard_Real& First,
704 Standard_Real& Last) const
706 First = myTrimmed->FirstParameter();
707 Last = myTrimmed->LastParameter();
710 //==================================================================
711 //Function: GetDomain
713 //==================================================================
714 void GeomFill_LocationDraft::GetDomain(Standard_Real& First,
715 Standard_Real& Last) const
717 First = myCurve->FirstParameter();
718 Last = myCurve->LastParameter();
721 //==================================================================
722 //function : Resolution
724 //==================================================================
725 void GeomFill_LocationDraft::Resolution (const Standard_Integer Index,
726 const Standard_Real Tol,
728 Standard_Real& TolV) const
732 TolU = mySurf->UResolution(Tol);
733 TolV = mySurf->VResolution(Tol);
741 //==================================================================
742 //Function:GetMaximalNorm
743 //Purpose : On suppose les triedres normes => return 1
744 //==================================================================
745 Standard_Real GeomFill_LocationDraft::GetMaximalNorm()
750 //==================================================================
751 //Function:GetAverageLaw
753 //==================================================================
754 void GeomFill_LocationDraft::GetAverageLaw(gp_Mat& AM,
758 Standard_Real U, delta;
761 myLaw->GetAverageLaw(V1, V2, V3);
762 AM.SetCols(V1.XYZ(), V2.XYZ(), V3.XYZ());
764 AV.SetCoord(0., 0., 0.);
765 delta = (myTrimmed->LastParameter() - myTrimmed->FirstParameter())/10;
766 U= myTrimmed->FirstParameter();
767 for (ii=0; ii<=10; ii++, U+=delta) {
768 V.SetXYZ( myTrimmed->Value(U).XYZ() );
774 //==================================================================
775 //Function : IsTranslation
777 //==================================================================
778 // Standard_Boolean GeomFill_LocationDraft::IsTranslation(Standard_Real& Error) const
779 Standard_Boolean GeomFill_LocationDraft::IsTranslation(Standard_Real& ) const
781 return myLaw->IsConstant();
784 //==================================================================
785 //Function : IsRotation
787 //==================================================================
788 Standard_Boolean GeomFill_LocationDraft::IsRotation(Standard_Real& Error) const
790 GeomAbs_CurveType Type;
792 Type = myCurve->GetType();
793 if (Type == GeomAbs_Circle) {
794 return myLaw->IsOnlyBy3dCurve();
796 return Standard_False;
799 //==================================================================
800 //Function : Rotation
802 //==================================================================
803 void GeomFill_LocationDraft::Rotation(gp_Pnt& Centre) const
805 Centre = myCurve->Circle().Location();
809 //==================================================================
810 //Function : IsIntersec
812 //==================================================================
813 Standard_Boolean GeomFill_LocationDraft::IsIntersec() const
819 //==================================================================
820 //Function : Direction
822 //==================================================================
823 gp_Dir GeomFill_LocationDraft::Direction() const