1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/BRepLib/BRepLib_PointCloudShape.cxx
dpasukhi 52cbf180cd 0033375: Coding - Static Analyzing processing. Performance
Performance update applied:
  - moving to const reference as much as possible
Result of CLANG_TIDY (static analyzing filter: perform*)
2023-07-21 16:33:47 +01:00

308 lines
9.3 KiB
C++

// Copyright (c) 2021 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BRepLib_PointCloudShape.hxx>
#include <BRep_Tool.hxx>
#include <BRepGProp.hxx>
#include <BRepLib_ToolTriangulatedShape.hxx>
#include <BRepTools.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <Geom_Surface.hxx>
#include <GProp_GProps.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <random>
// =======================================================================
// function : BRepLib_PointCloudShape
// purpose :
// =======================================================================
BRepLib_PointCloudShape::BRepLib_PointCloudShape (const TopoDS_Shape& theShape,
const Standard_Real theTol)
: myShape (theShape),
myDist (0.0),
myTol (theTol),
myNbPoints (0)
{
//
}
// =======================================================================
// function : ~BRepLib_PointCloudShape
// purpose :
// =======================================================================
BRepLib_PointCloudShape::~BRepLib_PointCloudShape()
{
//
}
// =======================================================================
// function : NbPointsByDensity
// purpose :
// =======================================================================
Standard_Integer BRepLib_PointCloudShape::NbPointsByDensity (const Standard_Real theDensity)
{
clear();
Standard_Real aDensity = (theDensity < Precision::Confusion() ? computeDensity() : theDensity);
if (aDensity < Precision::Confusion())
{
return 0;
}
Standard_Integer aNbPoints = 0;
for (TopExp_Explorer aExpF(myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
Standard_Real anArea = faceArea(aExpF.Current());
Standard_Integer aNbPnts = Max ((Standard_Integer)std::ceil(anArea / theDensity), 1);
myFacePoints.Bind(aExpF.Current(), aNbPnts);
aNbPoints+= aNbPnts;
}
return aNbPoints;
}
// =======================================================================
// function : GeneratePointsByDensity
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::GeneratePointsByDensity (const Standard_Real theDensity)
{
if (myFacePoints.IsEmpty())
{
if (NbPointsByDensity (theDensity) == 0)
{
return Standard_False;
}
}
Standard_Integer aNbAdded = 0;
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
if (addDensityPoints (aExpF.Current()))
{
aNbAdded++;
}
}
return (aNbAdded > 0);
}
// =======================================================================
// function : GeneratePointsByTriangulation
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::GeneratePointsByTriangulation()
{
clear();
Standard_Integer aNbAdded = 0;
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
if (addTriangulationPoints (aExpF.Current()))
{
aNbAdded++;
}
}
return (aNbAdded > 0);
}
// =======================================================================
// function : faceArea
// purpose :
// =======================================================================
Standard_Real BRepLib_PointCloudShape::faceArea (const TopoDS_Shape& theShape)
{
Standard_Real anArea = 0.0;
if (myFaceArea.Find (theShape, anArea))
{
return anArea;
}
GProp_GProps aFaceProps;
BRepGProp::SurfaceProperties (theShape, aFaceProps);
anArea = aFaceProps.Mass();
myFaceArea.Bind (theShape, anArea);
return anArea;
}
// =======================================================================
// function : computeDensity
// purpose :
// =======================================================================
Standard_Real BRepLib_PointCloudShape::computeDensity()
{
// at first step find the face with smallest area
Standard_Real anAreaMin = Precision::Infinite();
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
Standard_Real anArea = faceArea (aExpF.Current());
if (anArea < myTol * myTol)
{
continue;
}
if (anArea < anAreaMin)
{
anAreaMin = anArea;
}
}
return anAreaMin * 0.1;
}
// =======================================================================
// function : NbPointsByTriangulation
// purpose :
// =======================================================================
Standard_Integer BRepLib_PointCloudShape::NbPointsByTriangulation() const
{
// at first step find the face with smallest area
Standard_Integer aNbPoints = 0;
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (aExpF.Current()), aLoc);
if (aTriangulation.IsNull())
{
continue;
}
aNbPoints += aTriangulation->NbNodes();
}
return aNbPoints;
}
// =======================================================================
// function : addDensityPoints
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::addDensityPoints (const TopoDS_Shape& theFace)
{
//addition of the points with specified density on the face by random way
Standard_Integer aNbPnts = (myFacePoints.IsBound (theFace) ? myFacePoints.Find (theFace) : 0);
if (aNbPnts == 0)
{
return Standard_False;
}
TopoDS_Face aFace = TopoDS::Face (theFace);
Standard_Real anUMin = 0.0, anUMax = 0.0, aVMin = 0.0, aVMax = 0.0;
BRepTools::UVBounds (aFace, anUMin, anUMax, aVMin, aVMax);
BRepTopAdaptor_FClass2d aClassifier (aFace, Precision::Confusion());
const TopLoc_Location& aLoc = theFace.Location();
const gp_Trsf& aTrsf = aLoc.Transformation();
TopLoc_Location aLoc1;
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace, aLoc1);
if (aSurf.IsNull())
{
return Standard_False;
}
std::mt19937 aRandomGenerator(0);
std::uniform_real_distribution<> anUDistrib(anUMin, anUMax);
std::uniform_real_distribution<> aVDistrib (aVMin, aVMax);
for (Standard_Integer nbCurPnts = 1; nbCurPnts <= aNbPnts;)
{
const Standard_Real aU = anUDistrib(aRandomGenerator);
const Standard_Real aV = aVDistrib (aRandomGenerator);
gp_Pnt2d aUVNode (aU, aV);
const TopAbs_State aState = aClassifier.Perform (aUVNode);
if (aState == TopAbs_OUT)
{
continue;
}
nbCurPnts++;
gp_Pnt aP1;
gp_Vec dU, dV;
aSurf->D1 (aU, aV, aP1, dU, dV);
gp_Vec aNorm = dU ^ dV;
if (aFace.Orientation() == TopAbs_REVERSED)
{
aNorm.Reverse();
}
const Standard_Real aNormMod = aNorm.Magnitude();
if (aNormMod > gp::Resolution())
{
aNorm /= aNormMod;
}
if (myDist > Precision::Confusion())
{
std::uniform_real_distribution<> aDistanceDistrib (0.0, myDist);
gp_XYZ aDeflPoint = aP1.XYZ() + aNorm.XYZ() * aDistanceDistrib (aRandomGenerator);
aP1.SetXYZ (aDeflPoint);
}
aP1.Transform (aTrsf);
if (aNormMod > gp::Resolution())
{
aNorm = gp_Dir (aNorm).Transformed (aTrsf);
}
addPoint (aP1, aNorm, aUVNode, aFace);
}
return Standard_True;
}
// =======================================================================
// function : addTriangulationPoints
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::addTriangulationPoints (const TopoDS_Shape& theFace)
{
TopLoc_Location aLoc;
TopoDS_Face aFace = TopoDS::Face (theFace);
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLoc);
if (aTriangulation.IsNull())
{
return Standard_False;
}
TopLoc_Location aLoc1;
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace, aLoc1);
const gp_Trsf& aTrsf = aLoc.Transformation();
BRepLib_ToolTriangulatedShape::ComputeNormals (aFace, aTriangulation);
Standard_Boolean aHasUVNode = aTriangulation->HasUVNodes();
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter)
{
gp_Pnt aP1 = aTriangulation->Node (aNodeIter);
gp_Dir aNormal = aTriangulation->Normal(aNodeIter);
if (!aLoc.IsIdentity())
{
aP1 .Transform (aTrsf);
aNormal.Transform (aTrsf);
}
const gp_Pnt2d anUVNode = aHasUVNode ? aTriangulation->UVNode (aNodeIter) : gp_Pnt2d();
addPoint (aP1, aNormal, anUVNode, aFace);
}
return Standard_True;
}
// =======================================================================
// function : clear
// purpose :
// =======================================================================
void BRepLib_PointCloudShape::clear()
{
myFaceArea.Clear();
myFacePoints.Clear();
}