2026-04-09 23:39:51 +08:00
|
|
|
|
#ifndef BAR_INTERSECTION_PARAMS_H
|
2026-04-08 19:45:15 +08:00
|
|
|
|
#define BAR_INTERSECTION_PARAMS_H
|
|
|
|
|
|
|
|
|
|
|
|
#include "VZNL_Types.h"
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-09 23:39:51 +08:00
|
|
|
|
* @brief RANSAC 平面分割参数
|
2026-04-08 19:45:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
struct SPlaneSegmentationParams {
|
2026-04-09 23:39:51 +08:00
|
|
|
|
float distanceThreshold; // 点到平面距离阈值 (mm)
|
|
|
|
|
|
int maxIterations; // RANSAC 最大迭代次数
|
|
|
|
|
|
int minPlanePoints; // 最小平面点数
|
|
|
|
|
|
float minPlaneRatio; // 平面最小点数占比
|
|
|
|
|
|
float heightThreshold; // 高于平面的最小高度,用于过滤平面点 (mm)
|
2026-04-08 19:45:15 +08:00
|
|
|
|
|
|
|
|
|
|
SPlaneSegmentationParams()
|
|
|
|
|
|
: distanceThreshold(1.0f)
|
|
|
|
|
|
, maxIterations(500)
|
|
|
|
|
|
, minPlanePoints(1000)
|
|
|
|
|
|
, minPlaneRatio(0.05f)
|
|
|
|
|
|
, heightThreshold(10.0f)
|
|
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-09 23:39:51 +08:00
|
|
|
|
* @brief 区域生长参数
|
2026-04-08 19:45:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
struct SGrowthParams {
|
2026-04-09 23:39:51 +08:00
|
|
|
|
float thresholdX; // 跨行合并阈值:相邻行 segment 质心 x 的最大允许差 (mm)
|
|
|
|
|
|
float thresholdY; // 行内分段阈值:同行相邻点 y 的最大允许差 (mm)
|
|
|
|
|
|
float thresholdZ; // 行内分段阈值:同行相邻点 z 的最大允许差 (mm)
|
|
|
|
|
|
int minClusterSize; // 最小簇点数
|
2026-04-10 00:18:05 +08:00
|
|
|
|
float angleSearchDistance;
|
|
|
|
|
|
int residualSmoothWindow;
|
2026-04-08 19:45:15 +08:00
|
|
|
|
float maxAxisDeviationFromXYDeg; // Max allowed axis deviation from the XY plane (deg)
|
|
|
|
|
|
float maxPerpendicularDeviationDeg; // Max deviation from 90 deg for centroid-connection test
|
|
|
|
|
|
int minContinuousValidPointCount; // Min consecutive valid points kept on each laser line after plane filtering; <=1 disables
|
|
|
|
|
|
float maxContinuousPointZTolerance; // Max z difference between adjacent points inside one valid run (mm)
|
2026-04-11 23:24:16 +08:00
|
|
|
|
float minBarDiameter;
|
|
|
|
|
|
float maxBarDiameter;
|
2026-04-08 19:45:15 +08:00
|
|
|
|
|
|
|
|
|
|
SGrowthParams()
|
|
|
|
|
|
: thresholdX(5.0f)
|
|
|
|
|
|
, thresholdY(5.0f)
|
|
|
|
|
|
, thresholdZ(5.0f)
|
|
|
|
|
|
, minClusterSize(20)
|
2026-04-10 00:18:05 +08:00
|
|
|
|
, angleSearchDistance(2.f)
|
|
|
|
|
|
, residualSmoothWindow(5)
|
2026-04-08 19:45:15 +08:00
|
|
|
|
, maxAxisDeviationFromXYDeg(50.0f)
|
|
|
|
|
|
, maxPerpendicularDeviationDeg(50.0f)
|
|
|
|
|
|
, minContinuousValidPointCount(0)
|
|
|
|
|
|
, maxContinuousPointZTolerance(5.0f)
|
2026-04-11 23:24:16 +08:00
|
|
|
|
, minBarDiameter(10.0f)
|
|
|
|
|
|
, maxBarDiameter(30.0f)
|
2026-04-08 19:45:15 +08:00
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-09 23:39:51 +08:00
|
|
|
|
* @brief 生长结果:一个连通簇
|
2026-04-08 19:45:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
struct SGrowthCluster {
|
2026-04-09 23:39:51 +08:00
|
|
|
|
std::vector<int> pointIndices; // 簇内点在原始 rows*cols 网格中的线性索引
|
|
|
|
|
|
SVzNL3DPointF centroid; // 簇质心
|
|
|
|
|
|
SVzNL3DPointF minBound; // 包围盒最小角
|
|
|
|
|
|
SVzNL3DPointF maxBound; // 包围盒最大角
|
2026-04-08 19:45:15 +08:00
|
|
|
|
int pointCount;
|
|
|
|
|
|
|
|
|
|
|
|
SGrowthCluster()
|
|
|
|
|
|
: centroid(), minBound(), maxBound(), pointCount(0)
|
|
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-09 23:39:51 +08:00
|
|
|
|
* @brief 检测结果
|
2026-04-08 19:45:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
struct SBarIntersectionResult {
|
2026-04-09 23:39:51 +08:00
|
|
|
|
// 平面信息
|
|
|
|
|
|
SVzNL3DPointF planeNormal; // 平面法向量
|
|
|
|
|
|
float planeD; // 平面方程 ax+by+cz+d=0 中的 d
|
2026-04-08 19:45:15 +08:00
|
|
|
|
|
2026-04-09 23:39:51 +08:00
|
|
|
|
// 簇(原始坐标系)
|
2026-04-08 19:45:15 +08:00
|
|
|
|
int clusterCount;
|
|
|
|
|
|
SGrowthCluster* clusters;
|
|
|
|
|
|
|
2026-04-09 23:39:51 +08:00
|
|
|
|
// 最优簇索引(-1表示无有效簇)
|
2026-04-08 19:45:15 +08:00
|
|
|
|
int bestClusterIndex;
|
|
|
|
|
|
|
2026-04-09 23:39:51 +08:00
|
|
|
|
// 最优簇的过滤后点云(对齐坐标系,用于可视化)
|
2026-04-08 19:45:15 +08:00
|
|
|
|
std::vector<SVzNLPointXYZ> bestClusterPoints;
|
|
|
|
|
|
|
|
|
|
|
|
SBarIntersectionResult()
|
|
|
|
|
|
: planeNormal(), planeD(0.0f)
|
|
|
|
|
|
, clusterCount(0), clusters(nullptr)
|
|
|
|
|
|
, bestClusterIndex(-1)
|
|
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-09 23:39:51 +08:00
|
|
|
|
* @brief 释放检测结果内存
|
2026-04-08 19:45:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
inline void FreeBarIntersectionResult(SBarIntersectionResult* result) {
|
|
|
|
|
|
if (result) {
|
|
|
|
|
|
if (result->clusters) { delete[] result->clusters; result->clusters = nullptr; }
|
|
|
|
|
|
result->clusterCount = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif // BAR_INTERSECTION_PARAMS_H
|