E57 Simple API V1.0.224  Sept. 8, 2011
E57 Simple API V1.0.224 Documentation

Introduction

This browser-based document describes the E57 Simple API (Application Programmer Interface) version 1.0, which is a collection of functions that help a C++ programmer wrap the E57 Foundation API.

Reading using the E57 Simple 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.ReadData3D( 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;
	}

Writing using the E57 Simple API

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

#define DATA_SCALE_FACTOR	(.00001)
		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::E57_INT32_MAX) / DATA_SCALE_FACTOR;
		scanHeader.pointFields.pointRangeMaximum = ((double) e57::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;
	}