8422b578 |
1 | // Copyright (c) 2014 OPEN CASCADE SAS |
2 | // |
3 | // This file is part of Open CASCADE Technology software library. |
4 | // |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
10 | // |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
13 | |
8422b578 |
14 | |
42cf5bc1 |
15 | #include <BRep_Builder.hxx> |
16 | #include <BRepGProp.hxx> |
17 | #include <GProp_GProps.hxx> |
18 | #include <Message_Msg.hxx> |
8422b578 |
19 | #include <Precision.hxx> |
42cf5bc1 |
20 | #include <ShapeBuild_ReShape.hxx> |
21 | #include <ShapeFix_FixSmallSolid.hxx> |
22 | #include <Standard_Type.hxx> |
23 | #include <TopExp_Explorer.hxx> |
8422b578 |
24 | #include <TopoDS_Builder.hxx> |
25 | #include <TopoDS_Compound.hxx> |
26 | #include <TopoDS_Iterator.hxx> |
42cf5bc1 |
27 | #include <TopoDS_Shape.hxx> |
28 | #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> |
29 | #include <TopTools_DataMapOfShapeListOfShape.hxx> |
8422b578 |
30 | #include <TopTools_DataMapOfShapeReal.hxx> |
31 | #include <TopTools_DataMapOfShapeShape.hxx> |
42cf5bc1 |
32 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
33 | #include <TopTools_ListOfShape.hxx> |
34 | #include <TopTools_MapIteratorOfMapOfShape.hxx> |
35 | #include <TopTools_MapOfShape.hxx> |
8422b578 |
36 | |
92efcf78 |
37 | IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_FixSmallSolid,ShapeFix_Root) |
38 | |
8422b578 |
39 | //======================================================================= |
40 | //function : ShapeFix_FixSmallSolid |
41 | //purpose : Construct |
42 | //======================================================================= |
43 | ShapeFix_FixSmallSolid::ShapeFix_FixSmallSolid() |
df515f16 |
44 | : myFixMode (0) |
45 | , myVolumeThreshold (Precision::Infinite()) |
8422b578 |
46 | , myWidthFactorThreshold (Precision::Infinite()) {} |
47 | |
df515f16 |
48 | //======================================================================= |
49 | //function : SetFixMode |
50 | //purpose : Set the mode for applying fixes of small solids. |
51 | //======================================================================= |
52 | void ShapeFix_FixSmallSolid::SetFixMode ( |
53 | const Standard_Integer theMode) |
54 | { |
55 | myFixMode = (theMode < 0 || theMode > 2) ? 0 : theMode; |
56 | } |
57 | |
8422b578 |
58 | //======================================================================= |
59 | //function : SetVolumeThreshold |
60 | //purpose : Set or clear volume threshold for small solids |
61 | //======================================================================= |
62 | void ShapeFix_FixSmallSolid::SetVolumeThreshold ( |
63 | const Standard_Real theThreshold) |
64 | { |
65 | myVolumeThreshold = |
66 | theThreshold >= 0.0 ? theThreshold : Precision::Infinite(); |
67 | } |
68 | |
69 | //======================================================================= |
70 | //function : SetWidthFactorThreshold |
71 | //purpose : Set or clear width factor threshold for small solids |
72 | //======================================================================= |
73 | void ShapeFix_FixSmallSolid::SetWidthFactorThreshold ( |
74 | const Standard_Real theThreshold) |
75 | { |
76 | myWidthFactorThreshold = |
77 | theThreshold >= 0.0 ? theThreshold : Precision::Infinite(); |
78 | } |
79 | |
80 | //======================================================================= |
81 | //function : IsValidInput |
82 | //purpose : auxiliary |
83 | //======================================================================= |
84 | // Check if an input shape is valid |
85 | static Standard_Boolean IsValidInput (const TopoDS_Shape& theShape) |
86 | { |
87 | if (theShape.IsNull()) |
88 | return Standard_False; |
89 | |
90 | switch (theShape.ShapeType()) |
91 | { |
92 | case TopAbs_COMPOUND: |
93 | case TopAbs_COMPSOLID: |
94 | case TopAbs_SOLID: |
95 | return Standard_True; |
96 | default: |
97 | return Standard_False; |
98 | } |
99 | } |
100 | |
101 | //======================================================================= |
102 | //function : Remove |
103 | //purpose : Remove small solids from the given shape |
104 | //======================================================================= |
105 | TopoDS_Shape ShapeFix_FixSmallSolid::Remove ( |
106 | const TopoDS_Shape& theShape, |
107 | const Handle(ShapeBuild_ReShape)& theContext) const |
108 | { |
109 | // Check if at least one smallness criterion is set and the shape is valid |
110 | if (!IsThresholdsSet() || !IsValidInput (theShape)) return theShape; |
111 | |
112 | // Find and remove all small solids |
113 | TopExp_Explorer aSolidIter (theShape, TopAbs_SOLID); |
114 | for (; aSolidIter.More(); aSolidIter.Next()) |
115 | { |
116 | const TopoDS_Shape& aSolid = aSolidIter.Current(); |
117 | if (IsSmall (aSolid)) |
7c8996f4 |
118 | { |
8422b578 |
119 | theContext->Remove (aSolid); |
7c8996f4 |
120 | SendWarning ( aSolid, Message_Msg( "ShapeFix.FixSmallSolid.MSG0" )); |
121 | } |
8422b578 |
122 | } |
123 | |
124 | // Return updated shape |
125 | return theContext->Apply (theShape); |
126 | } |
127 | |
128 | //======================================================================= |
129 | //function : ShapeArea |
130 | //purpose : auxiliary |
131 | //======================================================================= |
132 | // Calculate surface area of a shape |
133 | static Standard_Real ShapeArea (const TopoDS_Shape& theShape) |
134 | { |
135 | GProp_GProps aProps; |
136 | BRepGProp::SurfaceProperties (theShape, aProps); |
137 | return aProps.Mass(); |
138 | } |
139 | |
140 | //======================================================================= |
141 | //function : ShapeVolume |
142 | //purpose : auxiliary |
143 | //======================================================================= |
144 | // Calculate volume of a shape |
145 | static Standard_Real ShapeVolume (const TopoDS_Shape& theShape) |
146 | { |
147 | GProp_GProps aProps; |
148 | BRepGProp::VolumeProperties (theShape, aProps); |
149 | return aProps.Mass(); |
150 | } |
151 | |
152 | //======================================================================= |
153 | //function : AddToMap |
154 | //purpose : auxiliary |
155 | //======================================================================= |
156 | // Append an item to a list of shapes mapped to a shape |
157 | static void AddToMap (TopTools_DataMapOfShapeListOfShape& theMap, |
158 | const TopoDS_Shape& theKey, |
159 | const TopoDS_Shape& theItem) |
160 | { |
b7c077b9 |
161 | TopTools_ListOfShape* aListPtr = theMap.ChangeSeek (theKey); |
8422b578 |
162 | if (aListPtr == NULL) |
163 | { |
164 | TopTools_ListOfShape aList; |
165 | aList.Append (theItem); |
166 | theMap.Bind (theKey, aList); |
167 | } |
168 | else |
b7c077b9 |
169 | aListPtr->Append (theItem); |
8422b578 |
170 | } |
171 | |
172 | //======================================================================= |
173 | //function : AddToMap |
174 | //purpose : auxiliary |
175 | //======================================================================= |
176 | // Append items to a list of shapes mapped to a shape |
177 | static void AddToMap (TopTools_DataMapOfShapeListOfShape& theMap, |
178 | const TopoDS_Shape& theKey, |
179 | TopTools_ListOfShape& theItems) |
180 | { |
181 | if (theItems.IsEmpty()) return; |
182 | |
b7c077b9 |
183 | TopTools_ListOfShape* aListPtr = theMap.ChangeSeek (theKey); |
8422b578 |
184 | if (aListPtr == NULL) |
185 | theMap.Bind (theKey, theItems); |
186 | else |
b7c077b9 |
187 | aListPtr->Append (theItems); |
8422b578 |
188 | } |
189 | |
190 | //======================================================================= |
191 | //function : MapFacesToShells |
192 | //purpose : auxiliary |
193 | //======================================================================= |
194 | // Map faces from a solid with their shells; |
195 | // unmap faces shared between two shells |
196 | static void MapFacesToShells (const TopoDS_Shape& theSolid, |
197 | TopTools_DataMapOfShapeShape& theMap) |
198 | { |
199 | TopoDS_Iterator aShellIter (theSolid); |
200 | for (; aShellIter.More(); aShellIter.Next()) |
201 | { |
202 | const TopoDS_Shape& aShell = aShellIter.Value(); |
203 | if (aShell.ShapeType() != TopAbs_SHELL) continue; |
204 | |
205 | TopoDS_Iterator aFaceIter (aShell); |
206 | for (; aFaceIter.More(); aFaceIter.Next()) |
207 | { |
208 | const TopoDS_Shape& aFace = aFaceIter.Value(); |
209 | if (aFace.ShapeType() != TopAbs_FACE) continue; |
210 | |
211 | if (!theMap.Bind (aFace, aShell)) |
212 | theMap.UnBind (aFace); |
213 | } |
214 | } |
215 | } |
216 | |
217 | //======================================================================= |
218 | //function : FindMostSharedShell |
219 | //purpose : auxiliary |
220 | //======================================================================= |
221 | // Find an outer shell having greatest sum area of |
222 | // all faces shared with the solid |
223 | static Standard_Boolean FindMostSharedShell ( |
224 | const TopoDS_Shape& theSolid, |
225 | const TopTools_DataMapOfShapeShape& theMapFacesToOuterShells, |
226 | TopoDS_Shape& theMostSharedOuterShell, |
227 | TopoDS_Shape& theMostSharedSolidShell, |
228 | TopTools_ListOfShape& theOtherSolidShells) |
229 | { |
230 | TopTools_DataMapOfShapeReal aSharedAreas; |
231 | Standard_Real aMaxSharedArea = 0.0; |
232 | const TopoDS_Shape* aMostSharedOuterShellPtr = NULL; |
233 | const TopoDS_Shape* aMostSharedSolidShellPtr = NULL; |
234 | |
235 | // check every shell in the solid for faces shared with outer shells |
236 | TopoDS_Iterator aShellIter (theSolid); |
237 | for (; aShellIter.More(); aShellIter.Next()) |
238 | { |
239 | const TopoDS_Shape& aSolidShell = aShellIter.Value(); |
240 | if (aSolidShell.ShapeType() != TopAbs_SHELL) continue; |
241 | |
242 | theOtherSolidShells.Append (aSolidShell); |
243 | |
244 | TopoDS_Iterator aFaceIter (aSolidShell); |
245 | for (; aFaceIter.More(); aFaceIter.Next()) |
246 | { |
247 | const TopoDS_Shape& aFace = aFaceIter.Value(); |
248 | if (aFace.ShapeType() != TopAbs_FACE) continue; |
249 | |
250 | // find an outer shell that shares the current face |
b7c077b9 |
251 | const TopoDS_Shape* anOuterShellPtr = theMapFacesToOuterShells.Seek (aFace); |
8422b578 |
252 | if (anOuterShellPtr == NULL) continue; |
b7c077b9 |
253 | const TopoDS_Shape& anOuterShell = *anOuterShellPtr; |
8422b578 |
254 | |
255 | // add the face area to the sum shared area for the outer shell |
256 | Standard_Real anArea = ShapeArea (aFace); |
b7c077b9 |
257 | Standard_Real* aSharedAreaPtr = aSharedAreas.ChangeSeek (anOuterShell); |
8422b578 |
258 | if (aSharedAreaPtr == NULL) |
259 | aSharedAreas.Bind (anOuterShell, anArea); |
260 | else |
b7c077b9 |
261 | anArea = (*aSharedAreaPtr) += anArea; |
8422b578 |
262 | |
263 | // if this outer shell currently has maximum shared area, |
264 | // remember it and the current solid's shell |
265 | if (aMaxSharedArea < anArea) |
266 | { |
267 | aMaxSharedArea = anArea; |
268 | aMostSharedOuterShellPtr = &anOuterShell; |
269 | aMostSharedSolidShellPtr = &aSolidShell; |
270 | } |
271 | } |
272 | } |
273 | |
274 | // return nothing if no adjanced outer shells were found |
275 | if (aMostSharedSolidShellPtr == NULL) |
276 | return Standard_False; |
277 | |
278 | // compose return values |
279 | theMostSharedOuterShell = *aMostSharedOuterShellPtr; |
280 | theMostSharedSolidShell = *aMostSharedSolidShellPtr; |
281 | |
282 | // remove the most shared solid's shell from the returned list of its other shells |
283 | TopTools_ListIteratorOfListOfShape anOtherShellIter (theOtherSolidShells); |
284 | while (!anOtherShellIter.Value().IsSame (theMostSharedSolidShell)) |
285 | anOtherShellIter.Next(); |
286 | theOtherSolidShells.Remove (anOtherShellIter); |
287 | |
288 | return Standard_True; |
289 | } |
290 | |
291 | //======================================================================= |
292 | //function : MergeShells |
293 | //purpose : auxiliary |
294 | //======================================================================= |
295 | // Merge some shells to a base shell |
296 | static TopoDS_Shape MergeShells ( |
297 | const TopoDS_Shape& theBaseShell, |
298 | TopTools_ListOfShape& theShellsToMerge, |
299 | const TopTools_DataMapOfShapeShape& theMapFacesToOuterShells, |
300 | TopTools_DataMapOfShapeShape& theMapNewFreeFacesToShells) |
301 | { |
302 | // Create a new shell |
303 | BRep_Builder aBuilder; |
304 | TopoDS_Shape aNewShell = theBaseShell.EmptyCopied(); |
305 | |
306 | // Sort the faces belogning to the merged shells: |
307 | // - faces shared with the base shell: |
308 | // keep to remove from the base shell; |
309 | // - faces shared with other outer shells, non-face elements: |
310 | // add to the new shell; |
311 | // - faces not shared with any outer or any merged shell: |
312 | // keep to add to the new shell and to the new map. |
313 | TopTools_MapOfShape aRemoveFaces; |
314 | TopTools_MapOfShape aNewFreeFaces; |
315 | |
316 | TopTools_ListIteratorOfListOfShape aShellIter (theShellsToMerge); |
317 | for (; aShellIter.More(); aShellIter.Next()) |
318 | { |
319 | TopoDS_Iterator aFaceIter (aShellIter.Value()); |
320 | for (; aFaceIter.More(); aFaceIter.Next()) |
321 | { |
322 | const TopoDS_Shape& aFace = aFaceIter.Value(); |
323 | |
324 | // non-face element in a shell - just add it to the new shell |
325 | if (aFace.ShapeType() != TopAbs_FACE) |
326 | { |
327 | aBuilder.Add (aNewShell, aFace); |
328 | continue; |
329 | } |
330 | |
331 | // classify the face |
b7c077b9 |
332 | const TopoDS_Shape* anOuterShellPtr = theMapFacesToOuterShells.Seek (aFace); |
8422b578 |
333 | if (anOuterShellPtr != NULL) |
334 | { |
b7c077b9 |
335 | if (anOuterShellPtr->IsSame (theBaseShell)) |
8422b578 |
336 | aRemoveFaces.Add (aFace); // face shared with the base shell |
337 | else |
338 | aBuilder.Add (aNewShell, aFace); // face shared with another outer shell |
339 | } |
340 | else |
341 | { |
342 | if (aNewFreeFaces.Contains (aFace)) |
343 | aNewFreeFaces.Remove (aFace); // face shared with another merged shell |
344 | else |
345 | aNewFreeFaces.Add (aFace); // face not shared |
346 | } |
347 | } |
348 | } |
349 | theShellsToMerge.Clear(); |
350 | |
351 | // Add the kept faces from the merged shells to the new shell |
352 | TopTools_MapIteratorOfMapOfShape aNewFaceIter (aNewFreeFaces); |
353 | for (; aNewFaceIter.More(); aNewFaceIter.Next()) |
354 | { |
355 | const TopoDS_Shape& aFace = aNewFaceIter.Key(); |
356 | aBuilder.Add (aNewShell, aFace); |
357 | theMapNewFreeFacesToShells.Bind (aFace, aNewShell); |
358 | } |
359 | aNewFreeFaces.Clear(); |
360 | |
361 | // Add needed faces from the base shell to the new shell |
362 | TopoDS_Iterator aBaseFaceIter (theBaseShell); |
363 | for (; aBaseFaceIter.More(); aBaseFaceIter.Next()) |
364 | { |
365 | const TopoDS_Shape& aFace = aBaseFaceIter.Value(); |
366 | if (!aRemoveFaces.Contains (aFace)) |
367 | aBuilder.Add (aNewShell, aFace); |
368 | } |
369 | |
370 | // If there are no elements in the new shell, return null shape |
371 | if (!TopoDS_Iterator (aNewShell).More()) |
372 | return TopoDS_Shape(); |
373 | |
374 | return aNewShell; |
375 | } |
376 | |
377 | //======================================================================= |
378 | //function : AddShells |
379 | //purpose : auxiliary |
380 | //======================================================================= |
381 | // Add some shells to a base shell |
382 | static TopoDS_Compound AddShells ( |
383 | const TopoDS_Shape& theBaseShell, |
384 | TopTools_ListOfShape& theShellsToAdd) |
385 | { |
386 | // Create a compound |
387 | BRep_Builder aBuilder; |
388 | TopoDS_Compound aCompound; |
389 | aBuilder.MakeCompound (aCompound); |
390 | |
391 | // Add the base shell to the compound |
392 | if (!theBaseShell.IsNull()) |
393 | aBuilder.Add (aCompound, theBaseShell); |
394 | |
395 | // Add other shells to the compound |
396 | TopTools_ListIteratorOfListOfShape aShellIter (theShellsToAdd); |
397 | for (; aShellIter.More(); aShellIter.Next()) |
398 | aBuilder.Add (aCompound, aShellIter.Value()); |
399 | |
400 | theShellsToAdd.Clear(); |
401 | |
402 | return aCompound; |
403 | } |
404 | |
405 | TopoDS_Shape ShapeFix_FixSmallSolid::Merge ( |
406 | const TopoDS_Shape& theShape, |
407 | const Handle(ShapeBuild_ReShape)& theContext) const |
408 | { |
409 | // Check if at least one smallness criterion is set and the shape is valid |
410 | if (!IsThresholdsSet() || !IsValidInput (theShape)) return theShape; |
411 | |
412 | // Find all small solids and put them in a list; |
413 | // Build a map of faces belonging to non-small solids |
414 | // but not shared between two non-small solids |
415 | TopTools_ListOfShape aSmallSolids; |
416 | TopTools_DataMapOfShapeShape aMapFacesToShells; |
417 | |
418 | TopExp_Explorer aSolidIter (theShape, TopAbs_SOLID); |
419 | for (; aSolidIter.More(); aSolidIter.Next()) |
420 | { |
421 | const TopoDS_Shape& aSolid = aSolidIter.Current(); |
422 | if (IsSmall (aSolid)) |
423 | aSmallSolids.Append (aSolid); |
424 | else |
425 | MapFacesToShells (aSolid, aMapFacesToShells); |
426 | } |
427 | |
428 | // Merge all small solids adjacent to at least one non-small one; |
429 | // repeat this until no small solids remain or no new solids can be merged |
430 | TopTools_DataMapOfShapeShape aNewMapFacesToShells; |
431 | TopTools_DataMapOfShapeShape* aMapFacesToShellsPtr = &aMapFacesToShells; |
432 | TopTools_DataMapOfShapeShape* aNewMapFacesToShellsPtr = &aNewMapFacesToShells; |
433 | while (!aSmallSolids.IsEmpty()) |
434 | { |
435 | // find small solids that may be merged on the current iteration; |
436 | // compose their shells in lists associated with non-small solids' shells |
437 | // which they should be merged to |
438 | TopTools_DataMapOfShapeListOfShape aShellsToMerge, aShellsToAdd; |
51740958 |
439 | TopTools_ListIteratorOfListOfShape aSmallIter(aSmallSolids); |
440 | while (aSmallIter.More()) |
8422b578 |
441 | { |
51740958 |
442 | const TopoDS_Shape& aSmallSolid = aSmallIter.Value(); |
8422b578 |
443 | |
444 | // find a non-small solid's shell having greatest sum area of |
445 | // all faces shared with the current small solid |
446 | TopoDS_Shape aNonSmallSolidShell; |
447 | TopoDS_Shape anAdjacentShell; |
448 | TopTools_ListOfShape aNotAdjacentShells; |
449 | if (FindMostSharedShell (aSmallSolid, *aMapFacesToShellsPtr, |
450 | aNonSmallSolidShell, anAdjacentShell, aNotAdjacentShells)) |
451 | { |
452 | // add the small solid's shells to appropriate lists |
453 | // associated with the selected non-small solid's shell |
454 | AddToMap (aShellsToMerge, aNonSmallSolidShell, anAdjacentShell); |
455 | AddToMap (aShellsToAdd , aNonSmallSolidShell, aNotAdjacentShells); |
456 | |
457 | // remove the small solid |
458 | theContext->Remove (aSmallSolid); |
7c8996f4 |
459 | SendWarning ( aSmallSolid, Message_Msg( "ShapeFix.FixSmallSolid.MSG1" )); |
81a023ab |
460 | |
51740958 |
461 | aSmallSolids.Remove (aSmallIter); |
8422b578 |
462 | } |
463 | else |
51740958 |
464 | aSmallIter.Next(); |
8422b578 |
465 | } |
466 | |
467 | // stop if no solids can be merged |
468 | if (aShellsToMerge.IsEmpty()) break; |
469 | |
470 | // update needed non-small solids' shells by |
471 | // merging and adding the listed small solids' shells to them |
472 | TopTools_DataMapIteratorOfDataMapOfShapeListOfShape |
473 | aShellIter (aShellsToMerge); |
474 | for (; aShellIter.More(); aShellIter.Next()) |
475 | { |
476 | // get the current non-small solid's shell |
477 | // and corresponding small solids' shells |
478 | const TopoDS_Shape& aBaseShell = aShellIter.Key(); |
479 | TopTools_ListOfShape& aShellsToBeMerged = |
480 | (TopTools_ListOfShape&)aShellIter.Value(); |
481 | TopTools_ListOfShape* aShellsToBeAddedPtr = |
b7c077b9 |
482 | aShellsToAdd.ChangeSeek (aBaseShell); |
8422b578 |
483 | |
484 | // merge needed shells |
485 | TopoDS_Shape aNewShell = MergeShells (aBaseShell, aShellsToBeMerged, |
486 | *aMapFacesToShellsPtr, *aNewMapFacesToShellsPtr); |
487 | |
488 | // add new shells if needed |
489 | if (aShellsToBeAddedPtr != NULL) |
490 | aNewShell = AddShells (aNewShell, *aShellsToBeAddedPtr); |
491 | |
492 | // replace the current non-small solid's shell with the new one(s) |
493 | theContext->Replace (aBaseShell, aNewShell); |
494 | } |
495 | |
496 | // clear the old faces map and start using the new one |
497 | aMapFacesToShellsPtr->Clear(); |
498 | std::swap (aMapFacesToShellsPtr, aNewMapFacesToShellsPtr); |
499 | } |
500 | |
501 | // Return updated shape |
502 | return theContext->Apply (theShape); |
503 | } |
504 | |
505 | //======================================================================= |
506 | //function : IsThresholdsSet |
507 | //purpose : Check if at least one smallness criterion is set |
508 | //======================================================================= |
509 | Standard_Boolean ShapeFix_FixSmallSolid::IsThresholdsSet() const |
510 | { |
df515f16 |
511 | return (IsUsedVolumeThreshold() && myVolumeThreshold < Precision::Infinite()) || |
512 | (IsUsedWidthFactorThreshold() && myWidthFactorThreshold < Precision::Infinite()); |
8422b578 |
513 | } |
514 | |
515 | //======================================================================= |
516 | //function : IsSmall |
517 | //purpose : Check if a solid meets the smallness criteria |
518 | //======================================================================= |
519 | Standard_Boolean ShapeFix_FixSmallSolid::IsSmall (const TopoDS_Shape& theSolid) |
520 | const |
521 | { |
df515f16 |
522 | // If the volume threshold is used and set, and the solid's volume exceeds |
523 | // threshold value, consider the solid as not small |
8422b578 |
524 | Standard_Real aVolume = ShapeVolume (theSolid); |
df515f16 |
525 | if (IsUsedVolumeThreshold() && aVolume > myVolumeThreshold) |
8422b578 |
526 | return Standard_False; |
527 | |
df515f16 |
528 | // If the width factor threshold is used and set, |
529 | // and the solid's width factor exceeds threshold value, |
8422b578 |
530 | // consider the solid as not small |
df515f16 |
531 | if (IsUsedWidthFactorThreshold() && myWidthFactorThreshold < Precision::Infinite()) |
8422b578 |
532 | { |
533 | Standard_Real anArea = ShapeArea (theSolid); |
534 | if (aVolume > myWidthFactorThreshold * anArea * 0.5) |
535 | return Standard_False; |
536 | } |
537 | |
538 | // Both thresholds are met - consider the solid as small |
539 | return Standard_True; |
540 | } |
df515f16 |
541 | //======================================================================= |
542 | //function : IsUsedWidthFactorThreshold |
543 | //purpose : Check if width factor threshold criterion is used |
544 | //======================================================================= |
545 | Standard_Boolean ShapeFix_FixSmallSolid::IsUsedWidthFactorThreshold() const |
546 | { |
547 | return myFixMode == 0 || myFixMode == 1; |
548 | } |
549 | //======================================================================= |
550 | //function : IsUsedVolumeThreshold |
551 | //purpose : Check if volume threshold criterion is used |
552 | //======================================================================= |
553 | Standard_Boolean ShapeFix_FixSmallSolid::IsUsedVolumeThreshold() const |
554 | { |
555 | return myFixMode == 0 || myFixMode == 2; |
556 | } |