GrabBag/AppAlgo/holeDetection/include/GeometricFitting.h
2026-03-11 23:40:06 +08:00

176 lines
5.2 KiB
C

#ifndef GEOMETRIC_FITTING_H
#define GEOMETRIC_FITTING_H
#include "HoleDetectionParams.h"
#include "ErrorCodes.h"
#include "../include/VZNL_Types.h"
/**
* @brief Fit ellipse to 2D boundary points
*
* @param [in] points 3D boundary points (will be projected to 2D)
* @param [in] pointCount Number of points
* @param [out] outCenter Ellipse center (x, y, z)
* @param [out] outRadius Ellipse radius (average of semi-major and semi-minor axes)
* @param [out] outEccentricity Eccentricity (0 = circle)
* @param [out] errCode Error code output
* @return 0 on success, non-zero on error
*
* @pre points != nullptr
* @pre pointCount >= 5
* @pre outCenter != nullptr
* @pre outRadius != nullptr
* @pre outEccentricity != nullptr
* @pre errCode != nullptr
*/
int FitEllipse(
const SVzNLPointXYZ* points,
int pointCount,
SVzNL3DPointF* outCenter,
float* outRadius,
float* outEccentricity,
int* errCode
);
/**
* @brief Fit plane to 3D points
*
* @param [in] points 3D points
* @param [in] pointCount Number of points
* @param [out] outNormal Plane normal vector (unit length)
* @param [out] outD Plane equation constant (ax+by+cz+d=0)
* @param [out] errCode Error code output
* @return 0 on success, non-zero on error
*
* @pre points != nullptr
* @pre pointCount >= 3
* @pre outNormal != nullptr
* @pre outD != nullptr
* @pre errCode != nullptr
*
* @post ||outNormal|| = 1.0 ± 1e-6
*/
int FitPlane(
const SVzNLPointXYZ* points,
int pointCount,
SVzNL3DPointF* outNormal,
float* outD,
int* errCode
);
/**
* @brief Compute quality score for hole
*
* @param [in] eccentricity Eccentricity (0 = perfect circle)
* @param [in] radiusVariance Radius variance (mm)
* @param [in] angularSpan Angular coverage (degrees)
* @param [in] boundaryPointCount Number of boundary points
* @return Quality score (0-1, higher = better)
*/
float ComputeQualityScore(
float eccentricity,
float radiusVariance,
float angularSpan,
int boundaryPointCount
);
/**
* @brief Compute rectangularity score using PCA + corner detection
*
* Uses PCA to align points, then counts points in "corner regions"
* (where u² + v² > 1.1 in normalized coordinates).
* Ellipse points stay within u² + v² ≤ 1.0, rectangle corners exceed this.
*
* @param [in] points 3D boundary points (X-Y used for analysis)
* @param [in] pointCount Number of points
* @return Corner ratio (0-1). Higher = more rectangular.
* Returns 0 if pointCount < 4.
*/
float ComputeRectangularityScore(
const SVzNLPointXYZ* points,
int pointCount
);
/**
* @brief Compute angular coverage of points around centroid
*
* Calculates what percentage of 360° is covered by the point distribution.
* Used to detect incomplete/non-closed boundaries.
*
* @param [in] points 3D boundary points (X-Y used for analysis)
* @param [in] pointCount Number of points
* @param [in] numBins Number of angular bins (default: 36 = 10° each)
* @return Angular coverage in degrees (0-360).
* Returns 0 if pointCount < 3.
*/
float ComputeAngularCoverage(
const SVzNLPointXYZ* points,
int pointCount,
int numBins = 36
);
/**
* @brief Compute angular coverage of points around a specified center
*
* Same as above, but uses the given center instead of computing centroid.
* Use this when a fitted center (e.g. from ellipse fitting) is available.
*
* @param [in] points 3D boundary points (X-Y used for analysis)
* @param [in] pointCount Number of points
* @param [in] centerX X coordinate of the reference center
* @param [in] centerY Y coordinate of the reference center
* @param [in] numBins Number of angular bins (default: 36 = 10° each)
* @return Angular coverage in degrees (0-360).
* Returns 0 if pointCount < 3.
*/
float ComputeAngularCoverage(
const SVzNLPointXYZ* points,
int pointCount,
float centerX,
float centerY,
int numBins = 36
);
/**
* @brief Check circularity of points in X-Y plane
*
* Computes the coefficient of variation (CV) of distances from each point
* to the centroid. Low CV indicates circular/elliptical distribution.
*
* @param [in] points 3D boundary points (X-Y used for analysis)
* @param [in] pointCount Number of points
* @param [in] maxCV Maximum allowed CV (default: 0.4)
* @return true if CV <= maxCV (circular enough), false otherwise.
* Returns false if pointCount < 3.
*/
bool CheckCircularity(
const SVzNLPointXYZ* points,
int pointCount,
float maxCV = 0.4f
);
/**
* @brief Compute inlier ratio for ellipse fit
*
* Calculates the fraction of points whose distance to the fitted ellipse
* center is within tolerance of the fitted radius.
*
* @param [in] points 2D projected points (X-Y used)
* @param [in] pointCount Number of points
* @param [in] centerX Fitted ellipse center X
* @param [in] centerY Fitted ellipse center Y
* @param [in] radius Fitted average radius
* @param [in] tolerance Distance tolerance as fraction of radius (default: 0.3)
* @return Inlier ratio (0-1). Higher = better fit.
*/
float ComputeEllipseInlierRatio(
const SVzNLPointXYZ* points,
int pointCount,
float centerX,
float centerY,
float radius,
float tolerance = 0.3f
);
#endif // GEOMETRIC_FITTING_H