diff --git a/src/Mod/Mesh/App/Core/Approximation.cpp b/src/Mod/Mesh/App/Core/Approximation.cpp index 41b607810b..5b3a260bec 100644 --- a/src/Mod/Mesh/App/Core/Approximation.cpp +++ b/src/Mod/Mesh/App/Core/Approximation.cpp @@ -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++) diff --git a/src/Mod/Mesh/App/Core/Approximation.h b/src/Mod/Mesh/App/Core/Approximation.h index 310c08ed0e..cf6ccd450e 100644 --- a/src/Mod/Mesh/App/Core/Approximation.h +++ b/src/Mod/Mesh/App/Core/Approximation.h @@ -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 diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index aae8f83334..15fa0fe18b 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -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 diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index d203efea63..d2ac9715cf 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -32,6 +32,7 @@ namespace MeshCore { class PlaneFit; class CylinderFit; +class SphereFit; class MeshFacet; typedef std::vector 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); diff --git a/src/Mod/Mesh/Gui/SegmentationBestFit.cpp b/src/Mod/Mesh/Gui/SegmentationBestFit.cpp index 4566fee0ac..0e04012b3a 100644 --- a/src/Mod/Mesh/Gui/SegmentationBestFit.cpp +++ b/src/Mod/Mesh/Gui/SegmentationBestFit.cpp @@ -52,18 +52,19 @@ public: PlaneFitParameter() {} virtual ~PlaneFitParameter() {} virtual std::vector getParameter(FitParameter::Points pts) const { + std::vector values; MeshCore::PlaneFit fit; fit.AddPoints(pts); - fit.Fit(); - Base::Vector3f base = fit.GetBase(); - Base::Vector3f axis = fit.GetNormal(); - std::vector 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 getParameter(FitParameter::Points pts) const { std::vector 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 getParameter(FitParameter::Points pts) const { std::vector 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; } };