我目前正在编写代码以读取.las(激光雷达点数据)文件。读完文件后,我创建了一个指针来遍历所有点。但是,这给了我bad_alloc错误。
我唯一能想到的是,标头的大小与las文件标头指定的大小不同。我仔细检查了标头,但我认为没有发现任何错误。
Header和PointRecord3中的所有标头变量分别来自此documentation,第3页和第10页。
更新:读入的点数为402,673,112。但是,当我在其他LIDAR软件中打开它进行仔细检查时,点数仅为5,104,152。我相信这样做的原因是因为我在用C ++打开云之前先在其他软件中过滤了云,因此减少了点数。
这是我的代码:
#ifndef POINTCLOUD_H
#define POINTCLOUD_H
#pragma once
#include <string>
class PointCloud
{
public:
PointCloud(const std::string &path);
private:
struct __attribute__((packed)) Header {
char magic[4];
uint16_t fileourceID;
uint16_t globalEncoding;
uint32_t guiData1;
uint16_t guiData2;
uint16_t guiData3;
uint8_t guiData[8];
uint8_t versionMaj, versionMin;
char systemIdentifer[32];
char genSoftware[32];
uint16_t creationDay, creationYear;
uint16_t headerSize;
uint32_t pointDataOffset;
uint32_t numVarLenRecords;
uint8_t pointDataRecordFormat;
uint16_t pointDataRecordLen;
uint32_t numberOfPoints;
uint32_t numPointsByReturn[5];
double scaleX, scaleY, scaleZ;
double offX, offY, offZ;
double minX, minY, minZ;
double maxX, maxY, maxZ;
};
struct __attribute__((packed)) PointRecord3 {
uint32_t X, Y, Z;
uint16_t intensity;
uint8_t flags;
uint8_t classification;
uint8_t scanAngleRank;
uint8_t userData;
uint16_t pointSourceID;
double gpsTime;
uint16_t red;
uint16_t green;
uint16_t blue;
};
#include "PointCloud.h"
#include <fstream>
#include <iostream>
#include <string>
#include <assert.h>
using namespace std;
PointCloud::PointCloud(const string &path)
{
read(path);
}
void PointCloud::read(const string &path) {
ifstream in(path.c_str(), ios::binary );
if(in.is_open()){
Header header;
in.read((char *)&header, sizeof(header));
assert(header.versionMaj == 1 && header.versionMin == 2);
cout << "headerSize " << header.headerSize << " == " << sizeof(header) << " size of header struct" <<endl;
cout << "FILE TYPE: LAS " << (int)header.versionMaj << "." << (int)header.versionMin << endl;
cout << "POINT DATA OFFSET: " << (int)header.pointDataOffset <<endl;
cout << "POINT DATA RECORD FORMAT: " << (int)header.pointDataRecordFormat <<endl;
cout << "NUMBER OF POINTS: " << (int)header.numberOfPoints << endl;
PointRecord3 *points = new PointRecord3[header.numberOfPoints];
in.seekg(header.pointDataOffset);
for(uint32_t i = 0; i < header.numberOfPoints; i++) {
in.read((char *) (points + i), sizeof(*points));
}
if(in.good()) {
throw runtime_error("error");
}
delete points;
} else {
cout << "file not opened" << endl;
}
}
任何帮助将不胜感激!
这也是LAS文件标头的输出:
file signature: 'LASF'
file source ID: 0
global_encoding: 0
project ID GUID data 1-4: 00000000-0000-0000-0000-000000000000
version major.minor: 1.2
system identifier: 'EXPORT'
generating software: 'RiSCAN_PRO'
file creation day/year: 317/2018
header size: 227
offset to point data: 313
number var. length records: 1
point data format: 3
point data record length: 34
number of point records: 5104152
number of points by return: 5104152 0 0 0 0
scale factor x y z: 0.00025 0.00025 0.00025
offset x y z: 267805 3197054 13
min x y z: 267804.25250 3196596.64500 -1.89000
max x y z: 268760.27000 3197586.23000 23.33000
variable length header record 1 of 1:
reserved 43707
user ID 'LASF_Projection'
record ID 34735
length after header 32
description 'GeoKeyDirectoryTag (mandatory)'
GeoKeyDirectoryTag version 1.1.0 number of keys 3
key 1025 tiff_tag_location 0 count 1 value_offset 2 - GTRasterTypeGeoKey: RasterPixelIsPoint
key 1024 tiff_tag_location 0 count 1 value_offset 3 - GTModelTypeGeoKey: ModelTypeGeocentric
key 2048 tiff_tag_location 0 count 1 value_offset 4326 - GeographicTypeGeoKey: GCS_WGS_84
reporting minimum and maximum for all LAS point record entries ...
X -2989 3821075
Y -1829412 2128911
Z -59559 41318
intensity 32767 32768
return_number 1 1
number_of_returns 1 1
edge_of_flight_line 0 0
scan_direction_flag 1 1
classification 0 0
scan_angle_rank 0 0
user_data 0 0
point_source_ID 0 0
gps_time 0.000000 0.000000
Color R 0 0
G 0 0
B 0 0
number of first returns: 5104152
number of intermediate returns: 0
number of last returns: 5104152
number of single returns: 5104152
overview over number of returns of given pulse: 5104152 0 0 0 0 0 0
histogram of classification of points:
5104152 never classified (0)
答案 0 :(得分:0)
我知道了。因此发生的事情是C ++添加了一些额外的字节,这导致我的标头结构比实际文件标头大5个字节。我通过添加#pragma pack(push,1)来解决此问题。
#ifndef POINTCLOUD_H
#define POINTCLOUD_H
#pragma pack (push, 1)
#include <string>
struct float3
{
float x, y, z;
};
class PointCloud
{
public:
PointCloud(const std::string &path);
private:
struct __attribute__((packed)) Header
{
char fileSig[4];
uint16_t fileourceID;
uint16_t globalEncoding;
uint32_t guiData1;
uint16_t guiData2;
uint16_t guiData3;
uint8_t guiData[8];
uint8_t versionMaj, versionMin;
char systemIdentifer[32];
char genSoftware[32];
uint16_t creationDay, creationYear;
uint16_t headerSize;
uint32_t pointDataOffset;
uint32_t numVarLenRecords;
uint8_t pointDataRecordFormat;
uint16_t pointDataRecordLen;
uint32_t numberOfPoints;
uint32_t numPointsByReturn[5];
double scaleX, scaleY, scaleZ;
double offX, offY, offZ;
double minX, minY, minZ;
double maxX, maxY, maxZ;
};
struct __attribute__((packed)) PointRecord3
{
uint32_t X, Y, Z;
uint16_t intensity;
uint8_t flags;
uint8_t classification;
uint8_t scanAngleRank;
uint8_t userData;
uint16_t pointSourceID;
double gpsTime;
uint16_t red;
uint16_t green;
uint16_t blue;
};
void read(const std::string &path);
};
#endif // POINTCLOUD_H