7bd071ed |
1 | // Created on: 2016-04-19 |
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_NURBSRangeSplitter.hxx> |
46478ffe |
17 | |
18 | #include <algorithm> |
19 | #include <BRepMesh_GeomTool.hxx> |
7bd071ed |
20 | #include <GeomAdaptor_Curve.hxx> |
46478ffe |
21 | #include <GeomLib.hxx> |
7bd071ed |
22 | #include <IMeshData_Edge.hxx> |
46478ffe |
23 | #include <IMeshData_Wire.hxx> |
7bd071ed |
24 | #include <NCollection_Handle.hxx> |
7bd071ed |
25 | |
26 | namespace |
27 | { |
28 | class AnalyticalFilter |
29 | { |
30 | public: |
31 | //! Constructor. |
32 | AnalyticalFilter( |
33 | const IMeshData::IFaceHandle& theDFace, |
34 | const GeomAbs_IsoType theIsoType, |
35 | const Handle(IMeshData::SequenceOfReal)& theParams, |
36 | const Handle(IMeshData::SequenceOfReal)& theControlParams, |
37 | const Handle(IMeshData::MapOfReal)& theParamsForbiddenToRemove, |
38 | const Handle(IMeshData::MapOfReal)& theControlParamsForbiddenToRemove) |
39 | : myDFace(theDFace), |
c22b52d6 |
40 | mySurface(myDFace->GetSurface()->Surface().Surface()), |
7bd071ed |
41 | myIsoU(theIsoType == GeomAbs_IsoU), |
42 | myParams(theParams), |
43 | myControlParams(theControlParams), |
44 | myParamsForbiddenToRemove(theParamsForbiddenToRemove), |
45 | myControlParamsForbiddenToRemove(theControlParamsForbiddenToRemove), |
46 | myAllocator(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)), |
d533dafb |
47 | myControlParamsToRemove(new IMeshData::MapOfReal(1, myAllocator)), |
48 | myCurrParam(0.0), |
49 | myCurrControlParam(0.0), |
50 | myPrevControlParam(0.0) |
7bd071ed |
51 | { |
52 | } |
53 | |
54 | //! Returns map of parameters supposed to be removed. |
55 | const Handle(IMeshData::MapOfReal)& GetControlParametersToRemove( |
56 | const IMeshTools_Parameters& theParameters) |
57 | { |
58 | myParameters = theParameters; |
59 | |
7bd071ed |
60 | Standard_Integer aStartIndex, aEndIndex; |
61 | if (myIsoU) |
62 | { |
63 | aStartIndex = 1; |
64 | aEndIndex = myParams->Length(); |
65 | } |
66 | else |
67 | { |
68 | aStartIndex = 2; |
69 | aEndIndex = myParams->Length() - 1; |
70 | } |
71 | |
72 | for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i) |
73 | { |
74 | myCurrParam = myParams->Value(i); |
75 | myIso = new GeomAdaptor_Curve(myIsoU ? mySurface->UIso(myCurrParam) : mySurface->VIso(myCurrParam)); |
76 | |
77 | myPrevControlParam = myControlParams->Value(1); |
78 | myIso->D1(myPrevControlParam, myPrevControlPnt, myPrevControlVec); |
79 | for (Standard_Integer j = 2; j <= myControlParams->Length();) |
80 | { |
81 | j += checkControlPointAndMoveOn(j); |
82 | } |
83 | } |
84 | |
85 | return myControlParamsToRemove; |
86 | } |
87 | |
88 | private: |
89 | |
90 | //! Checks the given control point for deviation. |
91 | //! Returns number of steps to be used to move point iterator. |
92 | Standard_Integer checkControlPointAndMoveOn(const Standard_Integer theIndex) |
93 | { |
94 | Standard_Integer aMoveSteps = 0; |
95 | myCurrControlParam = myControlParams->Value(theIndex); |
96 | myIso->D1(myCurrControlParam, myCurrControlPnt, myCurrControlVec); |
97 | |
98 | const Standard_Real aMidParam = 0.5 * (myPrevControlParam + myCurrControlParam); |
99 | const gp_Pnt aMidPnt = myIso->Value(aMidParam); |
100 | |
101 | const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment( |
102 | myPrevControlPnt, myCurrControlPnt, aMidPnt); |
103 | |
46478ffe |
104 | Standard_Real anAngle = 0.0; |
105 | |
106 | if ((myPrevControlVec.SquareMagnitude() > Precision::SquareConfusion()) && |
107 | (myCurrControlVec.SquareMagnitude() > Precision::SquareConfusion())) |
108 | { |
109 | anAngle = myPrevControlVec.Angle(myCurrControlVec); |
110 | } |
111 | |
112 | const Standard_Real aSqMaxDeflection = myDFace->GetDeflection() * |
113 | myDFace->GetDeflection(); |
114 | |
115 | if (((aSqDist > aSqMaxDeflection) || (anAngle > myParameters.AngleInterior)) && |
7bd071ed |
116 | aSqDist > myParameters.MinSize * myParameters.MinSize) |
117 | { |
118 | // insertion |
119 | myControlParams->InsertBefore(theIndex, aMidParam); |
120 | } |
121 | else |
122 | { |
123 | // Here we should leave at least 3 parameters as far as |
124 | // we must have at least one parameter related to surface |
125 | // internals in order to prevent movement of triangle body |
126 | // outside the surface in case of highly curved ones, e.g. |
127 | // BSpline springs. |
46478ffe |
128 | if (((aSqDist < aSqMaxDeflection) || (anAngle < myParameters.AngleInterior)) && |
129 | myControlParams->Length() > 3 && theIndex < myControlParams->Length()) |
7bd071ed |
130 | { |
131 | // Remove too dense points |
132 | const Standard_Real aTmpParam = myControlParams->Value(theIndex + 1); |
133 | if (checkParameterForDeflectionAndUpdateCache(aTmpParam)) |
134 | { |
135 | ++aMoveSteps; |
136 | } |
137 | } |
138 | |
139 | myPrevControlParam = myCurrControlParam; |
140 | myPrevControlPnt = myCurrControlPnt; |
141 | myPrevControlVec = myCurrControlVec; |
142 | |
143 | ++aMoveSteps; |
144 | } |
145 | |
146 | return aMoveSteps; |
147 | } |
148 | |
149 | //! Checks whether the given param suits specified deflection. Updates cache. |
150 | Standard_Boolean checkParameterForDeflectionAndUpdateCache(const Standard_Real theParam) |
151 | { |
152 | gp_Pnt aTmpPnt; |
153 | gp_Vec aTmpVec; |
154 | myIso->D1(theParam, aTmpPnt, aTmpVec); |
155 | |
156 | const Standard_Real aTmpMidParam = 0.5 * (myPrevControlParam + theParam); |
157 | const gp_Pnt aTmpMidPnt = myIso->Value(aTmpMidParam); |
158 | |
159 | // Lets check next parameter. |
160 | // If it also fits deflection, we can remove previous parameter. |
161 | const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment( |
162 | myPrevControlPnt, aTmpPnt, aTmpMidPnt); |
163 | |
164 | if (aSqDist < myDFace->GetDeflection() * myDFace->GetDeflection()) |
165 | { |
166 | // Lets check parameters for angular deflection. |
167 | if (myPrevControlVec.SquareMagnitude() < gp::Resolution() || |
168 | aTmpVec.SquareMagnitude() < gp::Resolution() || |
46478ffe |
169 | myPrevControlVec.Angle(aTmpVec) < myParameters.AngleInterior) |
7bd071ed |
170 | { |
171 | // For current Iso line we can remove this parameter. |
172 | myControlParamsToRemove->Add(myCurrControlParam); |
173 | myCurrControlParam = theParam; |
174 | myCurrControlPnt = aTmpPnt; |
175 | myCurrControlVec = aTmpVec; |
176 | return Standard_True; |
177 | } |
178 | else |
179 | { |
180 | // We have found a place on the surface refusing |
181 | // removement of this parameter. |
182 | myParamsForbiddenToRemove ->Add(myCurrParam); |
183 | myControlParamsForbiddenToRemove->Add(myCurrControlParam); |
184 | } |
185 | } |
186 | |
187 | return Standard_False; |
188 | } |
189 | |
190 | private: |
191 | |
192 | IMeshData::IFaceHandle myDFace; |
193 | Handle(Geom_Surface) mySurface; |
194 | Standard_Boolean myIsoU; |
195 | Handle(IMeshData::SequenceOfReal) myParams; |
196 | Handle(IMeshData::SequenceOfReal) myControlParams; |
197 | |
198 | Handle(IMeshData::MapOfReal) myParamsForbiddenToRemove; |
199 | Handle(IMeshData::MapOfReal) myControlParamsForbiddenToRemove; |
200 | |
201 | Handle(NCollection_IncAllocator) myAllocator; |
202 | Handle(IMeshData::MapOfReal) myControlParamsToRemove; |
203 | |
204 | |
205 | IMeshTools_Parameters myParameters; |
206 | NCollection_Handle<GeomAdaptor_Curve> myIso; |
207 | |
208 | Standard_Real myCurrParam; |
209 | |
210 | Standard_Real myCurrControlParam; |
211 | gp_Pnt myCurrControlPnt; |
212 | gp_Vec myCurrControlVec; |
213 | |
214 | Standard_Real myPrevControlParam; |
215 | gp_Pnt myPrevControlPnt; |
216 | gp_Vec myPrevControlVec; |
217 | }; |
218 | |
219 | //! Adds param to map if it fits specified range. |
4945e8be |
220 | Standard_Boolean addParam( |
7bd071ed |
221 | const Standard_Real& theParam, |
222 | const std::pair<Standard_Real, Standard_Real>& theRange, |
223 | IMeshData::IMapOfReal& theParams) |
224 | { |
225 | if (theParam < theRange.first || |
226 | theParam > theRange.second) |
227 | { |
228 | return Standard_False; |
229 | } |
230 | |
231 | theParams.Add(theParam); |
232 | return Standard_True; |
233 | } |
234 | |
235 | //! Initializes parameters map using CN intervals. |
4945e8be |
236 | Standard_Boolean initParamsFromIntervals( |
7bd071ed |
237 | const TColStd_Array1OfReal& theIntervals, |
238 | const std::pair<Standard_Real, Standard_Real>& theRange, |
239 | const Standard_Boolean isSplitIntervals, |
240 | IMeshData::IMapOfReal& theParams) |
241 | { |
242 | Standard_Boolean isAdded = Standard_False; |
243 | |
244 | for (Standard_Integer i = theIntervals.Lower(); i <= theIntervals.Upper(); ++i) |
245 | { |
246 | const Standard_Real aStartParam = theIntervals.Value(i); |
247 | if (addParam(aStartParam, theRange, theParams)) |
248 | { |
249 | isAdded = Standard_True; |
250 | } |
251 | |
252 | if (isSplitIntervals && i < theIntervals.Upper()) |
253 | { |
254 | const Standard_Real aMidParam = (aStartParam + theIntervals.Value(i + 1)) / 2.; |
255 | if (addParam(aMidParam, theRange, theParams)) |
256 | { |
257 | isAdded = Standard_True; |
258 | } |
259 | } |
260 | } |
261 | |
262 | return isAdded; |
263 | } |
46478ffe |
264 | |
265 | //! Checks whether intervals should be split. |
266 | //! Returns true in case if it is impossible to compute normal |
267 | //! directly on intervals, false is returned elsewhere. |
268 | Standard_Boolean toSplitIntervals (const Handle (Geom_Surface)& theSurf, |
269 | const TColStd_Array1OfReal (&theIntervals)[2]) |
270 | { |
271 | Standard_Integer aIntervalU = theIntervals[0].Lower (); |
272 | for (; aIntervalU <= theIntervals[0].Upper (); ++aIntervalU) |
273 | { |
274 | const Standard_Real aParamU = theIntervals[0].Value(aIntervalU); |
973f7d55 |
275 | if (Precision::IsInfinite (aParamU)) |
276 | continue; |
277 | |
46478ffe |
278 | Standard_Integer aIntervalV = theIntervals[1].Lower (); |
279 | for (; aIntervalV <= theIntervals[1].Upper (); ++aIntervalV) |
280 | { |
281 | gp_Dir aNorm; |
282 | const Standard_Real aParamV = theIntervals[1].Value(aIntervalV); |
973f7d55 |
283 | if (Precision::IsInfinite (aParamV)) |
284 | continue; |
285 | |
46478ffe |
286 | if (GeomLib::NormEstim (theSurf, gp_Pnt2d (aParamU, aParamV), Precision::Confusion (), aNorm) != 0) |
287 | { |
288 | return Standard_True; |
289 | } |
290 | // TODO: do not split intervals if there is no normal in the middle of interval. |
291 | } |
292 | } |
293 | |
294 | return Standard_False; |
295 | } |
7bd071ed |
296 | } |
297 | |
298 | //======================================================================= |
299 | // Function: AdjustRange |
300 | // Purpose : |
301 | //======================================================================= |
302 | void BRepMesh_NURBSRangeSplitter::AdjustRange() |
303 | { |
304 | BRepMesh_DefaultRangeSplitter::AdjustRange(); |
305 | mySurfaceType = GetSurface()->GetType(); |
306 | |
307 | if (mySurfaceType == GeomAbs_BezierSurface) |
308 | { |
309 | const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU(); |
310 | const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV(); |
311 | |
312 | myIsValid = !(aRangeU.first < -0.5 || |
313 | aRangeU.second > 1.5 || |
314 | aRangeV.first < -0.5 || |
315 | aRangeV.second > 1.5); |
316 | } |
317 | } |
318 | |
319 | //======================================================================= |
320 | // Function: GenerateSurfaceNodes |
321 | // Purpose : |
322 | //======================================================================= |
323 | Handle(IMeshData::ListOfPnt2d) BRepMesh_NURBSRangeSplitter::GenerateSurfaceNodes( |
324 | const IMeshTools_Parameters& theParameters) const |
325 | { |
46478ffe |
326 | if (!initParameters()) |
327 | { |
328 | return Handle(IMeshData::ListOfPnt2d)(); |
329 | } |
7bd071ed |
330 | |
331 | const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU(); |
332 | const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV(); |
333 | const std::pair<Standard_Real, Standard_Real>& aDelta = GetDelta (); |
334 | |
335 | const Standard_Real aDefFace = GetDFace()->GetDeflection(); |
c22b52d6 |
336 | const Handle(BRepAdaptor_Surface)& gFace = GetSurface(); |
337 | Handle(Geom_Surface) aSurface = gFace->Surface().Surface(); |
7bd071ed |
338 | |
339 | const Handle(NCollection_IncAllocator) aTmpAlloc = |
340 | new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); |
341 | |
342 | const Handle(IMeshData::SequenceOfReal) aParams[2] = { |
343 | computeGrainAndFilterParameters(GetParametersU(), gFace->UResolution(aDefFace), |
344 | (aRangeU.second - aRangeU.first), aDelta.first, theParameters, aTmpAlloc), |
345 | |
346 | computeGrainAndFilterParameters(GetParametersV(), gFace->VResolution(aDefFace), |
347 | (aRangeV.second - aRangeV.first), aDelta.second, theParameters, aTmpAlloc) |
348 | }; |
349 | |
350 | // check intermediate isolines |
351 | Handle(IMeshData::MapOfReal) aFixedParams[2] = { |
352 | new IMeshData::MapOfReal(1, aTmpAlloc), |
353 | new IMeshData::MapOfReal(1, aTmpAlloc) |
354 | }; |
355 | |
356 | const Handle(IMeshData::MapOfReal) aParamsToRemove[2] = { |
357 | AnalyticalFilter(GetDFace(), GeomAbs_IsoV, aParams[1], aParams[0], |
358 | aFixedParams[1], aFixedParams[0]).GetControlParametersToRemove(theParameters), |
359 | |
360 | AnalyticalFilter(GetDFace(), GeomAbs_IsoU, aParams[0], aParams[1], |
361 | aFixedParams[0], aFixedParams[1]).GetControlParametersToRemove(theParameters), |
362 | }; |
363 | |
364 | aParamsToRemove[0]->Subtract(*aFixedParams[0]); |
365 | aParamsToRemove[1]->Subtract(*aFixedParams[1]); |
366 | |
367 | // insert nodes of the regular grid |
368 | Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d( |
369 | new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)); |
370 | |
371 | // insert nodes of the regular grid |
372 | for (Standard_Integer i = 1; i <= aParams[0]->Length(); ++i) |
373 | { |
374 | const Standard_Real aParam1 = aParams[0]->Value(i); |
375 | if (aParamsToRemove[0]->Contains(aParam1)) |
376 | { |
377 | continue; |
378 | } |
379 | |
380 | for (Standard_Integer j = 1; j <= aParams[1]->Length(); ++j) |
381 | { |
382 | const Standard_Real aParam2 = aParams[1]->Value(j); |
383 | if (aParamsToRemove[1]->Contains(aParam2)) |
384 | { |
385 | continue; |
386 | } |
387 | |
388 | aNodes->Append(gp_Pnt2d(aParam1, aParam2)); |
389 | } |
390 | } |
391 | |
392 | return aNodes; |
393 | } |
394 | |
c4ea4ca3 |
395 | //======================================================================= |
396 | // Function: getUndefinedIntervalNb |
397 | // Purpose : |
398 | //======================================================================= |
399 | Standard_Integer BRepMesh_NURBSRangeSplitter::getUndefinedIntervalNb( |
400 | const Handle(Adaptor3d_Surface)& theSurface, |
401 | const Standard_Boolean isU, |
402 | const GeomAbs_Shape /*theContinuity*/) const |
403 | { |
404 | return (isU ? theSurface->NbUPoles() : theSurface->NbVPoles()) - 1; |
405 | } |
406 | |
407 | //======================================================================= |
408 | // Function: getUndefinedInterval |
409 | // Purpose : |
410 | //======================================================================= |
411 | void BRepMesh_NURBSRangeSplitter::getUndefinedInterval( |
412 | const Handle(Adaptor3d_Surface)& theSurface, |
413 | const Standard_Boolean isU, |
414 | const GeomAbs_Shape theContinuity, |
415 | const std::pair<Standard_Real, Standard_Real>& theRange, |
416 | TColStd_Array1OfReal& theIntervals) const |
417 | { |
418 | Standard_Integer aIntervalsNb = isU ? |
419 | theSurface->NbUIntervals(theContinuity) : |
420 | theSurface->NbVIntervals(theContinuity); |
421 | |
422 | if (aIntervalsNb == 1) |
423 | { |
424 | aIntervalsNb = getUndefinedIntervalNb(theSurface, isU, theContinuity); |
425 | if (aIntervalsNb > 1) |
426 | { |
427 | theIntervals = TColStd_Array1OfReal(1, aIntervalsNb - 1); |
428 | const Standard_Real aDiff = (theRange.second - theRange.first) / aIntervalsNb; |
429 | for (Standard_Integer i = theIntervals.Lower(); i <= theIntervals.Upper(); ++i) |
430 | { |
431 | theIntervals.SetValue(i, theRange.first + i * aDiff); |
432 | } |
433 | } |
434 | } |
435 | |
436 | if (theIntervals.IsEmpty()) |
437 | { |
438 | theIntervals = TColStd_Array1OfReal(1, aIntervalsNb + 1); |
439 | if (isU) |
440 | { |
441 | theSurface->UIntervals(theIntervals, theContinuity); |
442 | } |
443 | else |
444 | { |
445 | theSurface->VIntervals(theIntervals, theContinuity); |
446 | } |
447 | } |
448 | } |
449 | |
7bd071ed |
450 | //======================================================================= |
451 | // Function: initParameters |
452 | // Purpose : |
453 | //======================================================================= |
46478ffe |
454 | Standard_Boolean BRepMesh_NURBSRangeSplitter::initParameters() const |
7bd071ed |
455 | { |
7bd071ed |
456 | const GeomAbs_Shape aContinuity = GeomAbs_CN; |
c4ea4ca3 |
457 | const Handle(BRepAdaptor_Surface)& aSurface = GetSurface(); |
7bd071ed |
458 | |
c4ea4ca3 |
459 | TColStd_Array1OfReal aIntervals[2]; |
460 | getUndefinedInterval(aSurface, Standard_True, aContinuity, GetRangeU(), aIntervals[0]); |
461 | getUndefinedInterval(aSurface, Standard_False, aContinuity, GetRangeV(), aIntervals[1]); |
7bd071ed |
462 | |
c22b52d6 |
463 | const Standard_Boolean isSplitIntervals = toSplitIntervals (aSurface->Surface().Surface(), aIntervals); |
7bd071ed |
464 | |
46478ffe |
465 | if (!initParamsFromIntervals(aIntervals[0], GetRangeU(), isSplitIntervals, |
466 | const_cast<IMeshData::IMapOfReal&>(GetParametersU()))) |
7bd071ed |
467 | { |
46478ffe |
468 | //if (!grabParamsOfEdges (Edge_Frontier, Param_U)) |
469 | { |
470 | return Standard_False; |
471 | } |
7bd071ed |
472 | } |
473 | |
46478ffe |
474 | if (!initParamsFromIntervals(aIntervals[1], GetRangeV(), isSplitIntervals, |
475 | const_cast<IMeshData::IMapOfReal&>(GetParametersV()))) |
476 | { |
477 | //if (!grabParamsOfEdges (Edge_Frontier, Param_V)) |
478 | { |
479 | return Standard_False; |
480 | } |
481 | } |
7bd071ed |
482 | |
46478ffe |
483 | return grabParamsOfEdges(Edge_Internal, Param_U | Param_V); |
484 | } |
485 | |
486 | //======================================================================= |
487 | //function : grabParamsOfInternalEdges |
488 | //purpose : |
489 | //======================================================================= |
490 | Standard_Boolean BRepMesh_NURBSRangeSplitter::grabParamsOfEdges ( |
491 | const EdgeType theEdgeType, |
492 | const Standard_Integer theParamDimensionFlag) const |
493 | { |
494 | if ((theParamDimensionFlag & (Param_U | Param_V)) == 0) |
495 | { |
496 | return Standard_False; |
497 | } |
498 | |
499 | const IMeshData::IFaceHandle& aDFace = GetDFace (); |
500 | for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb (); ++aWireIt) |
501 | { |
502 | const IMeshData::IWireHandle& aDWire = aDFace->GetWire (aWireIt); |
503 | for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb (); ++aEdgeIt) |
504 | { |
505 | const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge (aEdgeIt); |
506 | for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt) |
507 | { |
508 | const IMeshData::IPCurveHandle& aDPCurve = aDEdge->GetPCurve (aPCurveIt); |
509 | if (aDPCurve->GetFace () == aDFace) |
510 | { |
511 | if (theEdgeType == Edge_Internal && !aDPCurve->IsInternal ()) |
512 | { |
513 | continue; |
514 | } |
515 | |
516 | for (Standard_Integer aPointIt = 0; aPointIt < aDPCurve->ParametersNb (); ++aPointIt) |
517 | { |
518 | const gp_Pnt2d& aPnt2d = aDPCurve->GetPoint (aPointIt); |
519 | if (theParamDimensionFlag & Param_U) |
520 | { |
521 | const_cast<IMeshData::IMapOfReal&>(GetParametersU ()).Add (aPnt2d.X ()); |
522 | } |
523 | |
524 | if (theParamDimensionFlag & Param_V) |
525 | { |
526 | const_cast<IMeshData::IMapOfReal&>(GetParametersV ()).Add (aPnt2d.Y ()); |
527 | } |
528 | } |
529 | } |
530 | } |
531 | } |
532 | } |
533 | |
534 | return Standard_True; |
7bd071ed |
535 | } |
536 | |
537 | //======================================================================= |
538 | //function : computeGrainAndFilterParameters |
539 | //purpose : |
540 | //======================================================================= |
541 | Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::computeGrainAndFilterParameters( |
542 | const IMeshData::IMapOfReal& theSourceParams, |
543 | const Standard_Real theTol2d, |
544 | const Standard_Real theRangeDiff, |
545 | const Standard_Real theDelta, |
546 | const IMeshTools_Parameters& theParameters, |
547 | const Handle(NCollection_IncAllocator)& theAllocator) const |
548 | { |
549 | // Sort and filter sequence of parameters |
550 | Standard_Real aMinDiff = Precision::PConfusion(); |
551 | if (theDelta < 1.) |
552 | { |
553 | aMinDiff /= theDelta; |
554 | } |
555 | |
a939fd40 |
556 | const Handle(BRepAdaptor_Surface)& aSurface = GetSurface(); |
557 | const Standard_Real aMinSize2d = Max( |
558 | aSurface->UResolution(theParameters.MinSize), |
f55fe3b3 |
559 | aSurface->VResolution(theParameters.MinSize)); |
a939fd40 |
560 | |
561 | aMinDiff = Max(aMinSize2d, aMinDiff); |
7bd071ed |
562 | |
563 | const Standard_Real aDiffMaxLim = 0.1 * theRangeDiff; |
46478ffe |
564 | const Standard_Real aDiffMinLim = Max(0.005 * theRangeDiff, |
565 | 2. * theTol2d); |
a939fd40 |
566 | const Standard_Real aDiff = Max(aMinSize2d, |
46478ffe |
567 | Min(aDiffMaxLim, aDiffMinLim)); |
7bd071ed |
568 | return filterParameters(theSourceParams, aMinDiff, aDiff, theAllocator); |
569 | } |
570 | |
571 | //======================================================================= |
572 | //function : filterParameters |
573 | //purpose : |
574 | //======================================================================= |
575 | Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::filterParameters( |
576 | const IMeshData::IMapOfReal& theParams, |
577 | const Standard_Real theMinDist, |
578 | const Standard_Real theFilterDist, |
579 | const Handle(NCollection_IncAllocator)& theAllocator) const |
580 | { |
581 | Handle(IMeshData::SequenceOfReal) aResult = new IMeshData::SequenceOfReal(theAllocator); |
582 | |
583 | // Sort sequence of parameters |
584 | const Standard_Integer anInitLen = theParams.Extent(); |
585 | |
586 | if (anInitLen < 1) |
587 | { |
588 | return aResult; |
589 | } |
590 | |
591 | TColStd_Array1OfReal aParamArray(1, anInitLen); |
592 | Standard_Integer j; |
593 | for (j = 1; j <= anInitLen; j++) |
594 | aParamArray(j) = theParams(j); |
595 | |
596 | std::sort(aParamArray.begin(), aParamArray.end()); |
597 | |
598 | // mandatory pre-filtering using the first (minimal) filter value |
599 | Standard_Integer aParamLength = 1; |
600 | for (j = 2; j <= anInitLen; j++) |
601 | { |
602 | if ((aParamArray(j) - aParamArray(aParamLength)) > theMinDist) |
603 | { |
604 | if (++aParamLength < j) |
605 | aParamArray(aParamLength) = aParamArray(j); |
606 | } |
607 | } |
608 | |
609 | //perform filtering on series |
610 | Standard_Real aLastAdded, aLastCandidate; |
611 | Standard_Boolean isCandidateDefined = Standard_False; |
612 | aLastAdded = aParamArray(1); |
613 | aLastCandidate = aLastAdded; |
614 | aResult->Append(aLastAdded); |
615 | |
616 | for (j = 2; j < aParamLength; j++) |
617 | { |
618 | Standard_Real aVal = aParamArray(j); |
619 | if (aVal - aLastAdded > theFilterDist) |
620 | { |
621 | //adds the parameter |
622 | if (isCandidateDefined) |
623 | { |
624 | aLastAdded = aLastCandidate; |
625 | isCandidateDefined = Standard_False; |
626 | j--; |
627 | } |
628 | else |
629 | { |
630 | aLastAdded = aVal; |
631 | } |
632 | aResult->Append(aLastAdded); |
633 | continue; |
634 | } |
635 | |
636 | aLastCandidate = aVal; |
637 | isCandidateDefined = Standard_True; |
638 | } |
639 | aResult->Append(aParamArray(aParamLength)); |
640 | |
641 | return aResult; |
642 | } |