数据类型转换

This commit is contained in:
YangSn 2026-07-31 10:47:28 +08:00
parent 517889ff90
commit 47fef439e3
4 changed files with 659 additions and 504 deletions

View File

@ -67,6 +67,10 @@ public:
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
size_t* validPointCount = nullptr);
// 转换统一格式数据为std::vector<std::vector<SVzNLPositionD>>格式
int ConvertToSVzNLPositionD(const std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& unifiedData,
std::vector<std::vector<SVzNLPositionD>>& scanLines);
// 从文件加载Poly折线数据带颜色
// polyLines: 每条折线的点坐标列表polyLines[i] 是第i条折线的所有点含RGB颜色
int LoadPolySegments(const std::string& fileName,
@ -78,6 +82,7 @@ public:
private:
// 读取XYZ格式的激光数据
int _ParseLaserScanPoint(const std::string& data, SVzNL3DPosition& sData, SVzNL2DPosition& s2DData);
int _ParseLaserScanPoint(const std::string& data, SVzNL3DPosition& sData, SVzNL2DPositionF& s2DData);
// 读取RGBD格式的激光数据 - 新增RGBD支持
int _ParseLaserScanPoint(const std::string& data, SVzNLPointXYZRGBA& sData, SVzNL2DLRPoint& s2DData);

View File

@ -285,10 +285,15 @@ int LaserDataLoader::LoadLaserScanData(const std::string& fileName,
SVzNL2DLRPoint* p2DPoints = static_cast<SVzNL2DLRPoint*>(sLaserData.p2DPoint);
_ParseLaserScanPoint(line, pRGBAPoints[nLaserPointIdx], p2DPoints[nLaserPointIdx]);
nLaserPointIdx++;
} else {
} else if (eDataType == keResultDataType_Position) {
SVzNL3DPosition* p3DPoints = static_cast<SVzNL3DPosition*>(sLaserData.p3DPoint);
SVzNL2DPosition* p2DPoints = static_cast<SVzNL2DPosition*>(sLaserData.p2DPoint);
_ParseLaserScanPoint(line, p3DPoints[nLaserPointIdx], p2DPoints[nLaserPointIdx]);
result = _ParseLaserScanPoint(line, p3DPoints[nLaserPointIdx], p2DPoints[nLaserPointIdx]);
if (result != SUCCESS) {
m_lastError = "Invalid XYZUV point line: " + line;
LOG_ERROR("%s\n", m_lastError.c_str());
return result;
}
p3DPoints[nLaserPointIdx].nPointIdx = nLaserPointIdx;
nLaserPointIdx++;
}
@ -530,6 +535,26 @@ int LaserDataLoader::SaveLaserScanData(const std::string& fileName,
}
sw.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
}
} else if (dataType == keResultDataType_PositionF && lineData.p3DPoint) {
const SVzNL3DPosition* points = static_cast<const SVzNL3DPosition*>(lineData.p3DPoint);
const SVzNL2DPositionF* points2D = static_cast<const SVzNL2DPositionF*>(lineData.p2DPoint);
constexpr int BATCH = 256;
constexpr int PER_POINT = 160;
for (int base = 0; base < lineData.nPointCount; base += BATCH) {
int end = (base + BATCH < lineData.nPointCount) ? (base + BATCH) : lineData.nPointCount;
std::string buffer;
buffer.reserve(BATCH * PER_POINT);
for (int i = base; i < end; ++i) {
AppendFormattedLine(buffer,
"{ %.9f, %.9f, %.9f } - { %.6f, %.6f } - { %.6f, %.6f }\n",
points[i].pt3D.x, points[i].pt3D.y, points[i].pt3D.z,
points2D ? points2D[i].ptLeft2D.x : 0.0f,
points2D ? points2D[i].ptLeft2D.y : 0.0f,
points2D ? points2D[i].ptRight2D.x : 0.0f,
points2D ? points2D[i].ptRight2D.y : 0.0f);
}
sw.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
}
} else if (dataType == keResultDataType_PointXYZI && lineData.p3DPoint) {
// LiDAR 点云snprintf 批量写入,每 256 点 flush
// 坐标 mm 范围可达 ±200000 → "%.6f" 最长 14 字符 → 整行 ≤73 字符
@ -820,7 +845,7 @@ void LaserDataLoader::FreeLaserScanData(std::vector<std::pair<EVzResultDataType,
delete[] static_cast<SVzNL3DPosition*>(lineData.p3DPoint);
break;
case keResultDataType_PositionF:
delete[] static_cast<SVzNL3DPositionF*>(lineData.p3DPoint);
delete[] static_cast<SVzNL3DPosition*>(lineData.p3DPoint);
break;
case keResultDataType_PointF:
delete[] static_cast<SVzNL3DPointF*>(lineData.p3DPoint);
@ -915,6 +940,22 @@ int LaserDataLoader::ConvertToSVzNL3DPosition(const std::vector<std::pair<EVzRes
}
}
scanLines.push_back(scanLine);
} else if (dataType == keResultDataType_PositionF && lineData.p3DPoint) {
std::vector<SVzNL3DPosition> scanLine;
scanLine.reserve(lineData.nPointCount);
const SVzNL3DPosition* points = static_cast<const SVzNL3DPosition*>(lineData.p3DPoint);
for (int i = 0; i < lineData.nPointCount; i++) {
scanLine.push_back(points[i]);
if (std::fabs(points[i].pt3D.x) > EPSILON &&
std::fabs(points[i].pt3D.y) > EPSILON &&
std::fabs(points[i].pt3D.z) > EPSILON) {
validCount++;
}
}
scanLines.push_back(scanLine);
}
}
@ -928,6 +969,82 @@ int LaserDataLoader::ConvertToSVzNL3DPosition(const std::vector<std::pair<EVzRes
return SUCCESS;
}
int LaserDataLoader::ConvertToSVzNLPositionD(
const std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& unifiedData,
std::vector<std::vector<SVzNLPositionD>>& scanLines)
{
LOG_DEBUG("Converting unified data to SVzNLPositionD scan lines format\n");
scanLines.clear();
for (const auto& linePair : unifiedData) {
if (linePair.first != keResultDataType_Position &&
linePair.first != keResultDataType_PositionF) {
continue;
}
const SVzLaserLineData& lineData = linePair.second;
if (lineData.nPointCount < 0) {
continue;
}
if (lineData.nPointCount > 0 && (!lineData.p3DPoint || !lineData.p2DPoint)) {
m_lastError = "Missing 3D or 2D point buffer in Position laser data";
LOG_ERROR("%s, pointCount=%d, p3D=%p, p2D=%p\n",
m_lastError.c_str(),
lineData.nPointCount,
lineData.p3DPoint,
lineData.p2DPoint);
continue;
}
std::vector<SVzNLPositionD> scanLine;
scanLine.reserve(static_cast<size_t>(lineData.nPointCount));
if (linePair.first == keResultDataType_Position) {
const SVzNL3DPosition* points3D = static_cast<const SVzNL3DPosition*>(lineData.p3DPoint);
const SVzNL2DPosition* points2D = static_cast<const SVzNL2DPosition*>(lineData.p2DPoint);
for (int i = 0; i < lineData.nPointCount; ++i) {
SVzNLPositionD point;
std::memset(&point, 0, sizeof(point));
point.nPointIdx = points3D[i].nPointIdx;
point.pt3D = points3D[i].pt3D;
point.ptLeft2D.x = points2D[i].ptLeft2D.x;
point.ptLeft2D.y = points2D[i].ptLeft2D.y;
point.ptRight2D.x = points2D[i].ptRight2D.x;
point.ptRight2D.y = points2D[i].ptRight2D.y;
scanLine.push_back(point);
}
} else {
const SVzNL3DPosition* points3D = static_cast<const SVzNL3DPosition*>(lineData.p3DPoint);
const SVzNL2DPositionF* points2D = static_cast<const SVzNL2DPositionF*>(lineData.p2DPoint);
for (int i = 0; i < lineData.nPointCount; ++i) {
SVzNLPositionD point;
std::memset(&point, 0, sizeof(point));
point.nPointIdx = points3D[i].nPointIdx;
point.pt3D = points3D[i].pt3D;
point.ptLeft2D.x = points2D[i].ptLeft2D.x;
point.ptLeft2D.y = points2D[i].ptLeft2D.y;
point.ptRight2D.x = points2D[i].ptRight2D.x;
point.ptRight2D.y = points2D[i].ptRight2D.y;
scanLine.push_back(point);
}
}
if (!scanLine.empty()) {
scanLines.push_back(scanLine);
}
}
if (scanLines.empty()) {
m_lastError = "No Position laser data to convert";
LOG_ERROR("%s\n", m_lastError.c_str());
return ERR_CODE(DATA_ERR_INVALID);
}
LOG_DEBUG("Converted %zu lines to SVzNLPositionD scan lines format\n", scanLines.size());
return SUCCESS;
}
// 转换统一格式数据为SVzNL3DLaserLine格式
int LaserDataLoader::ConvertToSVzNL3DLaserLine(const std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& unifiedData,
std::vector<SVzNL3DLaserLine>& xyzData)
@ -938,8 +1055,9 @@ int LaserDataLoader::ConvertToSVzNL3DLaserLine(const std::vector<std::pair<EVzRe
EVzResultDataType dataType = linePair.first;
const SVzLaserLineData& lineData = linePair.second;
// 只处理Position类型的数据
if (dataType == keResultDataType_Position && lineData.p3DPoint) {
// PositionF 的 3D buffer 也是 SVzNL3DPosition仅 2D UV 为浮点。
if ((dataType == keResultDataType_Position ||
dataType == keResultDataType_PositionF) && lineData.p3DPoint) {
SVzNL3DLaserLine xyzLine;
xyzLine.nTimeStamp = lineData.llTimeStamp;
xyzLine.nPositionCnt = lineData.nPointCount;
@ -1043,10 +1161,36 @@ void LaserDataLoader::FreeConvertedData(std::vector<SVzNLXYZRGBDLaserLine>& rgbd
int LaserDataLoader::_ParseLaserScanPoint(const std::string& data, SVzNL3DPosition& sData, SVzNL2DPosition& s2DData)
{
float X, Y, Z;
float leftX, leftY;
float rightX, rightY;
sscanf(data.c_str(), "{%f,%f,%f}-{%f,%f}-{%f,%f}", &X, &Y, &Z, &leftX, &leftY, &rightX, &rightY);
float X = 0.0f, Y = 0.0f, Z = 0.0f;
float leftX = 0.0f, leftY = 0.0f;
float rightX = 0.0f, rightY = 0.0f;
const int parsed = sscanf(data.c_str(),
" { %f , %f , %f } - { %f , %f } - { %f , %f }",
&X, &Y, &Z, &leftX, &leftY, &rightX, &rightY);
if (parsed != 7) {
return ERR_CODE(FILE_ERR_FORMAT);
}
sData.pt3D.x = X;
sData.pt3D.y = Y;
sData.pt3D.z = Z;
s2DData.ptLeft2D.x = leftX;
s2DData.ptLeft2D.y = leftY;
s2DData.ptRight2D.x = rightX;
s2DData.ptRight2D.y = rightY;
return SUCCESS;
}
int LaserDataLoader::_ParseLaserScanPoint(const std::string& data, SVzNL3DPosition& sData, SVzNL2DPositionF& s2DData)
{
double X = 0.0, Y = 0.0, Z = 0.0;
float leftX = 0.0f, leftY = 0.0f;
float rightX = 0.0f, rightY = 0.0f;
const int parsed = sscanf(data.c_str(),
" { %lf , %lf , %lf } - { %f , %f } - { %f , %f }",
&X, &Y, &Z, &leftX, &leftY, &rightX, &rightY);
if (parsed != 7) {
return ERR_CODE(FILE_ERR_FORMAT);
}
sData.pt3D.x = X;
sData.pt3D.y = Y;
sData.pt3D.z = Z;
@ -1151,7 +1295,7 @@ int LaserDataLoader::_GetLaserType(const std::string& fileName, EVzResultDataTyp
eDataType = keResultDataType_PointXYZRGBA;
bFind = true;
} else if (commaCount >= 2) {
// XYZ格式: {x,y,z}-{lx,ly}-{rx,ry}
// XYZUV文本格式: {x,y,z}-{lx,ly}-{rx,ry}
eDataType = keResultDataType_Position;
bFind = true;
}

View File

@ -1188,7 +1188,8 @@ int PointCloudImageUtils::GenerateDepthImage(
if (!lineData.p3DPoint || lineData.nPointCount <= 0) continue;
// 根据数据类型处理点云数据
if (dataType == keResultDataType_Position) {
if (dataType == keResultDataType_Position ||
dataType == keResultDataType_PositionF) {
SVzNL3DPosition* positions = static_cast<SVzNL3DPosition*>(lineData.p3DPoint);
for (int i = 0; i < lineData.nPointCount; i++) {
const SVzNL3DPosition& point = positions[i];
@ -1250,7 +1251,8 @@ int PointCloudImageUtils::GenerateDepthImage(
if (!lineData.p3DPoint || lineData.nPointCount <= 0) continue;
if (dataType == keResultDataType_Position) {
if (dataType == keResultDataType_Position ||
dataType == keResultDataType_PositionF) {
SVzNL3DPosition* positions = static_cast<SVzNL3DPosition*>(lineData.p3DPoint);
for (int i = 0; i < lineData.nPointCount; i++) {
const SVzNL3DPosition& point = positions[i];

View File

@ -11,11 +11,15 @@ CloudView.file = CloudView/CloudView.pro
# 添加子项目
SUBDIRS += \
VrCommon \
VrUtils \
CloudUtils \
DataUtils
VrUtils
win32-msvc {
!equals(TARGET_APP, "ParkingSpaceGuideView") {
SUBDIRS += \
CloudUtils \
DataUtils
}
win32-msvc:!equals(TARGET_APP, "ParkingSpaceGuideView") {
SUBDIRS += \
CloudView3D \
CloudView