1 // Created on: 1998-06-02
2 // Created by: Philippe NOUAILLE
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 <Blend_Point.hxx>
21 #include <BlendFunc.hxx>
22 #include <BlendFunc_ChAsym.hxx>
27 #include <gp_Vec2d.hxx>
28 #include <math_Gauss.hxx>
29 #include <math_Matrix.hxx>
30 #include <math_SVD.hxx>
31 #include <Precision.hxx>
32 #include <Standard_NotImplemented.hxx>
34 //=======================================================================
35 //function : BlendFunc_ChAsym
37 //=======================================================================
38 BlendFunc_ChAsym::BlendFunc_ChAsym(const Handle(Adaptor3d_HSurface)& S1,
39 const Handle(Adaptor3d_HSurface)& S2,
40 const Handle(Adaptor3d_HCurve)& C) :
45 istangent(Standard_True),
51 //=======================================================================
52 //function : NbEquations
54 //=======================================================================
56 Standard_Integer BlendFunc_ChAsym::NbEquations () const
63 //=======================================================================
66 //=======================================================================
68 void BlendFunc_ChAsym::Set(const Standard_Real Param)
73 //=======================================================================
75 //purpose : Segmente la courbe a sa partie utile.
76 // La precision est prise arbitrairement petite !?
77 //=======================================================================
79 void BlendFunc_ChAsym::Set(const Standard_Real First, const Standard_Real Last)
81 tcurv = curv->Trim(First, Last, 1.e-12);
84 //=======================================================================
85 //function : GetTolerance
87 //=======================================================================
89 void BlendFunc_ChAsym::GetTolerance(math_Vector& Tolerance, const Standard_Real Tol) const
91 Tolerance(1) = surf1->UResolution(Tol);
92 Tolerance(2) = surf1->VResolution(Tol);
93 Tolerance(3) = surf2->UResolution(Tol);
94 Tolerance(4) = surf2->VResolution(Tol);
98 //=======================================================================
99 //function : GetBounds
101 //=======================================================================
103 void BlendFunc_ChAsym::GetBounds(math_Vector& InfBound, math_Vector& SupBound) const
105 InfBound(1) = surf1->FirstUParameter();
106 InfBound(2) = surf1->FirstVParameter();
107 InfBound(3) = surf2->FirstUParameter();
108 InfBound(4) = surf2->FirstVParameter();
109 SupBound(1) = surf1->LastUParameter();
110 SupBound(2) = surf1->LastVParameter();
111 SupBound(3) = surf2->LastUParameter();
112 SupBound(4) = surf2->LastVParameter();
114 for(Standard_Integer i = 1; i <= 4; i++){
115 if(!Precision::IsInfinite(InfBound(i)) &&
116 !Precision::IsInfinite(SupBound(i))) {
117 const Standard_Real range = (SupBound(i) - InfBound(i));
118 InfBound(i) -= range;
119 SupBound(i) += range;
125 //=======================================================================
126 //function : IsSolution
128 //=======================================================================
130 Standard_Boolean BlendFunc_ChAsym::IsSolution(const math_Vector& Sol, const Standard_Real Tol)
132 math_Vector valsol(1, 4), secmember(1, 4);
133 math_Matrix gradsol(1, 4, 1, 4);
136 gp_Vec np, dnp, d1gui, d2gui, Nsurf1, dwtsurf1;
137 gp_Vec d1u1, d1v1, d1u2, d1v2;
140 tcurv->D2(param, ptgui, d1gui, d2gui);
141 Normg = d1gui.Magnitude();
142 np = d1gui.Normalized();
143 dnp = (d2gui - np.Dot(d2gui) * np) / Normg;
151 surf1->D1(Sol(1), Sol(2), pt1, d1u1, d1v1);
152 Nsurf1 = d1u1.Crossed(d1v1);
153 tsurf1 = Nsurf1.Crossed(np);
154 dwtsurf1 = Nsurf1.Crossed(dnp);
156 surf2->D1(Sol(3), Sol(4), pt2, d1u2, d1v2);
158 gp_Vec pguis1(ptgui, pt1), pguis2(ptgui, pt2);
159 gp_Vec CrossVec, s1s2(pt1, pt2);
160 Standard_Real PScaInv = 1. / tsurf1.Dot(s1s2), F4, temp;
161 Standard_Real maxpiv = 1.e-9;
162 Standard_Real Nordu1 = d1u1.Magnitude(),
163 Nordv1 = d1v1.Magnitude();
165 temp = 2. * (Nordu1 + Nordv1) * s1s2.Magnitude() + 2. * Nordu1 * Nordv1;
167 Values(Sol, valsol, gradsol);
169 if (Abs(valsol(1)) < Tol &&
170 Abs(valsol(2)) < Tol &&
171 Abs(valsol(3)) < 2. * dist1 * Tol &&
172 Abs(valsol(4)) < Tol * (1. + tgang) * Abs(PScaInv) * temp) {
174 secmember(1) = Normg - dnp.Dot(pguis1);
175 secmember(2) = Normg - dnp.Dot(pguis2);
176 secmember(3) = - 2. * d1gui.Dot(pguis1);
178 CrossVec = tsurf1.Crossed(s1s2);
179 F4 = np.Dot(CrossVec) * PScaInv;
180 temp = dnp.Dot(CrossVec) + np.Dot(dwtsurf1.Crossed(s1s2));
182 temp -= F4 * dwtsurf1.Dot(s1s2);
183 secmember(4) = PScaInv * temp;
185 math_Gauss Resol(gradsol, maxpiv);
187 if (Resol.IsDone()) {
188 Resol.Solve(secmember);
189 istangent = Standard_False;
192 math_SVD SingRS (gradsol);
193 if (SingRS.IsDone()) {
194 math_Vector DEDT(1,4);
196 SingRS.Solve(DEDT, secmember, 1.e-6);
197 istangent = Standard_False;
199 else istangent = Standard_True;
203 tg1.SetLinearForm(secmember(1), d1u1, secmember(2), d1v1);
204 tg2.SetLinearForm(secmember(3), d1u2, secmember(4), d1v2);
205 tg12d.SetCoord(secmember(1),secmember(2));
206 tg22d.SetCoord(secmember(3),secmember(4));
209 distmin = Min( distmin, pt1.Distance(pt2));
211 return Standard_True;
214 istangent = Standard_True;
215 return Standard_False;
219 //=======================================================================
220 //function : GetMinimalDistance
222 //=======================================================================
224 Standard_Real BlendFunc_ChAsym::GetMinimalDistance() const
229 //=======================================================================
230 //function : ComputeValues
232 //=======================================================================
233 Standard_Boolean BlendFunc_ChAsym::ComputeValues(const math_Vector& X,
234 const Standard_Integer DegF,
235 const Standard_Integer DegL)
237 if (DegF > DegL) return Standard_False;
239 gp_Vec np, d1gui, d1u1, d1v1, d2u1, d2v1, d2uv1, d1u2, d1v2, Nsurf1;
241 Standard_Real PScaInv, F4;
243 tcurv->D1(param, ptgui, d1gui);
244 nplan = d1gui.Normalized();
247 if (choix%2 != 0) np.Reverse();
249 if ( (DegF == 0) && (DegL == 0) ) {
250 surf1->D1(X(1), X(2), pt1, d1u1, d1v1);
251 pt2 = surf2->Value(X(3), X(4));
254 surf1->D2(X(1), X(2), pt1, d1u1, d1v1, d2u1, d2v1, d2uv1);
255 surf2->D1(X(3), X(4), pt2, d1u2, d1v2);
258 Nsurf1 = d1u1.Crossed(d1v1);
259 tsurf1 = Nsurf1.Crossed(np);
261 gp_Vec nps1(ptgui, pt1), s1s2(pt1, pt2);//, tempVec;
262 PScaInv = 1. / tsurf1.Dot(s1s2);
263 F4 = np.Dot(tsurf1.Crossed(s1s2)) * PScaInv;
267 Dist = ptgui.XYZ().Dot(np.XYZ());
269 FX(1) = pt1.XYZ().Dot(np.XYZ()) - Dist;
270 FX(2) = pt2.XYZ().Dot(np.XYZ()) - Dist;
271 FX(3) = dist1 * dist1 - nps1.SquareMagnitude();
278 gp_Vec d1utsurf1, d1vtsurf1;
279 d1utsurf1 = (d2u1.Crossed(d1v1) + d1u1.Crossed(d2uv1)).Crossed(np);
280 d1vtsurf1 = (d2uv1.Crossed(d1v1) + d1u1.Crossed(d2v1)).Crossed(np);
282 DX(1, 1) = np.Dot(d1u1);
283 DX(1, 2) = np.Dot(d1v1);
289 DX(2, 3) = np.Dot(d1u2);
290 DX(2, 4) = np.Dot(d1v2);
292 tempVec = -2. * nps1;
293 DX(3, 1) = d1u1.Dot(tempVec);
294 DX(3, 2) = d1v1.Dot(tempVec);
298 temp = F4 * (d1utsurf1.Dot(s1s2) - tsurf1.Dot(d1u1));
299 temp += np.Dot(tsurf1.Crossed(d1u1) - d1utsurf1.Crossed(s1s2));
300 DX(4, 1) = temp * PScaInv;
302 temp = F4 * (d1vtsurf1.Dot(s1s2) - tsurf1.Dot(d1v1));
303 temp += np.Dot(tsurf1.Crossed(d1v1) - d1vtsurf1.Crossed(s1s2));
304 DX(4, 2) = temp * PScaInv;
306 temp = F4 * tsurf1.Dot(d1u2) - np.Dot(tsurf1.Crossed(d1u2));
307 DX(4, 3) = temp * PScaInv;
309 temp = F4 * tsurf1.Dot(d1v2) - np.Dot(tsurf1.Crossed(d1v2));
310 DX(4, 4) = temp * PScaInv;
313 return Standard_True;
318 //=======================================================================
321 //=======================================================================
323 Standard_Boolean BlendFunc_ChAsym::Value(const math_Vector& X, math_Vector& F)
325 const Standard_Boolean Error = ComputeValues(X, 0, 0);
331 //=======================================================================
332 //function : Derivatives
334 //=======================================================================
336 Standard_Boolean BlendFunc_ChAsym::Derivatives(const math_Vector& X, math_Matrix& D)
338 const Standard_Boolean Error = ComputeValues(X, 1, 1);
344 //=======================================================================
347 //=======================================================================
349 Standard_Boolean BlendFunc_ChAsym::Values(const math_Vector& X, math_Vector& F, math_Matrix& D)
351 const Standard_Boolean Error = ComputeValues(X, 0, 1);
358 //=======================================================================
359 //function : PointOnS1
361 //=======================================================================
363 const gp_Pnt& BlendFunc_ChAsym::PointOnS1 () const
369 //=======================================================================
370 //function : PointOnS2
372 //=======================================================================
374 const gp_Pnt& BlendFunc_ChAsym::PointOnS2 () const
380 //=======================================================================
381 //function : IsTangencyPoint
383 //=======================================================================
385 Standard_Boolean BlendFunc_ChAsym::IsTangencyPoint () const
391 //=======================================================================
392 //function : TangentOnS1
394 //=======================================================================
396 const gp_Vec& BlendFunc_ChAsym::TangentOnS1 () const
399 throw Standard_DomainError("BlendFunc_ChAsym::TangentOnS1");
404 //=======================================================================
405 //function : Tangent2dOnS1
407 //=======================================================================
409 const gp_Vec2d& BlendFunc_ChAsym::Tangent2dOnS1 () const
412 throw Standard_DomainError("BlendFunc_ChAsym::Tangent2dOnS1");
416 //=======================================================================
417 //function : TangentOnS2
419 //=======================================================================
421 const gp_Vec& BlendFunc_ChAsym::TangentOnS2 () const
424 throw Standard_DomainError("BlendFunc_ChAsym::TangentOnS2");
429 //=======================================================================
430 //function : Tangent2dOnS2
432 //=======================================================================
434 const gp_Vec2d& BlendFunc_ChAsym::Tangent2dOnS2 () const
437 throw Standard_DomainError("BlendFunc_ChAsym::Tangent2dOnS2");
442 //=======================================================================
443 //function : TwistOnS1
445 //=======================================================================
447 Standard_Boolean BlendFunc_ChAsym::TwistOnS1() const
450 throw Standard_DomainError("BlendFunc_ChAsym::TwistOnS1");
451 return tg1.Dot(nplan) < 0.;
454 //=======================================================================
455 //function : TwistOnS2
457 //=======================================================================
459 Standard_Boolean BlendFunc_ChAsym::TwistOnS2() const
462 throw Standard_DomainError("BlendFunc_ChAsym::TwistOnS2");
463 return tg2.Dot(nplan) < 0.;
466 //=======================================================================
468 //purpose : TgF,NmF et TgL,NmL les tangentes et normales respectives
469 // aux surfaces S1 et S2
470 //=======================================================================
472 void BlendFunc_ChAsym::Tangent(const Standard_Real U1,
473 const Standard_Real V1,
474 const Standard_Real U2,
475 const Standard_Real V2,
481 gp_Pnt Pt1,Pt2,ptgui;
482 gp_Vec d1u1,d1v1,d1u2,d1v2;
484 Standard_Boolean revF = Standard_False;
485 Standard_Boolean revL = Standard_False;
487 tcurv->D1(param, ptgui, d1gui);
488 np = d1gui.Normalized();
490 surf1->D1(U1,V1,Pt1,d1u1,d1v1);
491 NmF = d1u1.Crossed(d1v1);
493 surf2->D1(U2,V2,Pt2,d1u2,d1v2);
494 NmL = d1u2.Crossed(d1v2);
496 TgF = (np.Crossed(NmF)).Normalized();
497 TgL = (np.Crossed(NmL)).Normalized();
499 if ( (choix == 2)||(choix == 5) ){
500 revF = Standard_True;
501 revL = Standard_True;
504 if ( (choix == 4)||(choix == 7) )
505 revL = Standard_True;
507 if ( (choix == 3)||(choix == 8) )
508 revF = Standard_True;
518 //=======================================================================
521 //=======================================================================
523 void BlendFunc_ChAsym::Section(const Standard_Real /*Param*/,
524 const Standard_Real U1,
525 const Standard_Real V1,
526 const Standard_Real U2,
527 const Standard_Real V2,
532 const gp_Pnt Pt1 = surf1->Value(U1,V1);
533 const gp_Pnt Pt2 = surf2->Value(U2,V2);
534 const gp_Dir dir( gp_Vec(Pt1,Pt2) );
540 Pfin = ElCLib::Parameter(C, Pt2);
544 //=======================================================================
545 //function : IsRational
547 //=======================================================================
549 Standard_Boolean BlendFunc_ChAsym::IsRational () const
551 return Standard_False;
554 //=======================================================================
555 //function : GetSectionSize
557 //=======================================================================
558 Standard_Real BlendFunc_ChAsym::GetSectionSize() const
560 throw Standard_NotImplemented("BlendFunc_ChAsym::GetSectionSize()");
563 //=======================================================================
564 //function : GetMinimalWeight
566 //=======================================================================
567 void BlendFunc_ChAsym::GetMinimalWeight(TColStd_Array1OfReal& Weights) const
572 //=======================================================================
573 //function : NbIntervals
575 //=======================================================================
577 Standard_Integer BlendFunc_ChAsym::NbIntervals (const GeomAbs_Shape S) const
579 return curv->NbIntervals(BlendFunc::NextShape(S));
583 //=======================================================================
584 //function : Intervals
586 //=======================================================================
588 void BlendFunc_ChAsym::Intervals (TColStd_Array1OfReal& T, const GeomAbs_Shape S) const
590 curv->Intervals(T, BlendFunc::NextShape(S));
593 //=======================================================================
594 //function : GetShape
596 //=======================================================================
598 void BlendFunc_ChAsym::GetShape (Standard_Integer& NbPoles,
599 Standard_Integer& NbKnots,
600 Standard_Integer& Degree,
601 Standard_Integer& NbPoles2d)
609 //=======================================================================
610 //function : GetTolerance
611 //purpose : Determine les Tolerances a utiliser dans les approximations.
612 //=======================================================================
613 void BlendFunc_ChAsym::GetTolerance(const Standard_Real BoundTol,
619 Tol3d.Init(BoundTol);
622 //=======================================================================
625 //=======================================================================
627 void BlendFunc_ChAsym::Knots(TColStd_Array1OfReal& TKnots)
634 //=======================================================================
637 //=======================================================================
639 void BlendFunc_ChAsym::Mults(TColStd_Array1OfInteger& TMults)
646 //=======================================================================
649 //=======================================================================
651 void BlendFunc_ChAsym::Section(const Blend_Point& P,
652 TColgp_Array1OfPnt& Poles,
653 TColgp_Array1OfPnt2d& Poles2d,
654 TColStd_Array1OfReal& Weights)
656 Standard_Real u1, v1, u2, v2, prm = P.Parameter();
657 Standard_Integer low = Poles.Lower();
658 Standard_Integer upp = Poles.Upper();
659 math_Vector X(1,4), F(1,4);
661 P.ParametersOnS1(u1, v1);
662 P.ParametersOnS2(u2, v2);
667 Poles2d(Poles2d.Lower()).SetCoord(u1,v1);
668 Poles2d(Poles2d.Upper()).SetCoord(u2,v2);
672 Poles(low) = PointOnS1();
673 Poles(upp) = PointOnS2();
679 //=======================================================================
682 //=======================================================================
684 Standard_Boolean BlendFunc_ChAsym::Section
685 (const Blend_Point& P,
686 TColgp_Array1OfPnt& Poles,
687 TColgp_Array1OfVec& DPoles,
688 TColgp_Array1OfPnt2d& Poles2d,
689 TColgp_Array1OfVec2d& DPoles2d,
690 TColStd_Array1OfReal& Weights,
691 TColStd_Array1OfReal& DWeights)
693 math_Vector Sol(1, 4), valsol(1, 4), secmember(1, 4);
694 math_Matrix gradsol(1, 4, 1, 4);
695 Standard_Real prm = P.Parameter();
696 Standard_Integer low = Poles.Lower();
697 Standard_Integer upp = Poles.Upper();
699 P.ParametersOnS1(Sol(1),Sol(2));
700 P.ParametersOnS2(Sol(3),Sol(4));
703 Poles2d(Poles2d.Lower()).SetCoord(Sol(1),Sol(2));
704 Poles2d(Poles2d.Upper()).SetCoord(Sol(3),Sol(4));
705 Poles(low) = PointOnS1();
706 Poles(upp) = PointOnS2();
711 gp_Vec np, dnp, d1gui, d2gui, Nsurf1, dwtsurf1;
712 gp_Vec d1u1, d1v1, d1u2, d1v2;
715 tcurv->D2(param, ptgui, d1gui, d2gui);
716 Normg = d1gui.Magnitude();
717 np = d1gui.Normalized();
718 dnp = (d2gui - np.Dot(d2gui) * np) / Normg;
726 surf1->D1(Sol(1), Sol(2), pt1, d1u1, d1v1);
727 Nsurf1 = d1u1.Crossed(d1v1);
728 tsurf1 = Nsurf1.Crossed(np);
729 dwtsurf1 = Nsurf1.Crossed(dnp);
731 surf2->D1(Sol(3), Sol(4), pt2, d1u2, d1v2);
733 gp_Vec pguis1(ptgui, pt1), pguis2(ptgui, pt2);
734 gp_Vec CrossVec, s1s2(pt1, pt2);
735 Standard_Real PScaInv = 1. / tsurf1.Dot(s1s2), F4, temp;
736 Standard_Real maxpiv = 1.e-9;
737 Standard_Real Nordu1 = d1u1.Magnitude(),
738 Nordv1 = d1v1.Magnitude();
740 temp = 2. * (Nordu1 + Nordv1) * s1s2.Magnitude() + 2. * Nordu1 * Nordv1;
742 Values(Sol, valsol, gradsol);
744 secmember(1) = Normg - dnp.Dot(pguis1);
745 secmember(2) = Normg - dnp.Dot(pguis2);
746 secmember(3) = - 2. * d1gui.Dot(pguis1);
748 CrossVec = tsurf1.Crossed(s1s2);
749 F4 = np.Dot(CrossVec) * PScaInv;
750 temp = dnp.Dot(CrossVec) + np.Dot(dwtsurf1.Crossed(s1s2));
751 temp -= F4 * dwtsurf1.Dot(s1s2);
752 secmember(4) = PScaInv * temp;
754 math_Gauss Resol(gradsol, maxpiv);
756 if (Resol.IsDone()) {
757 Resol.Solve(secmember);
758 istangent = Standard_False;
761 math_SVD SingRS (gradsol);
762 if (SingRS.IsDone()) {
763 math_Vector DEDT(1,4);
765 SingRS.Solve(DEDT, secmember, 1.e-6);
766 istangent = Standard_False;
768 else istangent = Standard_True;
772 tg1.SetLinearForm(secmember(1), d1u1, secmember(2), d1v1);
773 tg2.SetLinearForm(secmember(3), d1u2, secmember(4), d1v2);
774 tg12d.SetCoord(secmember(1),secmember(2));
775 tg22d.SetCoord(secmember(3),secmember(4));
778 distmin = Min( distmin, pt1.Distance(pt2));
781 DPoles2d(Poles2d.Lower()).SetCoord(Tangent2dOnS1().X(),
782 Tangent2dOnS1().Y());
783 DPoles2d(Poles2d.Upper()).SetCoord(Tangent2dOnS2().X(),
784 Tangent2dOnS2().Y());
786 DPoles(low) = TangentOnS1();
787 DPoles(upp) = TangentOnS2();
797 //=======================================================================
800 //=======================================================================
802 Standard_Boolean BlendFunc_ChAsym::Section
803 (const Blend_Point& /*P*/,
804 TColgp_Array1OfPnt& /*Poles*/,
805 TColgp_Array1OfVec& /*DPoles*/,
806 TColgp_Array1OfVec& /*D2Poles*/,
807 TColgp_Array1OfPnt2d& /*Poles2d*/,
808 TColgp_Array1OfVec2d& /*DPoles2d*/,
809 TColgp_Array1OfVec2d& /*D2Poles2d*/,
810 TColStd_Array1OfReal& /*Weights*/,
811 TColStd_Array1OfReal& /*DWeights*/,
812 TColStd_Array1OfReal& /*D2Weights*/)
814 return Standard_False;
818 //=======================================================================
819 //function : Resolution
821 //=======================================================================
822 void BlendFunc_ChAsym::Resolution(const Standard_Integer IC2d, const Standard_Real Tol,
823 Standard_Real& TolU, Standard_Real& TolV) const
826 TolU = surf1->UResolution(Tol);
827 TolV = surf1->VResolution(Tol);
830 TolU = surf2->UResolution(Tol);
831 TolV = surf2->VResolution(Tol);
836 //=======================================================================
839 //=======================================================================
840 void BlendFunc_ChAsym::Set(const Standard_Real Dist1,
841 const Standard_Real Angle,
842 const Standard_Integer Choix)