|
E57 Simple API V1.0.312
Aug. 10, 2012
|
This browser-based document describes the E57 Simple API (Application Programmer Interface) version 0.52, which is a collection of functions that help a C++ programmer wrap the E57 Foundation API.
An example of a typical use of this interface would be as follows:
try
{
Create a ReaderImpl
_bstr_t bsFile = sFile; //converts Unicode to UTF-8
e57::Reader eReader( (char*) bsFile);
///////////////////////////////////////////////////////////// ACCESSING ROOT DATA
Read the root
e57::E57Root rootHeader; eReader.GetE57Root( rootHeader);
Access all the root information like
char* fileGuid = rootHeader.guid.c_str();
double fileGPSTime = rootHeader.creationDateTime;
...
///////////////////////////////////////////////////////////// ACCESSING SCAN DATA3D
Get the number of scan images available
int data3DCount = eReader.GetData3DCount();
selecting the first scan
int scanIndex = 0;
Read the scan 0 header.
e57::Data3D scanHeader; eReader.ReadData3D( scanIndex, scanHeader);
Access all the header information
_bstr_t bstrName = scanHeader.name.c_str();
_bstr_t bstrGuid = scanHeader.guid.c_str();
_bstr_t bstrDesc = scanHeader.description.c_str();
double startGPSTime = rootHeader.acquisitionStart;
double endGPSTime = rootHeader.acquisitionEnd;
Get pose information
ISI::Point translation;
translation.x(scanHeader.pose.translation.x);
translation.y(scanHeader.pose.translation.y);
translation.z(scanHeader.pose.translation.z);
ISI::Quat rotation;
rotation.w(scanHeader.pose.rotation.w);
rotation.x(scanHeader.pose.rotation.x);
rotation.y(scanHeader.pose.rotation.y);
rotation.z(scanHeader.pose.rotation.z);
Get scanner information
_bstr_t bstrSerial = scanHeader.sensorSerialNumber.c_str();
_bstr_t bstrVendor = scanHeader.sensorVendor.c_str();
_bstr_t bstrModel = scanHeader.sensorModel.c_str();
_bstr_t bstrSoftware = scanHeader.sensorSoftwareVersion.c_str();
_bstr_t bstrFirmware = scanHeader.sensorFirmwareVersion.c_str();
_bstr_t bstrHardware = scanHeader.sensorHardwareVersion.c_str();
Get environment information
double temperature = scanHeader.temperature;
double humidity = scanHeader.relativeHumidity;
double airPressure = scanHeader.atmosphericPressure;
...
/////////////////////////////////////////////////////////////// ACCESSING SCAN DATA
Get the Size of the Scan
int64_t nColumn = 0;
int64_t nRow = 0;
int64_t nPointsSize = 0; //Number of points
int64_t nGroupsSize = 0; //Number of groups
int64_t nCountSize = 0; //Number of points per group
bool bColumnIndex = false; //indicates that idElementName is "columnIndex"
eReader.GetData3DSizes( scanIndex, nRow, nColumn, nPointsSize, nGroupsSize, nCountSize, bColumnIndex);
int64_t nSize = nRow;
if(nSize == 0) nSize = 1024; // choose a chunk size
Setup buffers
int8_t * isInvalidData = NULL;
if(scanHeader.pointFields.cartesianInvalidStateField)
isInvalidData = new int8_t[nSize];
Setup Points Buffers
double * xData = NULL;
if(scanHeader.pointFields.cartesianXField)
xData = new double[nSize];
double * yData = NULL;
if(scanHeader.pointFields.cartesianYField)
yData = new double[nSize];
double * zData = NULL;
if(scanHeader.pointFields.cartesianZField)
zData = new double[nSize];
Setup intensity buffers if present
double * intData = NULL;
bool bIntensity = false;
double intRange = 0;
double intOffset = 0;
if(scanHeader.pointFields.intensityField)
{
bIntensity = true;
intData = new double[nSize];
intRange = scanHeader.intensityLimits.intensityMaximum - scanHeader.intensityLimits.intensityMinimum;
intOffset = scanHeader.intensityLimits.intensityMinimum;
}
Setup color buffers if present
uint16_t * redData = NULL;
uint16_t * greenData = NULL;
uint16_t * blueData = NULL;
bool bColor = false;
int32_t colorRedRange = 1;
int32_t colorRedOffset = 0;
int32_t colorGreenRange = 1;
int32_t colorGreenOffset = 0;
int32_t colorBlueRange = 1;
int32_t colorBlueOffset = 0;
if(header.pointFields.colorRedField)
{
bColor = true;
redData = new uint16_t[nSize];
greenData = new uint16_t[nSize];
blueData = new uint16_t[nSize];
colorRedRange = header.colorLimits.colorRedMaximum - header.colorLimits.colorRedMinimum;
colorRedOffset = header.colorLimits.colorRedMinimum;
colorGreenRange = header.colorLimits.colorGreenMaximum - header.colorLimits.colorGreenMinimum;
colorGreenOffset = header.colorLimits.colorGreenMinimum;
colorBlueRange = header.colorLimits.colorBlueMaximum - header.colorLimits.colorBlueMinimum;
colorBlueOffset = header.colorLimits.colorBlueMinimum;
}
Setup the GroupByLine buffers information
int64_t * idElementValue = NULL;
int64_t * startPointIndex = NULL;
int64_t * pointCount = NULL;
if(nGroupsSize > 0)
{
idElementValue = new int64_t[nGroupsSize];
startPointIndex = new int64_t[nGroupsSize];
pointCount = new int64_t[nGroupsSize];
if(!eReader.ReadData3DGroupsData(scanIndex, nGroupsSize, idElementValue,
startPointIndex, pointCount))
nGroupsSize = 0;
}
Setup row/column index information
int32_t * rowIndex = NULL;
int32_t * columnIndex = NULL;
if(scanHeader.pointFields.rowIndexField)
rowIndex = new int32_t[nSize];
if(scanHeader.pointFields.columnIndexField)
columnIndex = new int32_t[nRow];
Get dataReader object
e57::CompressedVectorReader dataReader = eReader.SetUpData3DPointsData(
scanIndex, //!< data block index given by the NewData3D
nRow, //!< size of each of the buffers given
xData, //!< pointer to a buffer with the x data
yData, //!< pointer to a buffer with the y data
zData, //!< pointer to a buffer with the z data
isInvalidData, //!< pointer to a buffer with the valid indication
intData, //!< pointer to a buffer with the lidar return intesity
NULL,
redData, //!< pointer to a buffer with the color red data
greenData, //!< pointer to a buffer with the color green data
blueData, //!< pointer to a buffer with the color blue data
NULL,
NULL,
NULL,
NULL,
rowIndex, //!< pointer to a buffer with the rowIndex
columnIndex //!< pointer to a buffer with the columnIndex
);
Read the point data
int64_t count = 0;
unsigned size = 0;
int col = 0;
int row = 0;
while(size = dataReader.read())
{
Use the data
for(long i = 0; i < size; i++)
{
if(columnIndex)
col = columnIndex[i];
else
col = 0; //point cloud case
if(rowIndex)
row = rowIndex[i];
else
row = count; //point cloud case
if(isInvalidData[i] == 0)
pScan->SetPoint(row, col, xData[i], yData[i], zData[i]);
if(bIntensity){ //Normalize intensity to 0 - 1.
double intensity = (intData[i] - intOffset)/intRange;
pScan->SetIntensity(row, col, intensity);
}
if(bColor){ //Normalize color to 0 - 255
int red = ((redData[i] - colorRedOffset) * 255)/colorRedRange;
int green = ((greenData[i] - colorGreenOffset) * 255)/colorBlueRange;
int blue = ((blueData[i] - colorBlueOffset) * 255)/colorBlueRange;
pScan->SetColor(row, col, red, green, blue);
count++;
}
}
Close and clean up
dataReader.close();
if(isInvalidData) delete isInvalidData;
if(xData) delete xData;
if(yData) delete yData;
if(zData) delete zData;
if(intData) delete intData;
if(redData) delete redData;
if(greenData) delete greenData;
if(blueData) delete blueData;
///////////////////////////////////////////////////////////////////// ACCESSING PICTURE IMAGE2D
Get the number of picture images available
int image2DCount = eReader.GetImage2DCount();
selecting the first picture image
int imageIndex = 0;
Read the picture 0 header.
e57::Image2D imageHeader; eReader.ReadImage2D( imageIndex, imageHeader);
Access all the header information
_bstr_t bstrName = imageHeader.name.c_str();
_bstr_t bstrGuid = imageHeader.guid.c_str();
_bstr_t bstrDesc = imageHeader.description.c_str();
double imageGPSTime = rootHeader.acquisitionDateTime;
Get pose information
ISI::Point translation;
translation.x(imageHeader.pose.translation.x);
translation.y(imageHeader.pose.translation.y);
translation.z(imageHeader.pose.translation.z);
ISI::Quat rotation;
rotation.w(imageHeader.pose.rotation.w);
rotation.x(imageHeader.pose.rotation.x);
rotation.y(imageHeader.pose.rotation.y);
rotation.z(imageHeader.pose.rotation.z);
Get camera information
_bstr_t bstrSerial = imageHeader.sensorSerialNumber.c_str();
_bstr_t bstrVendor = imageHeader.sensorVendor.c_str();
_bstr_t bstrModel = imageHeader.sensorModel.c_str();
...
///////////////////////////////////////////////////////////////////// ACCESSING PICTURE IMAGE
Get the Size of the Picture
e57::Image2DProjection imageProjection; //like E57_SPHERICAL
e57::Image2DType imageType; //like E57_JPEG_IMAGE
int64_t nImageWidth = 0;
int64_t nImageHeight = 0;
int64_t nImagesSize = 0; //Number of bytes in the image
e57::Image2DType imageMaskType; //like E57_PNG_IMAGE_MASK if present
e57::Image2dType imageVisualType; //like E57_JPEG_IMAGE if present
eReader.GetImage2DSizes( imageIndex, imageProjection, imageType,
nImageWidth, nImageHeight, nImagesSize, imageMaskType, imageVisualType);
Get pixel information off the sphericalRepresentation if imageProjection == E57_SPHERICAL
int32_t imageHeight = imageHeader.sphericalRepresentation.imageHeight;
int32_t imageWidth = imageHeader.sphericalRepresentation.imageWidth;
double pixelHeight = imageHeader.sphericalRepresentation.pixelHeight;
double pixelWidth = imageHeader.sphericalRepresentation.pixelWidth;
Set up buffers
void* jpegBuffer = new char[nImagesSize];
Read the picture data
eReader.ReadImage2DData(imageIndex, imageProjection, imageType, jpegBuffer, 0, nImagesSizw);
... access the picture and decode ...
Close and clean up
delete jpegBuffer;
eReaer.Close();
///////////////////////////////////////////////////////////////////// CATCH THE ERRORS
} catch(E57Exception& ex) {
ex.report(__FILE__, __LINE__, __FUNCTION__);
} catch (std::exception& ex) {
cerr << "Got an std::exception, what=" << ex.what() << endl;
} catch (...) {
cerr << "Got an unknown exception" << endl;
}
An example of a typical use of this interface would be as follows:
try
{
Create a WriterImpl
_bstr_t bsFile = sFile; //converts Unicode to UTF-8
e57::Writer eWriter( (char*) bsFile);
if(!eWriter.IsOpen()) //test for being open
return false;
///////////////////////////////////////////////////////////// SETTING UP SCAN DATA3D
e57::Data3D scanHeader;
Setup the Name and Description
scanHeader.name = (char*) bstrName;
scanHeader.description = (char*) bstrDesc;
Setup the GUID
GUID guid; //Window's GUID
pScan->GetGuid(&guid);
OLECHAR wbuffer[64];
StringFromGUID2(guid,&wbuffer[0],64);
_bstr_t bstrScanGuid = &wbuffer[0];
scanHeader.guid = (char*) bstrScanGuid;
scanHeader.acquisitionStart.SetCurrentGPSTime(); //use real time
scanHeader.acquisitionEnd.SetCurrentGPSTime();
Setup the scan size
scanHeader.indexBounds.rowMaximum = nRow - 1;
scanHeader.indexBounds.rowMinimum = 0;
scanHeader.indexBounds.columnMaximum = nColumn - 1;
scanHeader.indexBounds.columnMinimum = 0;
scanHeader.indexBounds.returnMaximum = 0;
scanHeader.indexBounds.returnMinimum = 0;
Setup GroupByLine information
scanHeader.pointGroupingSchemes.groupingByLine.groupsSize = nColumn;
scanHeader.pointGroupingSchemes.groupingByLine.pointCountSize = nRow;
scanHeader.pointGroupingSchemes.groupingByLine.idElementName = "columnIndex";
Set up total number of points
scanHeader.pointsSize = (nColumn * nRow);
Setup bounds
if(exportStatistics)
{ //because we are using scaled integers for the data, we must adjust our bounds
scanHeader.cartesianBounds.xMaximum = floor(pStat->GetMaxX()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.cartesianBounds.xMinimum = floor(pStat->GetMinX()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.cartesianBounds.yMaximum = floor(pStat->GetMaxY()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.cartesianBounds.yMinimum = floor(pStat->GetMinY()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.cartesianBounds.zMaximum = floor(pStat->GetMaxZ()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.cartesianBounds.zMinimum = floor(pStat->GetMinZ()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.sphericalBounds.rangeMaximum = floor(pStat->GetMaxRange()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.sphericalBounds.rangeMinimum = floor(pStat->GetMinRange()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
scanHeader.sphericalBounds.azimuthEnd = pStat->GetMaxAzimuth();
scanHeader.sphericalBounds.azimuthStart = pStat->GetMinAzimuth();
scanHeader.sphericalBounds.elevationMaximum = pStat->GetMaxPolar();
scanHeader.sphericalBounds.elevationMinimum = pStat->GetMinPolar();
}
Setup pose rotation and transformation
if(exportMatrix)
{
scanHeader.pose.rotation.w = rotation.w();
scanHeader.pose.rotation.x = rotation.x();
scanHeader.pose.rotation.y = rotation.y();
scanHeader.pose.rotation.z = rotation.z();
scanHeader.pose.translation.x = translation.x();
scanHeader.pose.translation.y = translation.y();
scanHeader.pose.translation.z = translation.z();
}
Setup scanner information
if(exportScanner)
{
scanHeader.sensorSerialNumber = (char*) bstrSerial;
scanHeader.sensorVendor = (char*) bstrVendor;
scanHeader.sensorModel = (char*) bstrModel;
scanHeader.sensorSoftwareVersion = (char*) bstrSoftware;
scanHeader.sensorFirmwareVersion = (char*) bstrFirmware;
scanHeader.sensorHardwareVersion = (char*) bstrHardware;
scanHeader.temperature = pStat->GetTemperature();
scanHeader.relativeHumidity = pStat->GetHumidity();
scanHeader.atmosphericPressure = pStat->GetAirPressure();
}
///////////////////////////////////////////////////////////////
SETTING UP PointRecord Fields
Setup Points
scanHeader.pointFields.cartesianInvalidStateField = true;
int8_t * isInvalidData = new int8_t[nRow];
scanHeader.pointFields.cartesianXField = true;
double * xData = new double[nRow];
scanHeader.pointFields.cartesianYField = true;
double * yData = new double[nRow];
scanHeader.pointFields.cartesianZField = true;
double * zData = new double[nRow];
scanHeader.pointFields.pointRangeScaledInteger = DATA_SCALE_FACTOR;
scanHeader.pointFields.pointRangeMinimum = ((double)-E57_INT32_MAX) / DATA_SCALE_FACTOR;
scanHeader.pointFields.pointRangeMaximum = ((double) E57_INT32_MAX) / DATA_SCALE_FACTOR;
Setup Color
uint16_t * redData = NULL;
uint16_t * greenData = NULL;
uint16_t * blueData = NULL;
if(exportColor)
{
scanHeader.pointFields.colorRedField = true;
redData = new uint16_t[nRow];
scanHeader.pointFields.colorGreenField = true;
greenData = new uint16_t[nRow];
scanHeader.pointFields.colorBlueField = true;
blueData = new uint16_t[nRow];
scanheader.colorLimits.colorRedMinimum = e57::E57_UINT8_MIN;
scanheader.colorLimits.colorRedMaximum = e57::E57_UINT8_MAX;
scanheader.colorLimits.colorGreenMinimum = e57::E57_UINT8_MIN;
scanheader.colorLimits.colorGreenMaximum = e57::E57_UINT8_MAX;
scanheader.colorLimits.colorBlueMinimum = e57::E57_UINT8_MIN;
scanheader.colorLimits.colorBlueMaximum = e57::E57_UINT8_MAX;
}
Setup Intensity
double * intData = NULL;
if(exportIntensity)
{
scanHeader.pointFields.intensityField = true;
intData = new double[nRow];
header.intensityLimits.intensityMaximum = 1.;
headerintensityLimits.intensityMinimum = 0.;
header.pointFields.intensityScaledInteger = 0.; //0. uses FloatNode, -1. uses IntegerNode, >0. uses ScaledIntegerNode
}
Write out a new scan header and receive back the index
int scanIndex = eWriter.NewData3D(scanHeader);
Setup the data buffers
e57::CompressedVectorWriter dataWriter = eWriter.SetUpData3DPointsData(
scanIndex, //!< data block index given by the NewData3D
nRow, //!< size of each of the buffers given
xData, //!< pointer to a buffer with the x data
yData, //!< pointer to a buffer with the y data
zData, //!< pointer to a buffer with the z data
isInvalidData, //!< pointer to a buffer with the valid indication
intData, //!< pointer to a buffer with the lidar return intesity
NULL,
redData, //!< pointer to a buffer with the color red data
greenData, //!< pointer to a buffer with the color green data
blueData, //!< pointer to a buffer with the color blue data
NULL
);
/////////////////////////////////////////////////////////////// WRITING SCAN DATA
vector<int64_t> idElementValue;
vector<int64_t> startPointIndex;
vector<int64_t> pointCount;
int group = 0;
int startPoint = 0;
Access the point data
for(long j = 0; j < nColumn; j++)
{
int count = 0;
for(long i = 0; i < nRow; i++)
{
Get the invalid status
isInvalidData[count] = (pScan->GetStatus(i,j) & INVALID) ? 2 : 0;
Get the point
ISI::Point point = pScan->GetPoint(i, j);
xData[count] = point.x();
yData[count] = point.y();
zData[count] = point.z();
Get the intensity 0. to 1. range
if(exportIntensity)
intData[count] = pScan->GetIntensity(i, j);
Get the color
if(exportColor)
{
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
pScan->GetColor(i, j, &red, &green, &blue);
redData[count] = (uint8_t) red;
greenData[count] = (uint8_t) green;
blueData[count] = (uint8_t) blue;
}
count++;
}
Write out the buffers
dataWriter.write(count);
Collect the group information
idElementValue.push_back((int64_t) j);
startPointIndex.push_back((int64_t) startPoint);
pointCount.push_back((int64_t) count);
group++;
startPoint += count;
}
Finish the scan data write
dataWriter.close();
Write out the group information
eWriter.WriteData3DGroupsData(scanIndex, group,
(int64_t*) &idElementValue[0],
(int64_t*) &startPointIndex[0],
(int64_t*) &pointCount[0]);
Clean up
if(isInvalidData) delete isInvalidData;
if(xData) delete xData;
if(yData) delete yData;
if(zData) delete zData;
if(intData) delete intData;
if(redData) delete redData;
if(greenData) delete greenData;
if(blueData) delete blueData;
///////////////////////////////////////////////////////////// SETTING UP SCAN IMAGE2D
e57::Image2D imageHeader;
Setup the Name and Description
imageHeader.name = (char*) bstrName;
imageHeader.description = (char*) bstrDesc;
Setup the GUID
imageHeader.guid = (char*) bstrImageGuid;
imageHeader.associatedData3DGuid = (char*) bstrScanGuid;
Setup the DateTime
imageHeader.acquisitionDateTime.SetCurrentGPSTime() //set current time.
Setup camera information
imageHeader.sensorSerialNumber = (char*) bstrSerial;
imageHeader.sensorVendor = (char*) bstrVendor;
imageHeader.sensorModel = (char*) bstrModel;
Setup image orientation
imageHeader.pose.rotation.w = rotation.w();
imageHeader.pose.rotation.x = rotation.x();
imageHeader.pose.rotation.y = rotation.y();
imageHeader.pose.rotation.z = rotation.z();
imageHeader.pose.translation.x = translation.x();
imageHeader.pose.translation.y = translation.y();
imageHeader.pose.translation.z = translation.z();
Setup image size
imageHeader.sphericalRepresentation.imageHeight = imageHeight;
imageHeader.sphericalRepresentation.imageWidth = imageWidth;
imageHeader.sphericalRepresentation.pixelHeight = pixelHeight;
imageHeader.sphericalRepresentation.pixelWidth = pixelWidth;
Open jpeg file
CFile jpegFile;
CFileException fileError;
jpegFile.Open(imagePath, CFile::modeRead | CFile::typeBinary, &fileError);
ULONGLONG dwLength = jpegFile.GetLength();
imageHeader.sphericalRepresentation.jpegImageSize = dwLength; //Real Size before newing image header
Write the image header
int imageIndex = eWriter.NewImage2D(header);
Access the jpeg image data
void * pBuffer = new char[dwLength];
jpegFile.SeekToBegin();
jpegFile.Read(pBuffer,dwLength);
Write the jpeg data
eWriter.WriteImage2DData(imageIndex, e57::E57_JPEG_IMAGE, e57::E57_SPHERICAL,
pBuffer,0,dwLength);
Finish the E57 file
eWriter.Close();
///////////////////////////////////////////////////////////////////// CATCH THE ERRORS
} catch(E57Exception& ex) {
ex.report(__FILE__, __LINE__, __FUNCTION__);
} catch (std::exception& ex) {
cerr << "Got an std::exception, what=" << ex.what() << endl;
} catch (...) {
cerr << "Got an unknown exception" << endl;
}
1.8.2