This commit is contained in:
cool609 2026-03-29 15:58:39 +08:00
parent eddc403142
commit b873290801
2 changed files with 95 additions and 73 deletions

View File

@ -2,7 +2,9 @@
#include <algorithm>
#include <cmath>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
namespace {
@ -208,6 +210,19 @@ int DetectMultipleHoles(
continue;
}
/*if (debugCallbacks && debugCallbacks->clusterOutputDir) {
std::string path = std::string(debugCallbacks->clusterOutputDir)
+ "/cluster_" + std::to_string(i) + ".csv";
std::ofstream ofs(path);
if (ofs.is_open()) {
ofs << "row,col,x,y,z\n";
for (const auto& bp : clusterPoints) {
ofs << bp.row << "," << bp.col << ","
<< bp.point.x << "," << bp.point.y << "," << bp.point.z << "\n";
}
}
}*/
SHoleResult hole;
ret = hole_detection::internal::FitHoleFromExtremePoints(
points,

View File

@ -31,51 +31,51 @@ struct SHoleBoundaryPoint {
: point(p), row(r), col(c) {}
};
/**
* @brief Per-point signed angle state along one scanned line
*/
enum ELineAngleTrend {
keLineAngleTrend_Invalid = 0,
keLineAngleTrend_Flat = 1,
keLineAngleTrend_PositiveJump = 2,
keLineAngleTrend_NegativeJump = 3
};
/**
* @brief Angle profile sample for one valid point on a scanned line
*/
struct SLineAngleSample {
SVzNLPointXYZ point; // Current point
int row; // Grid row
int col; // Grid column
int linePos; // Position inside the scanned line
float signedAngleDeg; // Signed turning angle in degrees
float beforeMeanZ; // Mean Z of points found within A before current point
float afterMeanZ; // Mean Z of points found within A after current point
float beforeCoord; // Projected coord of the furthest point before current point
float afterCoord; // Projected coord of the furthest point after current point
ELineAngleTrend trend; // Flat / positive jump / negative jump
unsigned char hasAngle; // 1 if both sides have enough points to form an angle
SLineAngleSample()
: point()
, row(-1)
, col(-1)
, linePos(-1)
, signedAngleDeg(0.0f)
, beforeMeanZ(0.0f)
, afterMeanZ(0.0f)
, beforeCoord(0.0f)
, afterCoord(0.0f)
, trend(keLineAngleTrend_Invalid)
, hasAngle(0U)
{}
};
/**
* @brief Cluster information for debug callbacks
*/
struct SClusterInfo {
/**
* @brief Per-point signed angle state along one scanned line
*/
enum ELineAngleTrend {
keLineAngleTrend_Invalid = 0,
keLineAngleTrend_Flat = 1,
keLineAngleTrend_PositiveJump = 2,
keLineAngleTrend_NegativeJump = 3
};
/**
* @brief Angle profile sample for one valid point on a scanned line
*/
struct SLineAngleSample {
SVzNLPointXYZ point; // Current point
int row; // Grid row
int col; // Grid column
int linePos; // Position inside the scanned line
float signedAngleDeg; // Signed turning angle in degrees
float beforeMeanZ; // Mean Z of points found within A before current point
float afterMeanZ; // Mean Z of points found within A after current point
float beforeCoord; // Projected coord of the furthest point before current point
float afterCoord; // Projected coord of the furthest point after current point
ELineAngleTrend trend; // Flat / positive jump / negative jump
unsigned char hasAngle; // 1 if both sides have enough points to form an angle
SLineAngleSample()
: point()
, row(-1)
, col(-1)
, linePos(-1)
, signedAngleDeg(0.0f)
, beforeMeanZ(0.0f)
, afterMeanZ(0.0f)
, beforeCoord(0.0f)
, afterCoord(0.0f)
, trend(keLineAngleTrend_Invalid)
, hasAngle(0U)
{}
};
/**
* @brief Cluster information for debug callbacks
*/
struct SClusterInfo {
const SHoleBoundaryPoint* points; // Points in this cluster
int count; // Number of points in this cluster
};
@ -123,34 +123,41 @@ struct SHoleDetectionDebugCallbacks {
*/
void (*onHoleFitted)(const SHoleResult* hole, int holeIndex, void* userData);
/**
* @brief Called when segment endpoint pairs are detected
* @param segmentPairs Array of segment pairs (each pair has start and end points)
* @param count Number of segment pairs
* @param userData User-provided context pointer
*/
void (*onSegmentPairsDetected)(const SSegmentPair* segmentPairs, int count, void* userData);
/**
* @brief Called when one scanned line's signed angle profile is available
* @param samples Array of valid-point angle samples in line order
* @param count Number of samples
* @param lineType "Row" or "Column"
* @param lineIndex Row/column index
* @param userData User-provided context pointer
*/
void (*onLineAngleProfileDetected)(
const SLineAngleSample* samples,
int count,
const char* lineType,
int lineIndex,
void* userData
);
/**
* @brief User-provided context pointer, passed to all callbacks
*/
void* userData;
/**
* @brief Called when segment endpoint pairs are detected
* @param segmentPairs Array of segment pairs (each pair has start and end points)
* @param count Number of segment pairs
* @param userData User-provided context pointer
*/
void (*onSegmentPairsDetected)(const SSegmentPair* segmentPairs, int count, void* userData);
/**
* @brief Called when one scanned line's signed angle profile is available
* @param samples Array of valid-point angle samples in line order
* @param count Number of samples
* @param lineType "Row" or "Column"
* @param lineIndex Row/column index
* @param userData User-provided context pointer
*/
void (*onLineAngleProfileDetected)(
const SLineAngleSample* samples,
int count,
const char* lineType,
int lineIndex,
void* userData
);
/**
* @brief User-provided context pointer, passed to all callbacks
*/
void* userData;
/**
* @brief If non-null, each cluster's boundary points are saved as a CSV file
* in this directory before fitting. Files are named cluster_0.csv, cluster_1.csv, ...
* Fields: row,col,x,y,z
*/
const char* clusterOutputDir;
};
/**