7bd071ed |
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 | } |