mesh segmentation algorithm for surfaces

This commit is contained in:
wmayer
2018-12-10 13:19:27 +01:00
parent 1f2dc3a366
commit e1e86caac1
5 changed files with 164 additions and 18 deletions

View File

@@ -912,6 +912,55 @@ void CylinderFit::ProjectToCylinder()
// -----------------------------------------------------------------------------
SphereFit::SphereFit()
: _vCenter(0,0,0)
, _fRadius(0)
{
}
SphereFit::~SphereFit()
{
}
float SphereFit::GetRadius() const
{
if (_bIsFitted)
return _fRadius;
else
return FLOAT_MAX;
}
Base::Vector3f SphereFit::GetCenter() const
{
if (_bIsFitted)
return _vCenter;
else
return Base::Vector3f();
}
float SphereFit::Fit()
{
return FLOAT_MAX;
}
float SphereFit::GetDistanceToSphere(const Base::Vector3f &) const
{
return FLOAT_MAX;
}
float SphereFit::GetStdDeviation() const
{
return FLOAT_MAX;
}
void SphereFit::ProjectToSphere()
{
}
// -------------------------------------------------------------------------------
PolynomialFit::PolynomialFit()
{
for (int i=0; i<9; i++)

View File

@@ -406,6 +406,48 @@ protected:
// -------------------------------------------------------------------------------
/**
* Approximation of a sphere into a given set of points.
*/
class MeshExport SphereFit : public Approximation
{
public:
/**
* Construction
*/
SphereFit();
/**
* Destruction
*/
virtual ~SphereFit();
float GetRadius() const;
Base::Vector3f GetCenter() const;
/**
* Fit a sphere into the given points. If the fit fails FLOAT_MAX is returned.
*/
float Fit();
/**
* Returns the distance from the point \a rcPoint to the fitted sphere. If Fit() has not been
* called FLOAT_MAX is returned.
*/
float GetDistanceToSphere(const Base::Vector3f &rcPoint) const;
/**
* Returns the standard deviation from the points to the fitted sphere. If Fit() has not been
* called FLOAT_MAX is returned.
*/
float GetStdDeviation() const;
/**
* Projects the points onto the fitted sphere.
*/
void ProjectToSphere();
protected:
Base::Vector3f _vCenter; /**< Center of the sphere. */
float _fRadius; /**< Radius of the cylinder. */
};
// -------------------------------------------------------------------------------
/**
* Helper class for the quadric fit. Includes the
* partial derivates of the quadric and serves for

View File

@@ -218,8 +218,10 @@ void CylinderSurfaceFit::AddTriangle(const MeshCore::MeshGeomFacet& tria)
bool CylinderSurfaceFit::TestTriangle(const MeshGeomFacet& tria) const
{
// This is to filter out triangles whose points lie on the cylinder and
// that whose normals are more or less parallel to the cylinder axis
float dot = axis.Dot(tria.GetNormal());
return fabs(dot) < 0.01f;
return fabs(dot) < 0.5f;
}
bool CylinderSurfaceFit::Done() const
@@ -258,6 +260,7 @@ float CylinderSurfaceFit::GetDistanceToSurface(const Base::Vector3f& pnt) const
// --------------------------------------------------------
SphereSurfaceFit::SphereSurfaceFit()
: fitter(new SphereFit)
{
center.Set(0,0,0);
radius = FLOAT_MAX;
@@ -266,25 +269,36 @@ SphereSurfaceFit::SphereSurfaceFit()
SphereSurfaceFit::SphereSurfaceFit(const Base::Vector3f& c, float r)
: center(c)
, radius(r)
, fitter(0)
{
}
SphereSurfaceFit::~SphereSurfaceFit()
{
delete fitter;
}
void SphereSurfaceFit::Initialize(const MeshCore::MeshGeomFacet& tria)
{
//FIXME
if (fitter) {
fitter->Clear();
fitter->AddPoint(tria._aclPoints[0]);
fitter->AddPoint(tria._aclPoints[1]);
fitter->AddPoint(tria._aclPoints[2]);
}
}
void SphereSurfaceFit::AddTriangle(const MeshCore::MeshGeomFacet& tria)
{
//FIXME
if (fitter) {
fitter->AddPoint(tria._aclPoints[0]);
fitter->AddPoint(tria._aclPoints[1]);
fitter->AddPoint(tria._aclPoints[2]);
}
}
bool SphereSurfaceFit::TestTriangle(const MeshGeomFacet& tria) const
bool SphereSurfaceFit::TestTriangle(const MeshGeomFacet&) const
{
// Already handled by GetDistanceToSurface
return true;
@@ -292,14 +306,24 @@ bool SphereSurfaceFit::TestTriangle(const MeshGeomFacet& tria) const
bool SphereSurfaceFit::Done() const
{
//FIXME
if (fitter) {
return fitter->Done();
}
return true;
}
float SphereSurfaceFit::Fit()
{
//FIXME
return 0;
if (!fitter)
return 0;
float fit = fitter->Fit();
if (fit < FLOAT_MAX) {
center = fitter->GetCenter();
radius = fitter->GetRadius();
}
return fit;
}
float SphereSurfaceFit::GetDistanceToSurface(const Base::Vector3f& pnt) const

View File

@@ -32,6 +32,7 @@ namespace MeshCore {
class PlaneFit;
class CylinderFit;
class SphereFit;
class MeshFacet;
typedef std::vector<unsigned long> MeshSegment;
@@ -89,6 +90,7 @@ class MeshExport AbstractSurfaceFit
public:
AbstractSurfaceFit(){}
virtual ~AbstractSurfaceFit(){}
virtual const char* GetType() const = 0;
virtual void Initialize(const MeshGeomFacet&) = 0;
virtual bool TestTriangle(const MeshGeomFacet&) const = 0;
virtual void AddTriangle(const MeshGeomFacet&) = 0;
@@ -103,6 +105,7 @@ public:
PlaneSurfaceFit();
PlaneSurfaceFit(const Base::Vector3f& b, const Base::Vector3f& n);
~PlaneSurfaceFit();
const char* GetType() const { return "Plane"; }
void Initialize(const MeshGeomFacet&);
bool TestTriangle(const MeshGeomFacet&) const;
void AddTriangle(const MeshGeomFacet&);
@@ -122,6 +125,7 @@ public:
CylinderSurfaceFit();
CylinderSurfaceFit(const Base::Vector3f& b, const Base::Vector3f& a, float r);
~CylinderSurfaceFit();
const char* GetType() const { return "Cylinder"; }
void Initialize(const MeshGeomFacet&);
bool TestTriangle(const MeshGeomFacet&) const;
void AddTriangle(const MeshGeomFacet&);
@@ -142,6 +146,7 @@ public:
SphereSurfaceFit();
SphereSurfaceFit(const Base::Vector3f& c, float r);
~SphereSurfaceFit();
const char* GetType() const { return "Sphere"; }
void Initialize(const MeshGeomFacet&);
bool TestTriangle(const MeshGeomFacet&) const;
void AddTriangle(const MeshGeomFacet&);
@@ -152,6 +157,7 @@ public:
private:
Base::Vector3f center;
float radius;
SphereFit* fitter;
};
class MeshExport MeshDistanceGenericSurfaceFitSegment : public MeshDistanceSurfaceSegment
@@ -161,7 +167,7 @@ public:
unsigned long minFacets, float tol);
virtual ~MeshDistanceGenericSurfaceFitSegment();
bool TestFacet (const MeshFacet& rclFacet) const;
const char* GetType() const { return "GenericSurfaceFit"; }
const char* GetType() const { return fitter->GetType(); }
void Initialize(unsigned long);
bool TestInitialFacet(unsigned long) const;
void AddFacet(const MeshFacet& rclFacet);

View File

@@ -52,18 +52,19 @@ public:
PlaneFitParameter() {}
virtual ~PlaneFitParameter() {}
virtual std::vector<float> getParameter(FitParameter::Points pts) const {
std::vector<float> values;
MeshCore::PlaneFit fit;
fit.AddPoints(pts);
fit.Fit();
Base::Vector3f base = fit.GetBase();
Base::Vector3f axis = fit.GetNormal();
std::vector<float> values;
values.push_back(base.x);
values.push_back(base.y);
values.push_back(base.z);
values.push_back(axis.x);
values.push_back(axis.y);
values.push_back(axis.z);
if (fit.Fit() < FLOAT_MAX) {
Base::Vector3f base = fit.GetBase();
Base::Vector3f axis = fit.GetNormal();
values.push_back(base.x);
values.push_back(base.y);
values.push_back(base.z);
values.push_back(axis.x);
values.push_back(axis.y);
values.push_back(axis.z);
}
return values;
}
};
@@ -75,6 +76,20 @@ public:
virtual ~CylinderFitParameter() {}
virtual std::vector<float> getParameter(FitParameter::Points pts) const {
std::vector<float> values;
MeshCore::CylinderFit fit;
fit.AddPoints(pts);
if (fit.Fit() < FLOAT_MAX) {
Base::Vector3f base = fit.GetBase();
Base::Vector3f axis = fit.GetAxis();
float radius = fit.GetRadius();
values.push_back(base.x);
values.push_back(base.y);
values.push_back(base.z);
values.push_back(axis.x);
values.push_back(axis.y);
values.push_back(axis.z);
values.push_back(radius);
}
return values;
}
};
@@ -86,6 +101,16 @@ public:
virtual ~SphereFitParameter() {}
virtual std::vector<float> getParameter(FitParameter::Points pts) const {
std::vector<float> values;
MeshCore::SphereFit fit;
fit.AddPoints(pts);
if (fit.Fit() < FLOAT_MAX) {
Base::Vector3f base = fit.GetCenter();
float radius = fit.GetRadius();
values.push_back(base.x);
values.push_back(base.y);
values.push_back(base.z);
values.push_back(radius);
}
return values;
}
};