455a473aba94171787f8644bff0f5329a04a1ff8
[occt.git] / src / BRepMesh / BRepMesh_TorusRangeSplitter.cxx
1 // Created on: 2016-07-07
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepMesh_TorusRangeSplitter.hxx>
17 #include <GCPnts_TangentialDeflection.hxx>
18
19 //=======================================================================
20 // Function: GenerateSurfaceNodes
21 // Purpose : 
22 //=======================================================================
23 Handle(IMeshData::ListOfPnt2d) BRepMesh_TorusRangeSplitter::GenerateSurfaceNodes(
24   const IMeshTools_Parameters& theParameters) const
25 {
26   const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
27   const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
28
29   const Standard_Real aDiffU = aRangeU.second - aRangeU.first;
30   const Standard_Real aDiffV = aRangeV.second - aRangeV.first;
31
32   const gp_Torus aTorus = GetDFace()->GetSurface()->Torus();
33   const Standard_Real r = aTorus.MinorRadius();
34   const Standard_Real R = aTorus.MajorRadius();
35
36   const Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep(
37     r, GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize);
38
39   Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
40   Dv = oldDv;
41
42   const Standard_Integer nbV = Max((Standard_Integer) (aDiffV / Dv), 2);
43   Dv = aDiffV / (nbV + 1);
44
45   Standard_Real Du;
46   const Standard_Real ru = R + r;
47   if (ru > 1.e-16)
48   {
49     Du = GCPnts_TangentialDeflection::ArcAngularStep(ru,
50       GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize);
51
52     const Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
53     if (aa < gp::Resolution())
54     {
55       return Handle(IMeshData::ListOfPnt2d)();
56     }
57
58     Du *= Min(oldDv, Du) / aa;
59   }
60   else
61   {
62     Du = Dv;
63   }
64
65   Standard_Integer nbU = Max((Standard_Integer) (aDiffU / Du), 2);
66   nbU = Max(nbU, (Standard_Integer) (nbV * aDiffU * R / (aDiffV * r) / 5.));
67   Du = aDiffU / (nbU + 1);
68
69   const Handle(NCollection_IncAllocator) aTmpAlloc =
70     new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
71
72   Handle(IMeshData::SequenceOfReal) aParamU, aParamV;
73   if (R < r)
74   {
75     // As the points of edges are returned.
76     // in this case, the points are not representative.
77
78     //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
79     aParamU = new IMeshData::SequenceOfReal(aTmpAlloc);
80     for (Standard_Integer i = 0; i <= nbU; i++)
81     {
82       aParamU->Append(aRangeU.first + i * Du);
83     }
84   }//R<r
85   else //U if R > r
86   {
87     aParamU = fillParams(GetParametersU(), GetRangeU(), nbU, 0.5, aTmpAlloc);
88   }
89
90   aParamV = fillParams(GetParametersV(), GetRangeV(), nbV, 2. / 3., aTmpAlloc);
91
92   const std::pair<Standard_Real, Standard_Real> aNewRangeU(aRangeU.first  + Du * 0.1,
93                                                            aRangeU.second - Du * 0.1);
94
95   const std::pair<Standard_Real, Standard_Real> aNewRangeV(aRangeV.first  + Dv * 0.1,
96                                                            aRangeV.second - Dv * 0.1);
97
98   Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
99   for (Standard_Integer i = 1; i <= aParamU->Length(); ++i)
100   {
101     const Standard_Real aPasU = aParamU->Value(i);
102     if (aPasU >= aNewRangeU.first && aPasU < aNewRangeU.second)
103     {
104       for (Standard_Integer j = 1; j <= aParamV->Length(); ++j)
105       {
106         const Standard_Real aPasV = aParamV->Value(j);
107         if (aPasV >= aNewRangeV.first && aPasV < aNewRangeV.second)
108         {
109           aNodes->Append(gp_Pnt2d(aPasU, aPasV));
110         }
111       }
112     }
113   }
114
115   return aNodes;
116 }
117
118 //=======================================================================
119 // Function: AddPoint
120 // Purpose : 
121 //=======================================================================
122 void BRepMesh_TorusRangeSplitter::AddPoint(const gp_Pnt2d& thePoint)
123 {
124   BRepMesh_DefaultRangeSplitter::AddPoint(thePoint);
125   GetParametersU().Add(thePoint.X());
126   GetParametersV().Add(thePoint.Y());
127 }
128
129 //=======================================================================
130 // Function: fillParams
131 // Purpose : 
132 //=======================================================================
133 Handle(IMeshData::SequenceOfReal) BRepMesh_TorusRangeSplitter::fillParams(
134   const IMeshData::IMapOfReal&                   theParams,
135   const std::pair<Standard_Real, Standard_Real>& theRange,
136   const Standard_Integer                         theStepsNb,
137   const Standard_Real                            theScale,
138   const Handle(NCollection_IncAllocator)&        theAllocator) const
139 {
140   Handle(IMeshData::SequenceOfReal) aParams =
141     new IMeshData::SequenceOfReal(theAllocator);
142
143   const Standard_Integer aLength = theParams.Size();
144   TColStd_Array1OfReal aParamArray(1, aLength);
145
146   for (Standard_Integer j = 1; j <= aLength; ++j)
147   {
148     aParamArray(j) = theParams(j);
149   }
150
151   // Calculate DU, leave array of parameters
152   const Standard_Real aDiff = Abs(theRange.second - theRange.first);
153   Standard_Real aStep = FUN_CalcAverageDUV(aParamArray, aLength);
154   aStep = Max(aStep, aDiff / (Standard_Real) theStepsNb / 2.);
155
156   Standard_Real aStdStep = aDiff / (Standard_Real) aLength;
157   if (aStep > aStdStep)
158   {
159     aStdStep = aStep;
160   }
161   aStdStep *= theScale;
162
163   // Add parameters
164   for (Standard_Integer j = 1; j <= aLength; ++j)
165   {
166     const Standard_Real pp = aParamArray(j);
167
168     Standard_Boolean isToInsert = Standard_True;
169     const Standard_Integer aParamsLength = aParams->Length();
170     for (Standard_Integer i = 1; i <= aParamsLength && isToInsert; ++i)
171     {
172       isToInsert = (Abs(aParams->Value(i) - pp) > aStdStep);
173     }
174
175     if (isToInsert)
176     {
177       aParams->Append(pp);
178     }
179   }
180
181   return aParams;
182 }
183
184 //=======================================================================
185 // Function: FUN_CalcAverageDUV
186 // Purpose : 
187 //=======================================================================
188 Standard_Real BRepMesh_TorusRangeSplitter::FUN_CalcAverageDUV(
189   TColStd_Array1OfReal& P, const Standard_Integer PLen) const
190 {
191   Standard_Integer i, j, n = 0;
192   Standard_Real p, result = 0.;
193
194   for (i = 1; i <= PLen; i++)
195   {
196     // Sort
197     for (j = i + 1; j <= PLen; j++)
198     {
199       if (P(i) > P(j))
200       {
201         p = P(i);
202         P(i) = P(j);
203         P(j) = p;
204       }
205     }
206     // Accumulate
207     if (i != 1)
208     {
209       p = Abs(P(i) - P(i - 1));
210       if (p > 1.e-7)
211       {
212         result += p;
213         n++;
214       }
215     }
216   }
217   return (n ? (result / (Standard_Real) n) : -1.);
218 }