1 // Created on: 1998-01-22
2 // Created by: Philippe MANGIN/Roman BORISOV
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.
17 #include <GeomFill_Frenet.hxx>
19 #include <Adaptor3d_Curve.hxx>
20 #include <Extrema_ExtPC.hxx>
21 #include <GeomAbs_CurveType.hxx>
22 #include <GeomFill_SnglrFunc.hxx>
23 #include <GeomFill_TrihedronLaw.hxx>
24 #include <GeomLib.hxx>
26 #include <NCollection_Array1.hxx>
27 #include <Precision.hxx>
28 #include <Standard_OutOfRange.hxx>
29 #include <Standard_Type.hxx>
30 #include <TColgp_SequenceOfPnt2d.hxx>
31 #include <TColStd_HArray1OfBoolean.hxx>
34 IMPLEMENT_STANDARD_RTTIEXT(GeomFill_Frenet,GeomFill_TrihedronLaw)
36 static const Standard_Real NullTol = 1.e-10;
37 static const Standard_Real MaxSingular = 1.e-5;
39 static const Standard_Integer maxDerivOrder = 3;
42 //=======================================================================
44 //purpose : computes (F/|F|)'
45 //=======================================================================
46 static gp_Vec FDeriv(const gp_Vec& F, const gp_Vec& DF)
48 Standard_Real Norma = F.Magnitude();
49 gp_Vec Result = (DF - F*(F*DF)/(Norma*Norma))/Norma;
54 //=======================================================================
56 //purpose : computes (F/|F|)''
57 //=======================================================================
58 static gp_Vec DDeriv(const gp_Vec& F, const gp_Vec& DF, const gp_Vec& D2F)
60 Standard_Real Norma = F.Magnitude();
61 gp_Vec Result = (D2F - 2*DF*(F*DF)/(Norma*Norma))/Norma -
62 F*((DF.SquareMagnitude() + F*D2F
63 - 3*(F*DF)*(F*DF)/(Norma*Norma))/(Norma*Norma*Norma));
67 //=======================================================================
69 //purpose : Return a cosine between vectors theV1 and theV2.
70 //=======================================================================
71 static Standard_Real CosAngle(const gp_Vec& theV1, const gp_Vec& theV2)
73 const Standard_Real aTol = gp::Resolution();
75 const Standard_Real m1 = theV1.Magnitude(), m2 = theV2.Magnitude();
76 if((m1 <= aTol) || (m2 <= aTol)) //Vectors are codirectional
79 Standard_Real aCAng = theV1.Dot(theV2)/(m1*m2);
91 //=======================================================================
92 //function : GeomFill_Frenet
94 //=======================================================================
96 GeomFill_Frenet::GeomFill_Frenet()
97 : isSngl(Standard_False)
102 //=======================================================================
105 //=======================================================================
107 Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const
109 Handle(GeomFill_Frenet) copy = new (GeomFill_Frenet)();
110 if (!myCurve.IsNull()) copy->SetCurve(myCurve);
114 //=======================================================================
115 //function : SetCurve
117 //=======================================================================
119 Standard_Boolean GeomFill_Frenet::SetCurve(const Handle(Adaptor3d_Curve)& C)
121 GeomFill_TrihedronLaw::SetCurve(C);
123 GeomAbs_CurveType type;
127 case GeomAbs_Ellipse:
128 case GeomAbs_Hyperbola:
129 case GeomAbs_Parabola:
133 isSngl = Standard_False;
138 // We have to search singularities
143 return Standard_True;
146 //=======================================================================
149 //=======================================================================
151 void GeomFill_Frenet::Init()
153 Standard_Integer i, j;
154 GeomFill_SnglrFunc Func(myCurve);
155 Standard_Real TolF = 1.0e-10, Tol = 10*TolF, Tol2 = Tol * Tol,
156 PTol = Precision::PConfusion();
158 // We want to determine if the curve has linear segments
159 Standard_Integer NbIntC2 = myCurve->NbIntervals(GeomAbs_C2);
160 Handle(TColStd_HArray1OfReal) myC2Disc =
161 new TColStd_HArray1OfReal(1, NbIntC2 + 1);
162 Handle(TColStd_HArray1OfBoolean) IsLin =
163 new TColStd_HArray1OfBoolean(1, NbIntC2);
164 Handle(TColStd_HArray1OfBoolean) IsConst =
165 new TColStd_HArray1OfBoolean(1, NbIntC2);
166 TColStd_Array1OfReal AveFunc(1, NbIntC2);
167 myCurve->Intervals(myC2Disc->ChangeArray1(), GeomAbs_C2);
168 Standard_Integer NbControl = 10;
169 Standard_Real Step, Average = 0, modulus;
171 for(i = 1; i <= NbIntC2; i++) {
172 Step = (myC2Disc->Value(i+1) - myC2Disc->Value(i))/NbControl;
173 IsLin->ChangeValue(i) = Standard_True;
174 IsConst->ChangeValue(i) = Standard_True;
175 for(j = 1; j <= NbControl; j++) {
176 Func.D0(myC2Disc->Value(i) + (j-1)*Step, C);
178 modulus = C.XYZ().Modulus();
180 IsLin->ChangeValue(i) = Standard_False;
184 if(IsConst->Value(i)) {
185 if(Abs(C.X() - C1.X()) > Tol ||
186 Abs(C.Y() - C1.Y()) > Tol ||
187 Abs(C.Z() - C1.Z()) > Tol) {
188 IsConst->ChangeValue(i) = Standard_False;
193 AveFunc(i) = Average/NbControl;
196 // Here we are looking for singularities
197 TColStd_SequenceOfReal * SeqArray = new TColStd_SequenceOfReal[ NbIntC2 ];
198 TColStd_SequenceOfReal SnglSeq;
199 // Standard_Real Value2, preValue=1.e200, t;
200 Standard_Real Value2, t;
202 gp_Pnt Origin(0, 0, 0);
204 for(i = 1; i <= NbIntC2; i++) {
205 if (!IsLin->Value(i) && !IsConst->Value(i))
207 Func.SetRatio(1./AveFunc(i)); // Normalization
208 Ext.Initialize(Func, myC2Disc->Value(i), myC2Disc->Value(i+1), TolF);
210 if(Ext.IsDone() && Ext.NbExt() != 0)
212 for(j = 1; j <= Ext.NbExt(); j++)
214 Value2 = Ext.SquareDistance(j);
217 t = Ext.Point(j).Parameter();
218 SeqArray[i-1].Append(t);
223 if(SeqArray[i-1].Length() != 0) {
224 NCollection_Array1<Standard_Real> anArray( 1, SeqArray[i-1].Length() );
225 for (j = 1; j <= anArray.Length(); j++)
226 anArray(j) = SeqArray[i-1](j);
227 std::sort (anArray.begin(), anArray.end());
228 for (j = 1; j <= anArray.Length(); j++)
229 SeqArray[i-1](j) = anArray(j);
233 //Filling SnglSeq by first sets of roots
234 for(i = 0; i < NbIntC2; i++)
235 for (j = 1; j <= SeqArray[i].Length(); j++)
236 SnglSeq.Append( SeqArray[i](j) );
238 //Extrema works bad, need to pass second time
239 for(i = 0; i < NbIntC2; i++)
240 if (! SeqArray[i].IsEmpty())
242 SeqArray[i].Prepend( myC2Disc->Value(i+1) );
243 SeqArray[i].Append( myC2Disc->Value(i+2) );
244 Func.SetRatio(1./AveFunc(i+1)); // Normalization
245 for (j = 1; j < SeqArray[i].Length(); j++)
246 if (SeqArray[i](j+1) - SeqArray[i](j) > PTol)
248 Ext.Initialize(Func, SeqArray[i](j), SeqArray[i](j+1), TolF);
252 for(Standard_Integer k = 1; k <= Ext.NbExt(); k++)
254 Value2 = Ext.SquareDistance(k);
257 t = Ext.Point(k).Parameter();
258 if (t-SeqArray[i](j) > PTol && SeqArray[i](j+1)-t > PTol)
268 if(SnglSeq.Length() > 0) {
270 NCollection_Array1<Standard_Real> anArray( 1, SnglSeq.Length() );
271 for (i = 1; i <= SnglSeq.Length(); i++)
272 anArray(i) = SnglSeq(i);
273 std::sort (anArray.begin(), anArray.end());
274 for (i = 1; i <= SnglSeq.Length(); i++)
275 SnglSeq(i) = anArray(i);
277 // discard repeating elements
278 Standard_Boolean found = Standard_True;
282 found = Standard_False;
283 for (i = j; i < SnglSeq.Length(); i++)
284 if (SnglSeq(i+1) - SnglSeq(i) <= PTol)
288 found = Standard_True;
293 mySngl = new TColStd_HArray1OfReal(1, SnglSeq.Length());
294 for(i = 1; i <= mySngl->Length(); i++)
295 mySngl->ChangeValue(i) = SnglSeq(i);
297 // computation of length of singular interval
298 mySnglLen = new TColStd_HArray1OfReal(1, mySngl->Length());
299 gp_Vec SnglDer, SnglDer2;
301 for(i = 1; i <= mySngl->Length(); i++) {
302 Func.D2(mySngl->Value(i), C, SnglDer, SnglDer2);
303 if ((norm = SnglDer.Magnitude()) > gp::Resolution())
304 mySnglLen->ChangeValue(i) = Min(NullTol/norm, MaxSingular);
305 else if ((norm = SnglDer2.Magnitude()) > gp::Resolution())
306 mySnglLen->ChangeValue(i) = Min(Sqrt(2*NullTol/norm), MaxSingular);
307 else mySnglLen->ChangeValue(i) = MaxSingular;
310 for(i = 1; i <= mySngl->Length(); i++) {
311 std::cout<<"Sngl("<<i<<") = "<<mySngl->Value(i)<<" Length = "<<mySnglLen->Value(i)<<std::endl;
314 if(mySngl->Length() > 1) {
315 // we have to merge singular points that have common parts of singular intervals
316 TColgp_SequenceOfPnt2d tmpSeq;
317 tmpSeq.Append(gp_Pnt2d(mySngl->Value(1), mySnglLen->Value(1)));
318 Standard_Real U11, U12, U21, U22;
319 for(i = 2; i<= mySngl->Length(); i++) {
320 U12 = tmpSeq.Last().X() + tmpSeq.Last().Y();
321 U21 = mySngl->Value(i) - mySnglLen->Value(i);
323 U11 = tmpSeq.Last().X() - tmpSeq.Last().Y();
324 U22 = mySngl->Value(i) + mySnglLen->Value(i);
325 tmpSeq.ChangeValue(tmpSeq.Length()) = gp_Pnt2d((U11 + U22)/2, (U22 - U11)/2);
327 else tmpSeq.Append(gp_Pnt2d(mySngl->Value(i), mySnglLen->Value(i)));
329 mySngl = new TColStd_HArray1OfReal(1, tmpSeq.Length());
330 mySnglLen = new TColStd_HArray1OfReal(1, tmpSeq.Length());
331 for(i = 1; i <= mySngl->Length(); i++) {
332 mySngl->ChangeValue(i) = tmpSeq(i).X();
333 mySnglLen->ChangeValue(i) = tmpSeq(i).Y();
337 std::cout<<"After merging"<<std::endl;
338 for(i = 1; i <= mySngl->Length(); i++) {
339 std::cout<<"Sngl("<<i<<") = "<<mySngl->Value(i)<<" Length = "<<mySnglLen->Value(i)<<std::endl;
342 isSngl = Standard_True;
344 else isSngl = Standard_False;
347 //=======================================================================
348 //function : RotateTrihedron
349 //purpose : This function revolves the trihedron (which is determined of
350 // given "Tangent", "Normal" and "BiNormal" vectors)
351 // to coincide "Tangent" and "NewTangent" axes.
352 //=======================================================================
354 GeomFill_Frenet::RotateTrihedron( gp_Vec& Tangent,
357 const gp_Vec& NewTangent) const
359 const Standard_Real anInfCOS = cos(Precision::Angular()); //0.99999995
360 const Standard_Real aTol = gp::Resolution();
362 gp_Vec anAxis = Tangent.Crossed(NewTangent);
363 const Standard_Real NT = anAxis.Magnitude();
365 //No rotation required
366 return Standard_True;
368 anAxis /= NT; //Normalization
370 const Standard_Real aPx = anAxis.X(), aPy = anAxis.Y(), aPz = anAxis.Z();
371 const Standard_Real aCAng = CosAngle(Tangent,NewTangent); //cosine
373 const Standard_Real anAddCAng = 1.0 - aCAng;
374 const Standard_Real aSAng = sqrt(1.0 - aCAng*aCAng); //sine
376 //According to rotate direction, sine of rotation angle might be
377 //positive or negative.
378 //We can research to choose necessary sign. But I think, it is more
379 //effectively, to rotate "Tangent" vector in both direction. After that
380 //we can choose necessary rotation direction in depend of results.
382 const gp_Vec aV11(anAddCAng*aPx*aPx+aCAng, anAddCAng*aPx*aPy-aPz*aSAng, anAddCAng*aPx*aPz+aPy*aSAng);
383 const gp_Vec aV12(anAddCAng*aPx*aPx+aCAng, anAddCAng*aPx*aPy+aPz*aSAng, anAddCAng*aPx*aPz-aPy*aSAng);
384 const gp_Vec aV21(anAddCAng*aPx*aPy+aPz*aSAng, anAddCAng*aPy*aPy+aCAng, anAddCAng*aPy*aPz-aPx*aSAng);
385 const gp_Vec aV22(anAddCAng*aPx*aPy-aPz*aSAng, anAddCAng*aPy*aPy+aCAng, anAddCAng*aPy*aPz+aPx*aSAng);
386 const gp_Vec aV31(anAddCAng*aPx*aPz-aPy*aSAng, anAddCAng*aPy*aPz+aPx*aSAng, anAddCAng*aPz*aPz+aCAng);
387 const gp_Vec aV32(anAddCAng*aPx*aPz+aPy*aSAng, anAddCAng*aPy*aPz-aPx*aSAng, anAddCAng*aPz*aPz+aCAng);
389 gp_Vec aT1(Tangent.Dot(aV11), Tangent.Dot(aV21), Tangent.Dot(aV31));
390 gp_Vec aT2(Tangent.Dot(aV12), Tangent.Dot(aV22), Tangent.Dot(aV32));
392 if(CosAngle(aT1,NewTangent) >= CosAngle(aT2,NewTangent))
395 Normal = gp_Vec(Normal.Dot(aV11), Normal.Dot(aV21), Normal.Dot(aV31));
396 BiNormal = gp_Vec(BiNormal.Dot(aV11), BiNormal.Dot(aV21), BiNormal.Dot(aV31));
401 Normal = gp_Vec(Normal.Dot(aV12), Normal.Dot(aV22), Normal.Dot(aV32));
402 BiNormal = gp_Vec(BiNormal.Dot(aV12), BiNormal.Dot(aV22), BiNormal.Dot(aV32));
405 return CosAngle(Tangent,NewTangent) >= anInfCOS;
409 //=======================================================================
412 //=======================================================================
414 Standard_Boolean GeomFill_Frenet::D0(const Standard_Real theParam,
419 const Standard_Real aTol = gp::Resolution();
422 Standard_Integer Index;
423 Standard_Real Delta = 0.;
424 if(IsSingular(theParam, Index))
425 if (SingularD0(theParam, Index, Tangent, Normal, BiNormal, Delta))
426 return Standard_True;
428 Standard_Real aParam = theParam + Delta;
429 myTrimmed->D2(aParam, P, Tangent, BiNormal);
431 const Standard_Real DivisionFactor = 1.e-3;
432 const Standard_Real anUinfium = myTrimmed->FirstParameter();
433 const Standard_Real anUsupremum = myTrimmed->LastParameter();
434 const Standard_Real aDelta = (anUsupremum - anUinfium)*DivisionFactor;
435 Standard_Real Ndu = Tangent.Magnitude();
437 //////////////////////////////////////////////////////////////////////////////////////////////////////
441 //Derivative is approximated by Taylor-series
443 Standard_Integer anIndex = 1; //Derivative order
444 Standard_Boolean isDeriveFound = Standard_False;
448 aTn = myTrimmed->DN(theParam,++anIndex);
449 Ndu = aTn.Magnitude();
450 isDeriveFound = Ndu > aTol;
452 while(!isDeriveFound && anIndex < maxDerivOrder);
458 if(theParam-anUinfium < aDelta)
464 myTrimmed->D0(Min(theParam, u),P1);
465 myTrimmed->D0(Max(theParam, u),P2);
468 Standard_Real aDirFactor = aTn.Dot(V1);
475 //Derivative is approximated by three points
477 gp_Pnt Ptemp(0.0,0.0,0.0); //(0,0,0)-coordinate
479 Standard_Boolean IsParameterGrown;
481 if(theParam-anUinfium < 2*aDelta)
483 myTrimmed->D0(theParam,P1);
484 myTrimmed->D0(theParam+aDelta,P2);
485 myTrimmed->D0(theParam+2*aDelta,P3);
486 IsParameterGrown = Standard_True;
490 myTrimmed->D0(theParam-2*aDelta,P1);
491 myTrimmed->D0(theParam-aDelta,P2);
492 myTrimmed->D0(theParam,P3);
493 IsParameterGrown = Standard_False;
496 gp_Vec V1(Ptemp,P1), V2(Ptemp,P2), V3(Ptemp,P3);
502 }//else of "if(IsDeriveFound)" condition
503 Ndu = aTn.Magnitude();
505 Standard_Real dPar = 10.0*aDelta;
507 //Recursive calling is used for determine of trihedron for
508 //point, which is near to given.
509 if(theParam-anUinfium < dPar)
511 if(D0(aParam+dPar,Tangent,Normal,BiNormal) == Standard_False)
512 return Standard_False;
516 if(D0(aParam-dPar,Tangent,Normal,BiNormal) == Standard_False)
517 return Standard_False;
522 if(RotateTrihedron(Tangent,Normal,BiNormal,aTn) == Standard_False)
525 std::cout << "Cannot coincide two tangents." << std::endl;
527 return Standard_False;
532 Tangent = Tangent/Ndu;
533 BiNormal = Tangent.Crossed(BiNormal);
534 norm = BiNormal.Magnitude();
535 if (norm <= gp::Resolution())
537 gp_Ax2 Axe (gp_Pnt(0,0,0), Tangent);
538 BiNormal.SetXYZ(Axe.YDirection().XYZ());
541 BiNormal.Normalize();
544 Normal.Cross(Tangent);
547 return Standard_True;
550 //=======================================================================
553 //=======================================================================
555 Standard_Boolean GeomFill_Frenet::D1(const Standard_Real Param,
563 Standard_Integer Index;
564 Standard_Real Delta = 0.;
565 if(IsSingular(Param, Index))
566 if (SingularD1(Param, Index, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal, Delta))
567 return Standard_True;
569 // Standard_Real Norma;
570 Standard_Real theParam = Param + Delta;
571 gp_Vec DC1, DC2, DC3;
572 myTrimmed->D3(theParam, P, DC1, DC2, DC3);
573 Tangent = DC1.Normalized();
575 //if (DC2.Magnitude() <= NullTol || Tangent.Crossed(DC2).Magnitude() <= NullTol) {
576 if (Tangent.Crossed(DC2).Magnitude() <= gp::Resolution()) {
577 gp_Ax2 Axe (gp_Pnt(0,0,0), Tangent);
578 Normal.SetXYZ(Axe.XDirection().XYZ());
579 BiNormal.SetXYZ(Axe.YDirection().XYZ());
580 DTangent.SetCoord(0,0,0);
581 DNormal.SetCoord(0,0,0);
582 DBiNormal.SetCoord(0,0,0);
583 return Standard_True;
586 BiNormal = Tangent.Crossed(DC2).Normalized();
588 Normal = BiNormal.Crossed(Tangent);
590 DTangent = FDeriv(DC1, DC2);
592 gp_Vec instead_DC1, instead_DC2;
593 instead_DC1 = Tangent.Crossed(DC2);
594 instead_DC2 = DTangent.Crossed(DC2) + Tangent.Crossed(DC3);
595 DBiNormal = FDeriv(instead_DC1, instead_DC2);
597 DNormal = DBiNormal.Crossed(Tangent) + BiNormal.Crossed(DTangent);
598 return Standard_True;
601 //=======================================================================
604 //=======================================================================
606 Standard_Boolean GeomFill_Frenet::D2(const Standard_Real Param,
617 Standard_Integer Index;
618 Standard_Real Delta = 0.;
619 if(IsSingular(Param, Index))
620 if(SingularD2(Param, Index, Tangent, DTangent, D2Tangent,
621 Normal, DNormal, D2Normal,
622 BiNormal, DBiNormal, D2BiNormal,
624 return Standard_True;
626 // Standard_Real Norma;
627 Standard_Real theParam = Param + Delta;
628 gp_Vec DC1, DC2, DC3, DC4;
629 myTrimmed->D3(theParam, P, DC1, DC2, DC3);
630 DC4 = myTrimmed->DN(theParam, 4);
632 Tangent = DC1.Normalized();
634 //if (DC2.Magnitude() <= NullTol || Tangent.Crossed(DC2).Magnitude() <= NullTol) {
635 if (Tangent.Crossed(DC2).Magnitude() <= gp::Resolution()) {
636 gp_Ax2 Axe (gp_Pnt(0,0,0), Tangent);
637 Normal.SetXYZ(Axe.XDirection().XYZ());
638 BiNormal.SetXYZ(Axe.YDirection().XYZ());
639 DTangent.SetCoord(0,0,0);
640 DNormal.SetCoord(0,0,0);
641 DBiNormal.SetCoord(0,0,0);
642 D2Tangent.SetCoord(0,0,0);
643 D2Normal.SetCoord(0,0,0);
644 D2BiNormal.SetCoord(0,0,0);
645 return Standard_True;
648 BiNormal = Tangent.Crossed(DC2).Normalized();
650 Normal = BiNormal.Crossed(Tangent);
652 DTangent = FDeriv(DC1, DC2);
653 D2Tangent = DDeriv(DC1, DC2, DC3);
655 gp_Vec instead_DC1, instead_DC2, instead_DC3;
656 instead_DC1 = Tangent.Crossed(DC2);
657 instead_DC2 = DTangent.Crossed(DC2) + Tangent.Crossed(DC3);
658 instead_DC3 = D2Tangent.Crossed(DC2) + 2*DTangent.Crossed(DC3) + Tangent.Crossed(DC4);
659 DBiNormal = FDeriv(instead_DC1, instead_DC2);
660 D2BiNormal = DDeriv(instead_DC1, instead_DC2, instead_DC3);
662 DNormal = DBiNormal.Crossed(Tangent) + BiNormal.Crossed(DTangent);
664 D2Normal = D2BiNormal.Crossed(Tangent) + 2*DBiNormal.Crossed(DTangent) + BiNormal.Crossed(D2Tangent);
666 return Standard_True;
669 //=======================================================================
670 //function : NbIntervals
672 //=======================================================================
674 Standard_Integer GeomFill_Frenet::NbIntervals(const GeomAbs_Shape S) const
676 GeomAbs_Shape tmpS = GeomAbs_C0;
677 Standard_Integer NbTrimmed;
679 case GeomAbs_C0: tmpS = GeomAbs_C2; break;
680 case GeomAbs_C1: tmpS = GeomAbs_C3; break;
683 case GeomAbs_CN: tmpS = GeomAbs_CN; break;
684 default: throw Standard_OutOfRange();
687 NbTrimmed = myCurve->NbIntervals(tmpS);
689 if (!isSngl) return NbTrimmed;
691 TColStd_Array1OfReal TrimInt(1, NbTrimmed + 1);
692 myCurve->Intervals(TrimInt, tmpS);
694 TColStd_SequenceOfReal Fusion;
695 GeomLib::FuseIntervals(TrimInt, mySngl->Array1(), Fusion, Precision::PConfusion(), Standard_True);
697 return Fusion.Length() - 1;
700 //=======================================================================
701 //function : Intervals
703 //=======================================================================
705 void GeomFill_Frenet::Intervals(TColStd_Array1OfReal& T,
706 const GeomAbs_Shape S) const
708 GeomAbs_Shape tmpS = GeomAbs_C0;
709 Standard_Integer NbTrimmed;
711 case GeomAbs_C0: tmpS = GeomAbs_C2; break;
712 case GeomAbs_C1: tmpS = GeomAbs_C3; break;
715 case GeomAbs_CN: tmpS = GeomAbs_CN; break;
716 default: throw Standard_OutOfRange();
720 myCurve->Intervals(T, tmpS);
724 NbTrimmed = myCurve->NbIntervals(tmpS);
725 TColStd_Array1OfReal TrimInt(1, NbTrimmed + 1);
726 myCurve->Intervals(TrimInt, tmpS);
728 TColStd_SequenceOfReal Fusion;
729 GeomLib::FuseIntervals(TrimInt, mySngl->Array1(), Fusion, Precision::PConfusion(), Standard_True);
731 for (Standard_Integer i = 1; i <= Fusion.Length(); i++)
732 T.ChangeValue(i) = Fusion.Value(i);
735 void GeomFill_Frenet::GetAverageLaw(gp_Vec& ATangent,
739 Standard_Integer Num = 20; //order of digitalization
741 ATangent = gp_Vec(0, 0, 0);
742 ANormal = gp_Vec(0, 0, 0);
743 ABiNormal = gp_Vec(0, 0, 0);
744 Standard_Real Step = (myTrimmed->LastParameter() -
745 myTrimmed->FirstParameter()) / Num;
747 for (Standard_Integer i = 0; i <= Num; i++) {
748 Param = myTrimmed->FirstParameter() + i*Step;
749 if (Param > myTrimmed->LastParameter()) Param = myTrimmed->LastParameter();
758 ATangent.Normalize();
759 ABiNormal = ATangent.Crossed(ANormal).Normalized();
760 ANormal = ABiNormal.Crossed(ATangent);
763 //=======================================================================
764 //function : IsConstant
766 //=======================================================================
768 Standard_Boolean GeomFill_Frenet::IsConstant() const
770 return (myCurve->GetType() == GeomAbs_Line);
773 //=======================================================================
774 //function : IsOnlyBy3dCurve
776 //=======================================================================
778 Standard_Boolean GeomFill_Frenet::IsOnlyBy3dCurve() const
780 return Standard_True;
783 //=======================================================================
784 //function : IsSingular
786 //=======================================================================
788 Standard_Boolean GeomFill_Frenet::IsSingular(const Standard_Real U, Standard_Integer& Index) const
791 if(!isSngl) return Standard_False;
792 for(i = 1; i <= mySngl->Length(); i++) {
793 if (Abs(U - mySngl->Value(i)) < mySnglLen->Value(i)) {
795 return Standard_True;
798 return Standard_False;
801 //=======================================================================
802 //function : DoSingular
804 //=======================================================================
806 Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
807 const Standard_Integer Index,
812 Standard_Integer& TFlag,
813 Standard_Integer& BNFlag,
814 Standard_Real& Delta)
816 Standard_Integer i, MaxN = 20;
819 h = 2*mySnglLen->Value(Index);
828 for(i = 1; i <= MaxN; i++) {
829 Tangent = myTrimmed->DN(U, i);
830 if(Tangent.Magnitude() > Precision::Confusion()) break;
832 if (i > MaxN) return Standard_False;
837 for(; i <= MaxN; i++) {
838 BiNormal = Tangent.Crossed(myTrimmed->DN(U, i));
839 Standard_Real magn = BiNormal.Magnitude();
840 if (magn > Precision::Confusion())
842 //modified by jgv, 12.08.03 for OCC605 ////
843 gp_Vec NextBiNormal = Tangent.Crossed(myTrimmed->DN(U, i+1));
844 if (NextBiNormal.Magnitude() > magn)
847 BiNormal = NextBiNormal;
849 ///////////////////////////////////////////
856 return Standard_False;
859 BiNormal.Normalize();
864 if(Tangent.Angle(T) > M_PI/2) TFlag = -1;
865 if(BiNormal.Angle(BN) > M_PI/2) BNFlag = -1;
867 return Standard_True;
870 Standard_Boolean GeomFill_Frenet::SingularD0(const Standard_Real Param,
871 const Standard_Integer Index,
875 Standard_Real& Delta)
877 Standard_Integer n, k, TFlag, BNFlag;
878 if(!DoSingular(Param, Index, Tangent, BiNormal,
879 n, k, TFlag, BNFlag, Delta))
880 return Standard_False;
885 Normal.Cross(Tangent);
887 return Standard_True;
890 Standard_Boolean GeomFill_Frenet::SingularD1(const Standard_Real Param,
891 const Standard_Integer Index,
892 gp_Vec& Tangent,gp_Vec& DTangent,
893 gp_Vec& Normal,gp_Vec& DNormal,
894 gp_Vec& BiNormal,gp_Vec& DBiNormal,
895 Standard_Real& Delta)
897 Standard_Integer n, k, TFlag, BNFlag;
898 if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta))
899 return Standard_False;
902 F = myTrimmed->DN(Param, n);
903 DF = myTrimmed->DN(Param, n+1);
904 DTangent = FDeriv(F, DF);
906 Dtmp = myTrimmed->DN(Param, k);
907 F = Tangent.Crossed(Dtmp);
908 DF = DTangent.Crossed(Dtmp) + Tangent.Crossed(myTrimmed->DN(Param, k+1));
909 DBiNormal = FDeriv(F, DF);
913 DTangent = -DTangent;
917 BiNormal = -BiNormal;
918 DBiNormal = -DBiNormal;
921 Normal = BiNormal.Crossed(Tangent);
922 DNormal = DBiNormal.Crossed(Tangent) + BiNormal.Crossed(DTangent);
924 return Standard_True;
927 Standard_Boolean GeomFill_Frenet::SingularD2(const Standard_Real Param,
928 const Standard_Integer Index,
938 Standard_Real& Delta)
940 Standard_Integer n, k, TFlag, BNFlag;
941 if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta))
942 return Standard_False;
944 gp_Vec F, DF, D2F, Dtmp1, Dtmp2;
945 F = myTrimmed->DN(Param, n);
946 DF = myTrimmed->DN(Param, n+1);
947 D2F = myTrimmed->DN(Param, n+2);
948 DTangent = FDeriv(F, DF);
949 D2Tangent = DDeriv(F, DF, D2F);
951 Dtmp1 = myTrimmed->DN(Param, k);
952 Dtmp2 = myTrimmed->DN(Param, k+1);
953 F = Tangent.Crossed(Dtmp1);
954 DF = DTangent.Crossed(Dtmp1) + Tangent.Crossed(Dtmp2);
955 D2F = D2Tangent.Crossed(Dtmp1) + 2*DTangent.Crossed(Dtmp2) +
956 Tangent.Crossed(myTrimmed->DN(Param, k+2));
957 DBiNormal = FDeriv(F, DF);
958 D2BiNormal = DDeriv(F, DF, D2F);
962 DTangent = -DTangent;
963 D2Tangent = -D2Tangent;
967 BiNormal = -BiNormal;
968 DBiNormal = -DBiNormal;
969 D2BiNormal = -D2BiNormal;
972 Normal = BiNormal.Crossed(Tangent);
973 DNormal = DBiNormal.Crossed(Tangent) + BiNormal.Crossed(DTangent);
974 D2Normal = D2BiNormal.Crossed(Tangent) + 2*DBiNormal.Crossed(DTangent) + BiNormal.Crossed(D2Tangent);
976 return Standard_True;