Ejemplo n.º 1
0
bool IndexOutput::InitializeVLRData(boost::uint32_t CurCellX, boost::uint32_t CurCellY)
{

	try {
		m_indexVLRCellPointData.resize(numeric_limits<unsigned short>::max());

		m_DataRecordSize = m_VLRCommonDataSize;
		m_DataPointsThisVLR = 0;
		// 1st cell in VLR, x, y
		WriteVLRDataNoInc_n(m_indexVLRCellPointData, CurCellX, m_FirstCellLocation);
		WriteVLRDataNoInc_n(m_indexVLRCellPointData, CurCellY, m_FirstCellLocation + sizeof(boost::uint32_t));
		// last cell in VLR, x, y
		WriteVLRDataNoInc_n(m_indexVLRCellPointData, CurCellX, m_LastCellLocation);
		WriteVLRDataNoInc_n(m_indexVLRCellPointData, CurCellY, m_LastCellLocation + sizeof(boost::uint32_t));
		// data record size
		WriteVLRDataNoInc_n(m_indexVLRCellPointData, m_DataRecordSize, m_VLRDataSizeLocation);
		// number of points in this VLR - added in Index version 1.1
		WriteVLRDataNoInc_n(m_indexVLRCellPointData, m_DataPointsThisVLR, m_VLRPointCountLocation);
		m_FirstCellInVLR = false;
		m_SomeDataReadyToWrite = false;

		return true;
	}
	catch (std::bad_alloc) {
		return false;
	}
	catch (std::out_of_range) {
		return false;
	}
} // IndexOutput::InitializeVLRData
Ejemplo n.º 2
0
bool IndexOutput::OutputCell(liblas::detail::IndexCell *CellBlock, boost::uint32_t x, boost::uint32_t y)
{

	try {
		if (m_FirstCellInVLR)
		{
			if (! InitializeVLRData(x, y))
				return false;
			m_indexVLRTempData.resize((std::numeric_limits<unsigned short>::max)());
			m_TempWritePos = 0;
		} // if

		// data output for one cell may result in a partial VLR or more than one VLR depending on the number
		// of point records for the cell.
		// Partially filled VLR's are only flushed when the next cell would overflow the VLR size limit of USHRT_MAX
		// or on the last cell in the index cell block
		boost::uint32_t SubCellsXY, SubCellsZ, NumPts, PtRecords;

		NumPts = CellBlock->GetNumPoints();
		if (NumPts)
		{
			// keep track of the number of points in this VLR - added in Index version 1.1
			m_DataPointsThisVLR += NumPts;
			
			// current cell, x, y
			WriteVLRData_n(m_indexVLRTempData, x, m_TempWritePos);
			WriteVLRData_n(m_indexVLRTempData, y, m_TempWritePos);
			// number of points in this cell - added in Index version 1.1
			WriteVLRData_n(m_indexVLRTempData, NumPts, m_TempWritePos);

			// min and max Z
			ElevExtrema ExtremaZ = CellBlock->GetMinZ();
			WriteVLRData_n(m_indexVLRTempData, ExtremaZ, m_TempWritePos);
			ExtremaZ = CellBlock->GetMaxZ();
			WriteVLRData_n(m_indexVLRTempData, ExtremaZ, m_TempWritePos);
			
			// number of subcells in this cell in both XY and Z
			PtRecords = CellBlock->GetNumRecords();
			WriteVLRData_n(m_indexVLRTempData, PtRecords, m_TempWritePos);
			SubCellsXY = CellBlock->GetNumSubCellRecords();
			WriteVLRData_n(m_indexVLRTempData, SubCellsXY, m_TempWritePos);
			SubCellsZ = CellBlock->GetNumZCellRecords();
			WriteVLRData_n(m_indexVLRTempData, SubCellsZ, m_TempWritePos);
			

			// <<<>>> prevent array overruns
			// compile data into one long vector m_indexVLRTempData
			if (SubCellsZ)
			{
				for (liblas::detail::IndexSubCellData::iterator MyCellIt = CellBlock->GetFirstZCellRecord();
					MyCellIt != CellBlock->GetEndZCell(); ++MyCellIt)
				{
					// subcell number
					boost::uint32_t ZCellID = MyCellIt->first;
					WriteVLRData_n(m_indexVLRTempData, ZCellID, m_TempWritePos);
					// number of point records in subcell
					boost::uint32_t ZCellNumPts = static_cast<boost::uint32_t>(MyCellIt->second.size());
					WriteVLRData_n(m_indexVLRTempData, ZCellNumPts, m_TempWritePos);
					for (liblas::detail::IndexCellData::iterator MyPointIt = MyCellIt->second.begin();
						MyPointIt != MyCellIt->second.end(); ++MyPointIt)
					{
						boost::uint32_t PointID = MyPointIt->first;
						assert(PointID < m_index->GetPointRecordsCount());
						WriteVLRData_n(m_indexVLRTempData, PointID, m_TempWritePos);
						boost::uint8_t ConsecutivePts = MyPointIt->second;
						WriteVLRData_n(m_indexVLRTempData, ConsecutivePts, m_TempWritePos);
					} // for
				} // for
			} // if
			if (SubCellsXY)
			{
				for (liblas::detail::IndexSubCellData::iterator MyCellIt = CellBlock->GetFirstSubCellRecord();
					MyCellIt != CellBlock->GetEndSubCell(); ++MyCellIt)
				{
					// subcell number
					boost::uint32_t SubCellID = MyCellIt->first;
					WriteVLRData_n(m_indexVLRTempData, SubCellID, m_TempWritePos);
					// number of point records in subcell
					boost::uint32_t SubCellNumPts = static_cast<boost::uint32_t>(MyCellIt->second.size());
					WriteVLRData_n(m_indexVLRTempData, SubCellNumPts, m_TempWritePos);
					for (liblas::detail::IndexCellData::iterator MyPointIt = MyCellIt->second.begin();
						MyPointIt != MyCellIt->second.end(); ++MyPointIt)
					{
						boost::uint32_t PointID = MyPointIt->first;
						assert(PointID < m_index->GetPointRecordsCount());
						WriteVLRData_n(m_indexVLRTempData, PointID, m_TempWritePos);
						boost::uint8_t ConsecutivePts = MyPointIt->second;
						WriteVLRData_n(m_indexVLRTempData, ConsecutivePts, m_TempWritePos);
					} // for
				} // for
			} // if
			if (! (SubCellsZ || SubCellsXY))
			{
				for (liblas::detail::IndexCellData::iterator MyPointIt = CellBlock->GetFirstRecord();
					MyPointIt != CellBlock->GetEnd(); ++MyPointIt)
				{
					boost::uint32_t PointID = MyPointIt->first;
					assert(PointID < m_index->GetPointRecordsCount());
					WriteVLRData_n(m_indexVLRTempData, PointID, m_TempWritePos);
					boost::uint8_t ConsecutivePts = MyPointIt->second;
					WriteVLRData_n(m_indexVLRTempData, ConsecutivePts, m_TempWritePos);
				} // for
			} // if

			// copy data to VLR
			// if new cell data causes VLR data to exceed limit add VLR to header VLR list and start new VLR
			if (m_SomeDataReadyToWrite && (m_TempWritePos + m_DataRecordSize > (std::numeric_limits<unsigned short>::max)()))
			{
				m_indexVLRCellPointData.resize(m_DataRecordSize);
				m_indexVLRCellRecord.SetRecordLength(static_cast<boost::uint16_t>(m_DataRecordSize));
				m_indexVLRCellRecord.SetData(m_indexVLRCellPointData);
				m_index->GetIndexHeader()->AddVLR(m_indexVLRCellRecord);
				// get set up for next VLR
				if (! InitializeVLRData(x, y))
					return false;
				m_DataPointsThisVLR = NumPts;
			} // if
			// if size allows, add to VLR cell record data
			if (m_TempWritePos + m_DataRecordSize <= (std::numeric_limits<unsigned short>::max)())
			{
				boost::uint32_t WritePos = m_DataRecordSize;
				// update last cell in VLR, x, y
				WriteVLRDataNoInc_n(m_indexVLRCellPointData, x, m_LastCellLocation);
				WriteVLRDataNoInc_n(m_indexVLRCellPointData, y, m_LastCellLocation + sizeof(boost::uint32_t));
				// update data record size
				m_DataRecordSize += m_TempWritePos;
				WriteVLRDataNoInc_n(m_indexVLRCellPointData, m_DataRecordSize, m_VLRDataSizeLocation);
				// number of points in this VLR - added in Index version 1.1
				WriteVLRDataNoInc_n(m_indexVLRCellPointData, m_DataPointsThisVLR, m_VLRPointCountLocation);
				WriteVLRDataNoInc_str(m_indexVLRCellPointData, (char * const)&m_indexVLRTempData[0], m_TempWritePos, WritePos);
				m_SomeDataReadyToWrite = true;
				// rewind counter to start new cell data
				m_TempWritePos = 0;
			} // if
			else
			{
				// unusual situation where one cell's data exceeds the size allowed for a VLR (USHRT_MAX)
				// make as many USHRT_MAX size VLR's until all cell is represented.
				// distinguish the continuation style VLR with the first byte being the total size of the record.
				// When reading a VLR, if the size field is larger than USHRT_MAX you know you have more than one 
				// record to read and concatenate. 
				// WritePos should be at the end of the small VLR common data section
				boost::uint32_t WritePos = m_DataRecordSize;
				// m_TempWritePos is the size of the new data block
				// m_DataRecordSize is amount of common data written already
				boost::uint32_t UnwrittenBytes = m_TempWritePos;
				// Make DataRecordSize equal to the total size of the data + common data 
				m_DataRecordSize += m_TempWritePos;
				// write the total size in the common data section
				// resizing shouldn't be necessary
				if (m_indexVLRCellPointData.size() != (std::numeric_limits<unsigned short>::max)())
					m_indexVLRCellPointData.resize((std::numeric_limits<unsigned short>::max)());
				WriteVLRDataNoInc_n(m_indexVLRCellPointData, m_DataRecordSize, m_VLRDataSizeLocation);
				// number of points in this VLR - added in Index version 1.1
				WriteVLRDataNoInc_n(m_indexVLRCellPointData, m_DataPointsThisVLR, m_VLRPointCountLocation);
				
				// write out the part that fits in this VLR (excluding the common data)
				boost::uint32_t WrittenBytes = (std::numeric_limits<unsigned short>::max)() - WritePos;
				WriteVLRDataNoInc_str(m_indexVLRCellPointData, (char * const)&m_indexVLRTempData[0], WrittenBytes, WritePos);
				// add this VLR
				m_indexVLRCellRecord.SetRecordLength(static_cast<boost::uint16_t>((std::numeric_limits<unsigned short>::max)()));
				m_indexVLRCellRecord.SetData(m_indexVLRCellPointData);
				m_index->GetIndexHeader()->AddVLR(m_indexVLRCellRecord);
				
				// subtract the part written
				UnwrittenBytes -= WrittenBytes;
				
				while (UnwrittenBytes > 0)
				{
					boost::uint32_t NewWrittenBytes = (UnwrittenBytes < (std::numeric_limits<unsigned short>::max)() ? UnwrittenBytes: (std::numeric_limits<unsigned short>::max)());
					WriteVLRDataNoInc_str(m_indexVLRCellPointData, (char * const)&m_indexVLRTempData[WrittenBytes], NewWrittenBytes, 0);
					WrittenBytes += NewWrittenBytes;
					UnwrittenBytes -= NewWrittenBytes;
					m_indexVLRCellRecord.SetRecordLength(static_cast<boost::uint16_t>(NewWrittenBytes));
					m_indexVLRCellRecord.SetData(m_indexVLRCellPointData);
					m_index->GetIndexHeader()->AddVLR(m_indexVLRCellRecord);
				} // while
				// wipe the slate clean for the next cell
				m_SomeDataReadyToWrite = false;
				m_TempWritePos = 0;
				m_FirstCellInVLR = true;
			} // else
		} // if
		return true;
	} // try
	catch (std::bad_alloc) {
		return false;
	}
	catch (std::out_of_range) {
		return false;
	}
	
} // IndexOutput::OutputCell