1 // Copyright (C) 2014-2022 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GeomAlgoAPI_PointCloudOnFace.h"
22 #include <TopoDS_Shape.hxx>
23 #include <TopoDS_Face.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRepTools.hxx>
28 #include <BRepTools_WireExplorer.hxx>
29 #include <BRepTopAdaptor_FClass2d.hxx>
30 #include <BRepLib_MakeVertex.hxx>
31 #include <GeomLib.hxx>
33 #include <Geom_Plane.hxx>
35 #include <TopoDS_Iterator.hxx>
36 #include <TopExp_Explorer.hxx>
38 #include <GProp_GProps.hxx>
39 #include <BRepGProp.hxx>
40 #include <ShapeAnalysis.hxx>
41 #include <ShapeAnalysis_Surface.hxx>
42 #include <ShapeUpgrade_UnifySameDomain.hxx>
43 #include <ShapeUpgrade_ShapeDivideArea.hxx>
44 #include <BRepAdaptor_Surface.hxx>
45 #include <BRepAdaptor_Curve2d.hxx>
46 #include <BRepBndLib.hxx>
47 #include <GeomLProp_SLProps.hxx>
48 #include <BRepBuilderAPI_MakeEdge.hxx>
49 #include <TopTools_DataMapOfShapeReal.hxx>
51 #include <Standard_Version.hxx>
52 // code from KERNEL_SRC/src/Basics/Basics_OCCTVersion.hxx
53 #ifdef OCC_VERSION_SERVICEPACK
54 # define OCC_VERSION_LARGE (OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8 | OCC_VERSION_SERVICEPACK)
56 # ifdef OCC_VERSION_DEVELOPMENT
57 # define OCC_VERSION_LARGE ((OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8)-1)
59 # define OCC_VERSION_LARGE (OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8)
65 Standard_Boolean comp(const std::pair<TopoDS_Shape, Standard_Real>& theA,
66 const std::pair<TopoDS_Shape, Standard_Real>& theB)
68 return (theA.second < theB.second);
71 Standard_Boolean IsUiso (const TopoDS_Edge& theEdge,
72 const TopoDS_Face& theFace)
74 BRepAdaptor_Curve2d aBAcurve2d (theEdge, theFace);
77 aBAcurve2d.D1 (aBAcurve2d.FirstParameter(), aP2d, aVec);
78 return (Abs(aVec.Y()) > Abs(aVec.X()));
81 void CorrectShell (const TopoDS_Shape& theShell,
82 const TopoDS_Face& theFace)
84 BRepAdaptor_Surface aBAsurf (theFace, Standard_False);
85 GeomAbs_SurfaceType aType = aBAsurf.GetType();
86 if (aType <= GeomAbs_Torus) //elementary surfaces
89 TopLoc_Location anInputLoc;
90 const Handle(Geom_Surface)& anInputSurf = BRep_Tool::Surface (theFace, anInputLoc);
94 TopoDS_Iterator anIter (theShell);
95 for (; anIter.More(); anIter.Next())
97 const TopoDS_Face& aFace = TopoDS::Face (anIter.Value());
99 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aLoc);
100 if (aSurf == anInputSurf)
103 TopExp_Explorer anExplo (aFace, TopAbs_EDGE);
104 for (; anExplo.More(); anExplo.Next())
106 const TopoDS_Edge& anEdge = TopoDS::Edge (anExplo.Current());
107 Standard_Real aFirst, aLast;
108 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface (anEdge, aFace, aFirst, aLast);
109 aBB.UpdateEdge (anEdge, aPCurve, anInputSurf, anInputLoc, 0.);
111 Standard_Real aTol = BRep_Tool::Tolerance (aFace);
112 aBB.UpdateFace (aFace, anInputSurf, anInputLoc, aTol);
116 gp_Pnt GetMidPnt2d(const TopoDS_Face& theFace,
117 const Standard_Boolean theIsNaturalRestrictions)
121 if (theIsNaturalRestrictions)
123 BRepAdaptor_Surface aBAsurf (theFace);
124 Standard_Real aUmin, aUmax, aVmin, aVmax;
125 aUmin = aBAsurf.FirstUParameter();
126 aUmax = aBAsurf.LastUParameter();
127 aVmin = aBAsurf.FirstVParameter();
128 aVmax = aBAsurf.LastVParameter();
129 aResPnt = aBAsurf.Value ((aUmin + aUmax)/2, (aVmin + aVmax)/2);
133 const Standard_Integer aNbSamples = 4;
134 TopoDS_Wire aWire = BRepTools::OuterWire (theFace);
135 TopTools_IndexedMapOfShape aEmap;
136 TopExp::MapShapes (aWire, TopAbs_EDGE, aEmap);
137 Standard_Integer aNbPointsOnContour = aNbSamples * aEmap.Extent();
138 TColgp_Array1OfPnt anArray (1, aNbPointsOnContour);
140 BRepTools_WireExplorer aWexp (aWire, theFace);
141 Standard_Integer anInd = 0;
142 TopTools_MapOfShape aUsedEmap;
143 for (; aWexp.More(); aWexp.Next())
145 const TopoDS_Edge& anEdge = aWexp.Current();
146 if (!aUsedEmap.Add(anEdge)) continue;
147 BRepAdaptor_Curve2d aBAcurve2d (anEdge, theFace);
148 Standard_Real aDelta = (aBAcurve2d.LastParameter() - aBAcurve2d.FirstParameter())/aNbSamples;
149 for (Standard_Integer ii = 0; ii < aNbSamples; ii++)
151 Standard_Real aParam = aBAcurve2d.FirstParameter() + ii * aDelta;
152 gp_Pnt2d aP2d = aBAcurve2d.Value (aParam);
153 gp_Pnt aPnt (aP2d.X(), aP2d.Y(), 0.);
154 anArray (++anInd) = aPnt;
159 Standard_Boolean anIsSingular;
160 GeomLib::AxeOfInertia (anArray, anAxis, anIsSingular);
161 gp_Pnt aBaryCentre = anAxis.Location();
162 gp_Pnt2d aCentre2d (aBaryCentre.X(), aBaryCentre.Y());
163 BRepTopAdaptor_FClass2d aClassifier (theFace, Precision::Confusion());
164 BRepAdaptor_Surface aBAsurf (theFace, Standard_False);
166 TopAbs_State aStatus = aClassifier.Perform (aCentre2d);
167 gp_Pnt2d aP2d = aCentre2d;
168 Standard_Integer anIndVertex = 0;
169 const Standard_Integer aNbIter = 10;
170 while (aStatus != TopAbs_IN && anIndVertex < aNbPointsOnContour)
172 gp_Pnt aVertexPnt = anArray (anIndVertex+1);
173 gp_Pnt2d aVertexP2d (aVertexPnt.X(), aVertexPnt.Y());
174 TColgp_SequenceOfPnt2d aPseq;
175 aPseq.Append (aCentre2d);
176 aPseq.Append (aVertexP2d);
177 for (Standard_Integer ii = 1; ii <= aNbIter; ii++)
179 for (Standard_Integer jj = 1; jj < aPseq.Length(); jj++)
181 aP2d.SetXY ((aPseq(jj).XY() + aPseq(jj+1).XY())/2);
182 aStatus = aClassifier.Perform (aP2d);
183 if (aStatus == TopAbs_IN)
187 aPseq.InsertAfter (jj, aP2d);
191 if (aStatus == TopAbs_IN)
194 anIndVertex += aNbSamples;
196 aResPnt = aBAsurf.Value (aP2d.X(), aP2d.Y());
197 } //case of complex boundaries
202 void ModifyFacesForGlobalResult(const TopoDS_Face& theInputFace,
203 const Standard_Real theAverageArea,
204 const Standard_Boolean theIsToAddFaces,
205 Standard_Integer& theNbExtremalFaces,
206 TopTools_MapOfShape& theExtremalFaces,
207 const std::vector<std::pair<TopoDS_Shape, Standard_Real>> theFacesAndAreas,
208 const TopTools_DataMapOfShapeReal& theFaceAreaMap,
209 const TopTools_IndexedDataMapOfShapeListOfShape& theEFmap,
210 TopoDS_Shape& theRes,
211 TopoDS_Shape& theGlobalRes,
212 TopTools_MapOfShape& theRemovedFaces)
214 BRepAdaptor_Surface aBAsurf (theInputFace, Standard_False);
215 GeomAbs_SurfaceType aType = aBAsurf.GetType();
218 const Standard_Integer aNbFaces = (Standard_Integer) theFacesAndAreas.size();
220 const Standard_Integer aDiff = theNbExtremalFaces - theRemovedFaces.Extent();
222 Standard_Integer aSum = 0;
223 while (aSum < aDiff) //global loop
225 Standard_Integer aNbFacesDone = 0, aNbFacesInTape = 0;
226 TopoDS_Face aStartFace;
228 Standard_Integer aStartIndex = (theIsToAddFaces)? aNbFaces-1 : 0;
229 Standard_Integer anEndIndex = (theIsToAddFaces)? 0 : aNbFaces-1;
230 Standard_Integer aStep = (theIsToAddFaces)? -1 : 1;
232 for (Standard_Integer ii = aStartIndex; ii != anEndIndex; ii += aStep)
234 const TopoDS_Face& aFace = TopoDS::Face (theFacesAndAreas[ii].first);
235 if (!theRemovedFaces.Contains(aFace))
241 if (aStartFace.IsNull())
244 theRemovedFaces.Add (aStartFace);
246 TopoDS_Edge aCommonEdge;
247 TopoDS_Face aNextFace;
248 Standard_Real anExtremalArea = (theIsToAddFaces)? 0. : Precision::Infinite();
249 for (TopExp_Explorer anExplo(aStartFace, TopAbs_EDGE); anExplo.More(); anExplo.Next())
251 const TopoDS_Edge& anEdge = TopoDS::Edge (anExplo.Current());
252 const TopTools_ListOfShape& aFaceList = theEFmap.FindFromKey (anEdge);
253 TopTools_ListIteratorOfListOfShape anItl (aFaceList);
254 for (; anItl.More(); anItl.Next())
256 const TopoDS_Face& aFace = TopoDS::Face (anItl.Value());
257 if (aFace.IsSame (aStartFace) ||
258 theRemovedFaces.Contains(aFace))
260 Standard_Real anArea = theFaceAreaMap(aFace);
261 Standard_Boolean anIsToExchange = (theIsToAddFaces)? (anArea > anExtremalArea) : (anArea < anExtremalArea);
264 anExtremalArea = anArea;
265 aCommonEdge = anEdge;
270 if (aCommonEdge.IsNull()) //all adjacent faces are already removed
272 theExtremalFaces.Add (theFacesAndAreas[theNbExtremalFaces].first);
273 theNbExtremalFaces++;
277 //Start filling the shell
278 aBB.Remove (theRes, aStartFace);
281 aBB.MakeShell (aShell);
282 Standard_Real anAreaOfTape = 0.;
283 aBB.Add (aShell, aStartFace);
285 anAreaOfTape += theFaceAreaMap (aStartFace);
287 Standard_Boolean anIsUiso = IsUiso (aCommonEdge, aStartFace);
288 //Find another faces on this level
289 TopoDS_Face aCurrentFace = aNextFace;
290 TopoDS_Edge aCurrentEdge = aCommonEdge;
291 Standard_Boolean anIsFirstDirection = Standard_True;
292 aBB.Remove (theRes, aCurrentFace);
293 theRemovedFaces.Add (aCurrentFace);
294 if (theExtremalFaces.Contains (aCurrentFace))
298 aBB.Add (aShell, aCurrentFace);
300 anAreaOfTape += theFaceAreaMap (aCurrentFace);
301 Standard_Boolean anIsRound = Standard_False;
302 for (;;) //local loop
304 TopoDS_Edge aNextEdge;
305 for (TopExp_Explorer anExplo(aCurrentFace, TopAbs_EDGE); anExplo.More(); anExplo.Next())
307 const TopoDS_Edge& anEdge = TopoDS::Edge (anExplo.Current());
308 if (anEdge.IsSame (aCurrentEdge))
310 const TopTools_ListOfShape& aFaceList = theEFmap.FindFromKey (anEdge);
311 TopTools_ListIteratorOfListOfShape anItl (aFaceList);
312 for (; anItl.More(); anItl.Next())
314 const TopoDS_Face& aFace = TopoDS::Face (anItl.Value());
315 if (aFace.IsSame (aCurrentFace))
317 if (aFace.IsSame (aStartFace))
319 anIsRound = Standard_True;
320 if (aType > GeomAbs_Torus) { // non-elementary surfaces
321 // remove last face to prevent close tape creation
322 // it is a workaround for Tulip bos #26791
323 // as there is a problem with closed tape on some surface types
324 aBB.Remove (aShell, aCurrentFace);
326 anAreaOfTape -= theFaceAreaMap(aCurrentFace);
327 aBB.Add(theRes, aCurrentFace); // aaajfa ???
328 theRemovedFaces.Remove(aCurrentFace);
329 if (theExtremalFaces.Contains(aCurrentFace)) {
335 if (theRemovedFaces.Contains(aFace))
337 if (anIsUiso == IsUiso (anEdge, aFace))
344 if (anIsRound || !aNextEdge.IsNull())
347 if (anIsRound) //round tape: returned to start face
349 if (aNextEdge.IsNull())
351 if (anIsFirstDirection)
353 aCurrentFace = aStartFace;
354 aCurrentEdge = aCommonEdge;
355 anIsFirstDirection = Standard_False;
362 aBB.Add (aShell, aNextFace);
364 anAreaOfTape += theFaceAreaMap (aNextFace);
365 aBB.Remove (theRes, aNextFace);
366 theRemovedFaces.Add (aNextFace);
367 if (theExtremalFaces.Contains (aNextFace))
371 aCurrentEdge = aNextEdge;
373 aCurrentFace = aNextFace;
374 } //end of local loop
377 Standard_Integer aNumberToSplit = (theIsToAddFaces)? aNbFacesInTape + aNbFacesDone : aNbFacesInTape - aNbFacesDone;
378 if (!theIsToAddFaces && aNbFacesDone > 1)
380 Standard_Integer aRealNumberToSplit = (aNumberToSplit > 0)? aNumberToSplit : 1;
381 Standard_Real anAverageAreaInTape = anAreaOfTape / aRealNumberToSplit;
382 if (anAverageAreaInTape > theAverageArea)
384 Standard_Integer aNewNumberToSplit = RealToInt(round(anAreaOfTape / theAverageArea));
385 if (aNewNumberToSplit < aNbFacesInTape)
387 Standard_Integer aNumberToIncrease = aNewNumberToSplit - aNumberToSplit;
388 for (Standard_Integer jj = theNbExtremalFaces;
389 jj < theNbExtremalFaces + aNumberToIncrease && jj < aNbFaces;
391 theExtremalFaces.Add (theFacesAndAreas[jj].first);
392 theNbExtremalFaces += aNumberToIncrease;
393 aNumberToSplit = aNewNumberToSplit;
397 if (anIsRound && aNumberToSplit <= 1)
399 Standard_Integer aNumberToIncrease = 3 - aNumberToSplit;
400 for (Standard_Integer jj = theNbExtremalFaces;
401 jj < theNbExtremalFaces + aNumberToIncrease && jj < aNbFaces;
403 theExtremalFaces.Add (theFacesAndAreas[jj].first);
404 theNbExtremalFaces += aNumberToIncrease;
407 CorrectShell (aShell, theInputFace);
408 ShapeUpgrade_UnifySameDomain aUnifier;
409 aUnifier.Initialize (aShell, Standard_True, Standard_True);
411 TopoDS_Shape aUnifiedShape = aUnifier.Shape();
413 TopoDS_Shape aLocalResult = aUnifiedShape;
414 Standard_Integer aNbFacesInLocalResult = 1;
415 if (aNumberToSplit > 1)
417 #if OCC_VERSION_LARGE < 0x07050304
418 aNbFacesInLocalResult = 1;
420 ShapeUpgrade_ShapeDivideArea aLocalTool (aUnifiedShape);
421 aLocalTool.SetSplittingByNumber (Standard_True);
422 aLocalTool.MaxArea() = -1;
424 aLocalTool.SetNumbersUVSplits (aNumberToSplit, 1);
426 aLocalTool.SetNumbersUVSplits (1, aNumberToSplit);
427 aLocalTool.Perform();
428 aLocalResult = aLocalTool.Result();
429 aNbFacesInLocalResult = aNumberToSplit;
434 if (aNumberToSplit == 0)
436 if (theNbExtremalFaces < aNbFaces) {
437 theExtremalFaces.Add (theFacesAndAreas[theNbExtremalFaces].first);
438 theNbExtremalFaces++;
442 aBB.Add (theGlobalRes, aLocalResult);
444 aSum += Abs(aNbFacesInTape - aNbFacesInLocalResult);
445 } //end of global loop
448 TopoDS_Compound aSecondComp;
449 aBB.MakeCompound (aSecondComp);
452 TopoDS_Shape aMaxShell;
453 Standard_Integer aMaxNbFaces = 0;
454 TopoDS_Iterator anIter (theGlobalRes);
455 for (; anIter.More(); anIter.Next())
457 const TopoDS_Shape& aShell = anIter.Value();
458 TopTools_IndexedMapOfShape aFaceMap;
459 TopExp::MapShapes (aShell, TopAbs_FACE, aFaceMap);
460 if (aFaceMap.Extent() > aMaxNbFaces)
462 aMaxNbFaces = aFaceMap.Extent();
467 if (aMaxNbFaces == 1)
470 aBB.Remove (theGlobalRes, aMaxShell);
472 Standard_Boolean anIsUiso = Standard_True;
473 TopTools_IndexedDataMapOfShapeListOfShape aLocalEFmap;
474 TopExp::MapShapesAndAncestors (aMaxShell, TopAbs_EDGE, TopAbs_FACE, aLocalEFmap);
475 for (Standard_Integer jj = 1; jj <= aLocalEFmap.Extent(); jj++)
477 const TopoDS_Edge& anEdge = TopoDS::Edge (aLocalEFmap.FindKey(jj));
478 const TopTools_ListOfShape& aFaceList = aLocalEFmap(jj);
479 if (aFaceList.Extent() == 2)
481 const TopoDS_Face& aFace = TopoDS::Face (aFaceList.First());
482 anIsUiso = IsUiso (anEdge, aFace);
486 CorrectShell (aMaxShell, theInputFace);
487 ShapeUpgrade_UnifySameDomain aUnifier;
488 aUnifier.Initialize (aMaxShell, Standard_True, Standard_True);
490 TopoDS_Shape aUnifiedShape = aUnifier.Shape();
491 TopoDS_Shape aLocalResult = aUnifiedShape;
493 Standard_Integer aNumberToSplit = (theIsToAddFaces)? aMaxNbFaces + (aDiff-aSum) : aMaxNbFaces - (aDiff-aSum);
494 if (aNumberToSplit > 1)
496 #if OCC_VERSION_LARGE < 0x07050304
499 ShapeUpgrade_ShapeDivideArea aLocalTool (aUnifiedShape);
500 aLocalTool.SetSplittingByNumber (Standard_True);
501 aLocalTool.MaxArea() = -1;
503 aLocalTool.SetNumbersUVSplits (aNumberToSplit, 1);
505 aLocalTool.SetNumbersUVSplits (1, aNumberToSplit);
506 aLocalTool.Perform();
507 aLocalResult = aLocalTool.Result();
513 aBB.Add (aSecondComp, aLocalResult);
517 aSum += aMaxNbFaces - aNumberToSplit;
519 aBB.Add (theGlobalRes, aSecondComp);
522 //=================================================================================================
523 bool GeomAlgoAPI_PointCloudOnFace::PointCloud(GeomShapePtr theFace,
524 const int theNumberOfPoints,
525 GeomShapePtr thePoints,
526 std::string& theError)
529 std::cout << "GeomAlgoAPI_PointCloudOnFace::PointCloud" << std::endl;
532 #if OCC_VERSION_LARGE < 0x07050304
533 theError = "Improper OCCT version: please, use OCCT 7.5.3p4 or newer.";
537 if (!theFace.get()) {
538 theError = "Face for point cloud calculation is null";
542 TopoDS_Shape anInputShape = theFace->impl<TopoDS_Shape>();
544 if (anInputShape.ShapeType() != TopAbs_FACE) {
545 theError = "Shape for normale calculation is not a face";
549 TopoDS_Face anInputFace = TopoDS::Face (anInputShape);
551 ShapeUpgrade_ShapeDivideArea tool (anInputFace);
552 tool.SetSplittingByNumber (Standard_True);
553 tool.NbParts() = theNumberOfPoints;
555 TopoDS_Shape res = tool.Result();
558 TopoDS_Compound aGlobalRes;
559 aBB.MakeCompound (aGlobalRes);
561 TopTools_IndexedMapOfShape aFaceMap;
562 TopExp::MapShapes (res, TopAbs_FACE, aFaceMap);
563 Standard_Integer aNbFaces = aFaceMap.Extent();
565 TopTools_IndexedDataMapOfShapeListOfShape aEFmap;
566 TopExp::MapShapesAndAncestors (res, TopAbs_EDGE, TopAbs_FACE, aEFmap);
568 TopTools_MapOfShape aBiggestFaces, aSmallestFaces;
569 Standard_Boolean aUseTriangulation = Standard_True;
570 Standard_Boolean aSkipShared = Standard_False;
571 if (aNbFaces != theNumberOfPoints)
573 Standard_Real aTotalArea = 0.;
574 std::vector<std::pair<TopoDS_Shape, Standard_Real>> aFacesAndAreas (aNbFaces);
575 for (Standard_Integer ii = 1; ii <= aNbFaces; ii++)
578 BRepGProp::SurfaceProperties (aFaceMap(ii), aProps, aSkipShared, aUseTriangulation);
579 Standard_Real anArea = aProps.Mass();
580 aTotalArea += anArea;
581 std::pair<TopoDS_Shape, Standard_Real> aFaceWithArea (aFaceMap(ii), anArea);
582 aFacesAndAreas[ii-1] = aFaceWithArea;
584 std::sort (aFacesAndAreas.begin(), aFacesAndAreas.end(), comp);
586 Standard_Real anAverageArea = aTotalArea / theNumberOfPoints;
588 TopTools_DataMapOfShapeReal aFaceAreaMap;
589 for (Standard_Integer ii = 0; ii < aNbFaces; ii++)
590 aFaceAreaMap.Bind (aFacesAndAreas[ii].first, aFacesAndAreas[ii].second);
592 TopTools_MapOfShape aRemovedFaces;
594 if (aNbFaces < theNumberOfPoints)
596 Standard_Integer aNbMissingFaces = theNumberOfPoints - aNbFaces;
597 for (Standard_Integer ii = aNbFaces-1; ii > aNbFaces - aNbMissingFaces - 1; ii--)
598 aBiggestFaces.Add (aFacesAndAreas[ii].first);
600 ModifyFacesForGlobalResult (anInputFace, anAverageArea,
601 Standard_True, //to add faces
602 aNbMissingFaces, aBiggestFaces,
603 aFacesAndAreas, aFaceAreaMap, aEFmap,
607 else //aNbFaces > theNumberOfPoints
609 Standard_Integer aNbExcessFaces = aNbFaces - theNumberOfPoints;
610 for (Standard_Integer ii = 0; ii < aNbExcessFaces; ii++)
611 aSmallestFaces.Add (aFacesAndAreas[ii].first);
613 TopTools_IndexedDataMapOfShapeListOfShape aVFmap;
614 TopExp::MapShapesAndAncestors (res, TopAbs_VERTEX, TopAbs_FACE, aVFmap);
616 //Remove smallest faces with free boundaries
617 for (Standard_Integer ii = 0; ii < aNbExcessFaces; ii++)
619 const TopoDS_Face& aFace = TopoDS::Face (aFacesAndAreas[ii].first);
620 Standard_Boolean anIsFreeBoundFound = Standard_False;
621 TopExp_Explorer anExplo (aFace, TopAbs_EDGE);
622 for (; anExplo.More(); anExplo.Next())
624 const TopoDS_Edge& anEdge = TopoDS::Edge (anExplo.Current());
625 if (!BRep_Tool::Degenerated (anEdge) &&
626 aEFmap.FindFromKey(anEdge).Extent() < 2)
628 anIsFreeBoundFound = Standard_True;
632 if (anIsFreeBoundFound)
634 Standard_Real aMaxArea = 0.;
635 for (anExplo.Init(aFace, TopAbs_VERTEX); anExplo.More(); anExplo.Next())
637 const TopoDS_Shape& aVertex = anExplo.Current();
638 const TopTools_ListOfShape& aFaceList = aVFmap.FindFromKey (aVertex);
639 TopTools_ListIteratorOfListOfShape anItl (aFaceList);
640 for (; anItl.More(); anItl.Next())
642 Standard_Real anArea = aFaceAreaMap (anItl.Value());
643 if (anArea > aMaxArea)
647 Standard_Real anArreaOfSmallestFace = aFaceAreaMap (aFace);
648 if (anArreaOfSmallestFace < aMaxArea / 16)
650 aBB.Remove (res, aFace);
651 aRemovedFaces.Add (aFace);
656 ModifyFacesForGlobalResult (anInputFace, anAverageArea,
657 Standard_False, //to decrease number of faces
658 aNbExcessFaces, aSmallestFaces,
659 aFacesAndAreas, aFaceAreaMap, aEFmap,
665 aBB.Add (aGlobalRes, res);
668 TopoDS_Compound aCompound;
669 aBB.MakeCompound (aCompound);
670 for (TopExp_Explorer aGlobalExplo(aGlobalRes, TopAbs_FACE);
671 aGlobalExplo.More(), iface <= theNumberOfPoints;
672 aGlobalExplo.Next(), iface++)
674 const TopoDS_Face& aFace = TopoDS::Face (aGlobalExplo.Current());
675 Standard_Boolean anIsNaturalRestrictions = Standard_True;
676 TopExp_Explorer anExplo (aFace, TopAbs_EDGE);
677 for (; anExplo.More(); anExplo.Next())
679 const TopoDS_Edge& anEdge = TopoDS::Edge (anExplo.Current());
680 if (BRep_Tool::Degenerated (anEdge))
682 if (!aEFmap.Contains(anEdge) ||
683 aEFmap.FindFromKey(anEdge).Extent() < 2)
685 anIsNaturalRestrictions = Standard_False;
690 gp_Pnt aPnt = GetMidPnt2d (aFace, anIsNaturalRestrictions);
691 TopoDS_Vertex aVertex = BRepLib_MakeVertex (aPnt);
692 aBB.Add (aCompound, aVertex);
695 thePoints->setImpl(new TopoDS_Shape(aCompound));