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; }