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.
16 #include <GeomFill_DiscreteTrihedron.hxx>
18 #include <Adaptor3d_Curve.hxx>
19 #include <GeomAbs_CurveType.hxx>
20 #include <GeomFill_Frenet.hxx>
21 #include <GeomFill_HSequenceOfAx2.hxx>
22 #include <GeomFill_TrihedronLaw.hxx>
24 #include <Standard_ConstructionError.hxx>
25 #include <Standard_Type.hxx>
26 #include <TColStd_Array1OfReal.hxx>
27 #include <TColStd_HSequenceOfReal.hxx>
29 IMPLEMENT_STANDARD_RTTIEXT(GeomFill_DiscreteTrihedron,GeomFill_TrihedronLaw)
31 static const Standard_Real TolConf = Precision::Confusion();
33 //=======================================================================
34 //function : GeomFill_DiscreteTrihedron
35 //purpose : Constructor
36 //=======================================================================
38 GeomFill_DiscreteTrihedron::GeomFill_DiscreteTrihedron() :
39 myUseFrenet(Standard_False)
41 myFrenet = new GeomFill_Frenet();
42 myKnots = new TColStd_HSequenceOfReal();
43 myTrihedrons = new GeomFill_HSequenceOfAx2();
46 //=======================================================================
49 //=======================================================================
51 Handle(GeomFill_TrihedronLaw) GeomFill_DiscreteTrihedron::Copy() const
53 Handle(GeomFill_DiscreteTrihedron) copy = new (GeomFill_DiscreteTrihedron)();
54 if (!myCurve.IsNull()) copy->SetCurve(myCurve);
58 //=======================================================================
61 //=======================================================================
63 Standard_Boolean GeomFill_DiscreteTrihedron::SetCurve(const Handle(Adaptor3d_Curve)& C)
65 GeomFill_TrihedronLaw::SetCurve(C);
68 GeomAbs_CurveType type;
74 case GeomAbs_Hyperbola:
75 case GeomAbs_Parabola:
79 myUseFrenet = Standard_True;
80 myFrenet->SetCurve(C);
85 myUseFrenet = Standard_False;
86 // We have to fill <myKnots> and <myTrihedrons>
95 //=======================================================================
98 //=======================================================================
100 void GeomFill_DiscreteTrihedron::Init()
102 Standard_Integer NbIntervals = myTrimmed->NbIntervals(GeomAbs_CN);
103 TColStd_Array1OfReal Knots(1, NbIntervals+1);
104 myTrimmed->Intervals(Knots, GeomAbs_CN);
106 //Standard_Real Tol = Precision::Confusion();
107 Standard_Integer NbSamples = 10;
109 Standard_Integer i, j;
110 for (i = 1; i <= NbIntervals; i++)
112 Standard_Real delta = (Knots(i+1) - Knots(i))/NbSamples;
113 for (j = 0; j < NbSamples; j++)
115 Standard_Real Param = Knots(i) + j*delta;
116 myKnots->Append(Param);
119 myKnots->Append(Knots(NbIntervals+1));
122 gp_Pnt Origin(0.,0.,0.), Pnt, SubPnt;
126 for (i = 1; i <= myKnots->Length(); i++)
128 Standard_Real Param = myKnots->Value(i);
129 myTrimmed->D1(Param, Pnt, Tangent);
130 norm = Tangent.Magnitude();
133 Standard_Real subdelta = (myKnots->Value(i+1) - myKnots->Value(i))/NbSamples;
134 if (subdelta < Precision::PConfusion())
135 subdelta = myKnots->Value(i+1) - myKnots->Value(i);
136 SubPnt = myTrimmed->Value(Param + subdelta);
137 Tangent.SetXYZ(SubPnt.XYZ() - Pnt.XYZ());
139 //Tangent.Normalize();
140 TangDir = Tangent; //normalize;
142 if (i == 1) //first point
144 gp_Ax2 FirstAxis(Origin, TangDir);
145 myTrihedrons->Append(FirstAxis);
149 gp_Ax2 LastAxis = myTrihedrons->Value(myTrihedrons->Length());
150 gp_Vec LastTangent = LastAxis.Direction();
151 gp_Vec AxisOfRotation = LastTangent ^ Tangent;
152 if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal or opposite
154 Standard_Real ScalarProduct = LastTangent * Tangent;
155 if (ScalarProduct > 0.) //tangents are equal
156 myTrihedrons->Append(LastAxis);
157 else //tangents are opposite
159 Standard_Real NewParam = (myKnots->Value(i-1) + myKnots->Value(i))/2.;
160 if (NewParam - myKnots->Value(i-1) < gp::Resolution())
161 throw Standard_ConstructionError("GeomFill_DiscreteTrihedron : impassable singularities on path curve");
162 myKnots->InsertBefore(i, NewParam);
166 else //good value of angle
168 Standard_Real theAngle = LastTangent.AngleWithRef(Tangent, AxisOfRotation);
169 gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
170 gp_Ax2 NewAxis = LastAxis.Rotated(theAxisOfRotation, theAngle);
171 NewAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
172 myTrihedrons->Append(NewAxis);
178 //=======================================================================
181 //=======================================================================
183 Standard_Boolean GeomFill_DiscreteTrihedron::D0(const Standard_Real Param,
190 myFrenet->D0(Param, Tangent, Normal, BiNormal);
194 //Locate <Param> in the sequence <myKnots>
195 Standard_Integer Index = -1;
196 Standard_Real TolPar = Precision::PConfusion();
197 //Standard_Real TolConf = Precision::Confusion();
198 Standard_Integer NbSamples = 10;
199 gp_Pnt Origin(0.,0.,0.);
203 //Standard_Real PrevParam;
205 Standard_Integer I1, I2;
207 I2 = myKnots->Length();
211 if (Param <= myKnots->Value(i))
219 if (Abs(Param - myKnots->Value(I2)) < TolPar)
222 Standard_Real PrevParam = myKnots->Value(Index);
223 gp_Ax2 PrevAxis = myTrihedrons->Value(Index);
225 if (Abs(Param - PrevParam) < TolPar)
227 else //<Param> is between knots
229 myTrimmed->D1(Param, myPoint, Tangent);
230 Standard_Real norm = Tangent.Magnitude();
233 Standard_Real subdelta = (myKnots->Value(Index+1) - Param)/NbSamples;
234 if (subdelta < Precision::PConfusion())
235 subdelta = myKnots->Value(Index+1) - Param;
236 gp_Pnt SubPnt = myTrimmed->Value(Param + subdelta);
237 Tangent.SetXYZ(SubPnt.XYZ() - myPoint.XYZ());
239 //Tangent.Normalize();
240 gp_Dir TangDir(Tangent); //normalize;
242 gp_Vec PrevTangent = PrevAxis.Direction();
243 gp_Vec AxisOfRotation = PrevTangent ^ Tangent;
244 if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal
246 //we assume that tangents can not be opposite
249 else //good value of angle
251 Standard_Real theAngle = PrevTangent.AngleWithRef(Tangent, AxisOfRotation);
252 gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
253 theAxis = PrevAxis.Rotated(theAxisOfRotation, theAngle);
255 theAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
256 } //end of else (Param is between knots)
258 Tangent = theAxis.Direction();
259 Normal = theAxis.XDirection();
260 BiNormal = theAxis.YDirection();
262 return Standard_True;
265 //=======================================================================
268 //=======================================================================
270 Standard_Boolean GeomFill_DiscreteTrihedron::D1(const Standard_Real Param,
280 myFrenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal);
284 D0(Param, Tangent, Normal, BiNormal);
286 DTangent.SetCoord(0.,0.,0.);
287 DNormal.SetCoord(0.,0.,0.);
288 DBiNormal.SetCoord(0.,0.,0.);
290 return Standard_True;
293 //=======================================================================
296 //=======================================================================
298 Standard_Boolean GeomFill_DiscreteTrihedron::D2(const Standard_Real Param,
311 myFrenet->D2(Param, Tangent, DTangent, D2Tangent,
312 Normal, DNormal, D2Normal,
313 BiNormal, DBiNormal, D2BiNormal);
317 D0(Param, Tangent, Normal, BiNormal);
319 DTangent.SetCoord(0.,0.,0.);
320 DNormal.SetCoord(0.,0.,0.);
321 DBiNormal.SetCoord(0.,0.,0.);
322 D2Tangent.SetCoord(0.,0.,0.);
323 D2Normal.SetCoord(0.,0.,0.);
324 D2BiNormal.SetCoord(0.,0.,0.);
326 return Standard_True;
329 //=======================================================================
330 //function : NbIntervals
332 //=======================================================================
334 Standard_Integer GeomFill_DiscreteTrihedron::NbIntervals(const GeomAbs_Shape) const
336 return (myTrimmed->NbIntervals(GeomAbs_CN));
339 //=======================================================================
340 //function : Intervals
342 //=======================================================================
344 void GeomFill_DiscreteTrihedron::Intervals(TColStd_Array1OfReal& T,
345 const GeomAbs_Shape) const
347 myTrimmed->Intervals(T, GeomAbs_CN);
350 void GeomFill_DiscreteTrihedron::GetAverageLaw(gp_Vec& ATangent,
354 Standard_Integer Num = 20; //order of digitalization
356 ATangent = gp_Vec(0, 0, 0);
357 ANormal = gp_Vec(0, 0, 0);
358 ABiNormal = gp_Vec(0, 0, 0);
359 Standard_Real Step = (myTrimmed->LastParameter() -
360 myTrimmed->FirstParameter()) / Num;
362 for (Standard_Integer i = 0; i <= Num; i++) {
363 Param = myTrimmed->FirstParameter() + i*Step;
364 if (Param > myTrimmed->LastParameter()) Param = myTrimmed->LastParameter();
373 ATangent.Normalize();
374 ABiNormal = ATangent.Crossed(ANormal).Normalized();
375 ANormal = ABiNormal.Crossed(ATangent);
378 //=======================================================================
379 //function : IsConstant
381 //=======================================================================
383 Standard_Boolean GeomFill_DiscreteTrihedron::IsConstant() const
385 return (myCurve->GetType() == GeomAbs_Line);
388 //=======================================================================
389 //function : IsOnlyBy3dCurve
391 //=======================================================================
393 Standard_Boolean GeomFill_DiscreteTrihedron::IsOnlyBy3dCurve() const
395 return Standard_True;