1 // Created on: 2013-02-05
2 // Created by: Julia GERASIMOVA
3 // Copyright (c) 2001-2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <Adaptor3d_HCurve.hxx>
18 #include <GeomAbs_CurveType.hxx>
19 #include <GeomFill_DiscreteTrihedron.hxx>
20 #include <GeomFill_Frenet.hxx>
21 #include <GeomFill_HSequenceOfAx2.hxx>
22 #include <GeomFill_TrihedronLaw.hxx>
24 #include <Standard_ConstructionError.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <Standard_Type.hxx>
27 #include <TColStd_Array1OfReal.hxx>
28 #include <TColStd_HSequenceOfReal.hxx>
30 IMPLEMENT_STANDARD_RTTIEXT(GeomFill_DiscreteTrihedron,GeomFill_TrihedronLaw)
32 static const Standard_Real TolConf = Precision::Confusion();
34 //=======================================================================
35 //function : GeomFill_DiscreteTrihedron
36 //purpose : Constructor
37 //=======================================================================
39 GeomFill_DiscreteTrihedron::GeomFill_DiscreteTrihedron() :
40 myUseFrenet(Standard_False)
42 myFrenet = new GeomFill_Frenet();
43 myKnots = new TColStd_HSequenceOfReal();
44 myTrihedrons = new GeomFill_HSequenceOfAx2();
47 //=======================================================================
50 //=======================================================================
52 Handle(GeomFill_TrihedronLaw) GeomFill_DiscreteTrihedron::Copy() const
54 Handle(GeomFill_DiscreteTrihedron) copy = new (GeomFill_DiscreteTrihedron)();
55 if (!myCurve.IsNull()) copy->SetCurve(myCurve);
59 //=======================================================================
62 //=======================================================================
64 void GeomFill_DiscreteTrihedron::SetCurve(const Handle(Adaptor3d_HCurve)& C)
66 GeomFill_TrihedronLaw::SetCurve(C);
68 GeomAbs_CurveType type;
73 case GeomAbs_Hyperbola:
74 case GeomAbs_Parabola:
78 myUseFrenet = Standard_True;
79 myFrenet->SetCurve(C);
84 myUseFrenet = Standard_False;
85 // We have to fill <myKnots> and <myTrihedrons>
93 //=======================================================================
96 //=======================================================================
98 void GeomFill_DiscreteTrihedron::Init()
100 Standard_Integer NbIntervals = myTrimmed->NbIntervals(GeomAbs_CN);
101 TColStd_Array1OfReal Knots(1, NbIntervals+1);
102 myTrimmed->Intervals(Knots, GeomAbs_CN);
104 //Standard_Real Tol = Precision::Confusion();
105 Standard_Integer NbSamples = 10;
107 Standard_Integer i, j;
108 for (i = 1; i <= NbIntervals; i++)
110 Standard_Real delta = (Knots(i+1) - Knots(i))/NbSamples;
111 for (j = 0; j < NbSamples; j++)
113 Standard_Real Param = Knots(i) + j*delta;
114 myKnots->Append(Param);
117 myKnots->Append(Knots(NbIntervals+1));
120 gp_Pnt Origin(0.,0.,0.), Pnt, SubPnt;
124 for (i = 1; i <= myKnots->Length(); i++)
126 Standard_Real Param = myKnots->Value(i);
127 myTrimmed->D1(Param, Pnt, Tangent);
128 norm = Tangent.Magnitude();
131 Standard_Real subdelta = (myKnots->Value(i+1) - myKnots->Value(i))/NbSamples;
132 if (subdelta < Precision::PConfusion())
133 subdelta = myKnots->Value(i+1) - myKnots->Value(i);
134 SubPnt = myTrimmed->Value(Param + subdelta);
135 Tangent.SetXYZ(SubPnt.XYZ() - Pnt.XYZ());
137 //Tangent.Normalize();
138 TangDir = Tangent; //normalize;
140 if (i == 1) //first point
142 gp_Ax2 FirstAxis(Origin, TangDir);
143 myTrihedrons->Append(FirstAxis);
147 gp_Ax2 LastAxis = myTrihedrons->Value(myTrihedrons->Length());
148 gp_Vec LastTangent = LastAxis.Direction();
149 gp_Vec AxisOfRotation = LastTangent ^ Tangent;
150 if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal or opposite
152 Standard_Real ScalarProduct = LastTangent * Tangent;
153 if (ScalarProduct > 0.) //tangents are equal
154 myTrihedrons->Append(LastAxis);
155 else //tangents are opposite
157 Standard_Real NewParam = (myKnots->Value(i-1) + myKnots->Value(i))/2.;
158 if (NewParam - myKnots->Value(i-1) < gp::Resolution())
159 Standard_ConstructionError::Raise("GeomFill_DiscreteTrihedron : impassable singularities on path curve");
160 myKnots->InsertBefore(i, NewParam);
164 else //good value of angle
166 Standard_Real theAngle = LastTangent.AngleWithRef(Tangent, AxisOfRotation);
167 gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
168 gp_Ax2 NewAxis = LastAxis.Rotated(theAxisOfRotation, theAngle);
169 NewAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
170 myTrihedrons->Append(NewAxis);
176 //=======================================================================
179 //=======================================================================
181 Standard_Boolean GeomFill_DiscreteTrihedron::D0(const Standard_Real Param,
188 myFrenet->D0(Param, Tangent, Normal, BiNormal);
192 //Locate <Param> in the sequence <myKnots>
193 Standard_Integer Index = -1;
194 Standard_Real TolPar = Precision::PConfusion();
195 //Standard_Real TolConf = Precision::Confusion();
196 Standard_Integer NbSamples = 10;
197 gp_Pnt Origin(0.,0.,0.);
201 //Standard_Real PrevParam;
203 Standard_Integer I1, I2;
205 I2 = myKnots->Length();
209 if (Param <= myKnots->Value(i))
217 if (Abs(Param - myKnots->Value(I2)) < TolPar)
220 Standard_Real PrevParam = myKnots->Value(Index);
221 gp_Ax2 PrevAxis = myTrihedrons->Value(Index);
223 if (Abs(Param - PrevParam) < TolPar)
225 else //<Param> is between knots
227 myTrimmed->D1(Param, myPoint, Tangent);
228 Standard_Real norm = Tangent.Magnitude();
231 Standard_Real subdelta = (myKnots->Value(Index+1) - Param)/NbSamples;
232 if (subdelta < Precision::PConfusion())
233 subdelta = myKnots->Value(Index+1) - Param;
234 gp_Pnt SubPnt = myTrimmed->Value(Param + subdelta);
235 Tangent.SetXYZ(SubPnt.XYZ() - myPoint.XYZ());
237 //Tangent.Normalize();
238 gp_Dir TangDir(Tangent); //normalize;
240 gp_Vec PrevTangent = PrevAxis.Direction();
241 gp_Vec AxisOfRotation = PrevTangent ^ Tangent;
242 if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal
244 //we assume that tangents can not be opposite
247 else //good value of angle
249 Standard_Real theAngle = PrevTangent.AngleWithRef(Tangent, AxisOfRotation);
250 gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
251 theAxis = PrevAxis.Rotated(theAxisOfRotation, theAngle);
253 theAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
254 } //end of else (Param is between knots)
256 Tangent = theAxis.Direction();
257 Normal = theAxis.XDirection();
258 BiNormal = theAxis.YDirection();
260 return Standard_True;
263 //=======================================================================
266 //=======================================================================
268 Standard_Boolean GeomFill_DiscreteTrihedron::D1(const Standard_Real Param,
278 myFrenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal);
282 D0(Param, Tangent, Normal, BiNormal);
284 DTangent.SetCoord(0.,0.,0.);
285 DNormal.SetCoord(0.,0.,0.);
286 DBiNormal.SetCoord(0.,0.,0.);
288 return Standard_True;
291 //=======================================================================
294 //=======================================================================
296 Standard_Boolean GeomFill_DiscreteTrihedron::D2(const Standard_Real Param,
309 myFrenet->D2(Param, Tangent, DTangent, D2Tangent,
310 Normal, DNormal, D2Normal,
311 BiNormal, DBiNormal, D2BiNormal);
315 D0(Param, Tangent, Normal, BiNormal);
317 DTangent.SetCoord(0.,0.,0.);
318 DNormal.SetCoord(0.,0.,0.);
319 DBiNormal.SetCoord(0.,0.,0.);
320 D2Tangent.SetCoord(0.,0.,0.);
321 D2Normal.SetCoord(0.,0.,0.);
322 D2BiNormal.SetCoord(0.,0.,0.);
324 return Standard_True;
327 //=======================================================================
328 //function : NbIntervals
330 //=======================================================================
332 Standard_Integer GeomFill_DiscreteTrihedron::NbIntervals(const GeomAbs_Shape) const
334 return (myTrimmed->NbIntervals(GeomAbs_CN));
337 //=======================================================================
338 //function : Intervals
340 //=======================================================================
342 void GeomFill_DiscreteTrihedron::Intervals(TColStd_Array1OfReal& T,
343 const GeomAbs_Shape) const
345 myTrimmed->Intervals(T, GeomAbs_CN);
348 void GeomFill_DiscreteTrihedron::GetAverageLaw(gp_Vec& ATangent,
352 Standard_Integer Num = 20; //order of digitalization
354 ATangent = gp_Vec(0, 0, 0);
355 ANormal = gp_Vec(0, 0, 0);
356 ABiNormal = gp_Vec(0, 0, 0);
357 Standard_Real Step = (myTrimmed->LastParameter() -
358 myTrimmed->FirstParameter()) / Num;
360 for (Standard_Integer i = 0; i <= Num; i++) {
361 Param = myTrimmed->FirstParameter() + i*Step;
362 if (Param > myTrimmed->LastParameter()) Param = myTrimmed->LastParameter();
371 ATangent.Normalize();
372 ABiNormal = ATangent.Crossed(ANormal).Normalized();
373 ANormal = ABiNormal.Crossed(ATangent);
376 //=======================================================================
377 //function : IsConstant
379 //=======================================================================
381 Standard_Boolean GeomFill_DiscreteTrihedron::IsConstant() const
383 return (myCurve->GetType() == GeomAbs_Line);
386 //=======================================================================
387 //function : IsOnlyBy3dCurve
389 //=======================================================================
391 Standard_Boolean GeomFill_DiscreteTrihedron::IsOnlyBy3dCurve() const
393 return Standard_True;