修复崩溃,修复选点序号不对

This commit is contained in:
yiyi 2026-03-17 22:37:46 +08:00
parent d6049e7846
commit 36645c6ceb
3 changed files with 61 additions and 9 deletions

View File

@ -121,13 +121,19 @@ int LaserDataLoader::LoadLaserScanData(const std::string& fileName,
// 使用正则表达式判断是XYZ还是RGBD格式 // 使用正则表达式判断是XYZ还是RGBD格式
// XYZ格式: {x,y,z}-{leftX,leftY}-{rightX,rightY} // XYZ格式: {x,y,z}-{leftX,leftY}-{rightX,rightY}
// RGBD格式: {x,y,z,r,g,b}-{leftX,leftY}-{rightX,rightY} // RGBD格式: {x,y,z,r,g,b}-{leftX,leftY}-{rightX,rightY}
// 更精确的正则表达式,匹配完整的行格式 // 更精确的正则表达式,匹配完整的行格式
if(sLaserData.p3DPoint == nullptr || sLaserData.p2DPoint == nullptr) { if(sLaserData.p3DPoint == nullptr || sLaserData.p2DPoint == nullptr) {
LOG_ERROR("sLaserData.p3DPoint == nullptr || sLaserData.p2DPoint == nullptr \n"); LOG_ERROR("sLaserData.p3DPoint == nullptr || sLaserData.p2DPoint == nullptr \n");
return ERR_CODE(DATA_ERR_INVALID); return ERR_CODE(DATA_ERR_INVALID);
} }
// 防止数组越界:跳过超出声明点数的数据行
if (nLaserPointIdx >= sLaserData.nPointCount) {
LOG_WARN("nLaserPointIdx(%d) >= nPointCount(%d), skip\n", nLaserPointIdx, sLaserData.nPointCount);
continue;
}
if (eDataType == keResultDataType_PointXYZRGBA) { if (eDataType == keResultDataType_PointXYZRGBA) {
SVzNLPointXYZRGBA* pRGBAPoints = static_cast<SVzNLPointXYZRGBA*>(sLaserData.p3DPoint); SVzNLPointXYZRGBA* pRGBAPoints = static_cast<SVzNLPointXYZRGBA*>(sLaserData.p3DPoint);
SVzNL2DLRPoint* p2DPoints = static_cast<SVzNL2DLRPoint*>(sLaserData.p2DPoint); SVzNL2DLRPoint* p2DPoints = static_cast<SVzNL2DLRPoint*>(sLaserData.p2DPoint);

View File

@ -287,6 +287,7 @@ private:
std::vector<float> colors; std::vector<float> colors;
std::vector<int> lineIndices; // 每个点所属的线索引 std::vector<int> lineIndices; // 每个点所属的线索引
std::vector<int> originalIndices; // 每个显示点在原始点云中的索引用于计算原始index std::vector<int> originalIndices; // 每个显示点在原始点云中的索引用于计算原始index
std::vector<int> pointInLineIndices; // 每个显示点在所属线中的索引(预计算,支持不等长线)
bool hasColor; bool hasColor;
bool hasLineInfo; // 是否有线信息 bool hasLineInfo; // 是否有线信息
QString name; QString name;
@ -322,6 +323,7 @@ private:
, colors(std::move(other.colors)) , colors(std::move(other.colors))
, lineIndices(std::move(other.lineIndices)) , lineIndices(std::move(other.lineIndices))
, originalIndices(std::move(other.originalIndices)) , originalIndices(std::move(other.originalIndices))
, pointInLineIndices(std::move(other.pointInLineIndices))
, hasColor(other.hasColor) , hasColor(other.hasColor)
, hasLineInfo(other.hasLineInfo) , hasLineInfo(other.hasLineInfo)
, name(std::move(other.name)) , name(std::move(other.name))
@ -351,6 +353,7 @@ private:
colors = std::move(other.colors); colors = std::move(other.colors);
lineIndices = std::move(other.lineIndices); lineIndices = std::move(other.lineIndices);
originalIndices = std::move(other.originalIndices); originalIndices = std::move(other.originalIndices);
pointInLineIndices = std::move(other.pointInLineIndices);
hasColor = other.hasColor; hasColor = other.hasColor;
hasLineInfo = other.hasLineInfo; hasLineInfo = other.hasLineInfo;
name = std::move(other.name); name = std::move(other.name);

View File

@ -255,13 +255,27 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZ& cloud, const QString
data.pointsPerLine = 0; data.pointsPerLine = 0;
const float EPSILON = 1e-6f; const float EPSILON = 1e-6f;
int prevLineIdx = -1;
int ptInLineCounter = 0;
for (size_t i = 0; i < cloud.points.size(); ++i) { for (size_t i = 0; i < cloud.points.size(); ++i) {
// 跟踪线内索引(对所有点递增,包括被过滤的零点)
int lineIdx = -1;
if (data.hasLineInfo && i < cloud.lineIndices.size()) {
lineIdx = cloud.lineIndices[i];
}
if (lineIdx != prevLineIdx) {
ptInLineCounter = 0;
prevLineIdx = lineIdx;
}
const auto& pt = cloud.points[i]; const auto& pt = cloud.points[i];
if (!std::isfinite(pt.x) || !std::isfinite(pt.y) || !std::isfinite(pt.z)) { if (!std::isfinite(pt.x) || !std::isfinite(pt.y) || !std::isfinite(pt.z)) {
ptInLineCounter++;
continue; continue;
} }
// 显示时过滤 (0,0,0) 点 // 显示时过滤 (0,0,0) 点
if (std::fabs(pt.x) < EPSILON && std::fabs(pt.y) < EPSILON && std::fabs(pt.z) < EPSILON) { if (std::fabs(pt.x) < EPSILON && std::fabs(pt.y) < EPSILON && std::fabs(pt.z) < EPSILON) {
ptInLineCounter++;
continue; continue;
} }
data.vertices.push_back(pt.x); data.vertices.push_back(pt.x);
@ -271,14 +285,18 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZ& cloud, const QString
// 保存原始索引 // 保存原始索引
data.originalIndices.push_back(static_cast<int>(i)); data.originalIndices.push_back(static_cast<int>(i));
// 保存线内索引(点在所属线中的位置)
data.pointInLineIndices.push_back(ptInLineCounter);
// 保存线索引 // 保存线索引
if (data.hasLineInfo && i < cloud.lineIndices.size()) { if (lineIdx >= 0) {
int lineIdx = cloud.lineIndices[i];
data.lineIndices.push_back(lineIdx); data.lineIndices.push_back(lineIdx);
if (lineIdx + 1 > data.totalLines) { if (lineIdx + 1 > data.totalLines) {
data.totalLines = lineIdx + 1; data.totalLines = lineIdx + 1;
} }
} }
ptInLineCounter++;
} }
// 计算每线点数(假设网格化点云) // 计算每线点数(假设网格化点云)
@ -328,9 +346,31 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QStr
// 用于按点大小分组的临时 map // 用于按点大小分组的临时 map
std::map<float, std::vector<size_t>> sizeGroupMap; std::map<float, std::vector<size_t>> sizeGroupMap;
const float EPSILON = 1e-6f;
int prevLineIdx = -1;
int ptInLineCounter = 0;
for (size_t i = 0; i < cloud.points.size(); ++i) { for (size_t i = 0; i < cloud.points.size(); ++i) {
const auto& pt = cloud.points[i]; const auto& pt = cloud.points[i];
// 跟踪线内索引(对所有点递增,包括被过滤的零点)
int lineIdx = -1;
if (data.hasLineInfo && i < cloud.lineIndices.size()) {
lineIdx = cloud.lineIndices[i];
}
if (lineIdx != prevLineIdx) {
ptInLineCounter = 0;
prevLineIdx = lineIdx;
}
if (!std::isfinite(pt.x) || !std::isfinite(pt.y) || !std::isfinite(pt.z)) { if (!std::isfinite(pt.x) || !std::isfinite(pt.y) || !std::isfinite(pt.z)) {
ptInLineCounter++;
continue;
}
// 显示时过滤 (0,0,0) 点
if (std::fabs(pt.x) < EPSILON && std::fabs(pt.y) < EPSILON && std::fabs(pt.z) < EPSILON) {
ptInLineCounter++;
continue; continue;
} }
@ -347,9 +387,11 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QStr
// 保存原始索引 // 保存原始索引
data.originalIndices.push_back(static_cast<int>(i)); data.originalIndices.push_back(static_cast<int>(i));
// 保存线内索引(点在所属线中的位置)
data.pointInLineIndices.push_back(ptInLineCounter);
// 保存线索引 // 保存线索引
if (data.hasLineInfo && i < cloud.lineIndices.size()) { if (lineIdx >= 0) {
int lineIdx = cloud.lineIndices[i];
data.lineIndices.push_back(lineIdx); data.lineIndices.push_back(lineIdx);
if (lineIdx + 1 > data.totalLines) { if (lineIdx + 1 > data.totalLines) {
data.totalLines = lineIdx + 1; data.totalLines = lineIdx + 1;
@ -360,6 +402,8 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QStr
if (pt.pointSize > 1.0f) { if (pt.pointSize > 1.0f) {
sizeGroupMap[pt.pointSize].push_back(pointIndex); sizeGroupMap[pt.pointSize].push_back(pointIndex);
} }
ptInLineCounter++;
} }
// 构建自定义点大小分组 // 构建自定义点大小分组
@ -843,10 +887,9 @@ SelectedPointInfo PointCloudGLWidget::pickPoint(int screenX, int screenY)
// 计算点在线中的原始索引 // 计算点在线中的原始索引
if (bestLineIndex >= 0 && bestCloudIndex >= 0) { if (bestLineIndex >= 0 && bestCloudIndex >= 0) {
const auto& cloudData = m_pointClouds[bestCloudIndex]; const auto& cloudData = m_pointClouds[bestCloudIndex];
// 使用原始索引计算:原始索引 % 每线点数 // 使用预计算的线内索引(支持不等长线)
if (bestIndex < cloudData.originalIndices.size() && cloudData.pointsPerLine > 0) { if (bestIndex < cloudData.pointInLineIndices.size()) {
int originalIdx = cloudData.originalIndices[bestIndex]; result.pointIndexInLine = cloudData.pointInLineIndices[bestIndex];
result.pointIndexInLine = originalIdx % cloudData.pointsPerLine;
} }
} }