From eb5b3d615e99fb2a4e3cd43027ce7f50c25b5743 Mon Sep 17 00:00:00 2001 From: Howard Butler Date: Fri, 22 Nov 2013 18:58:33 -0600 Subject: [PATCH] PointBuffer/Schema orientation #209. A PointBuffer may be POINT_INTERLEAVED or DIMENSION_INTERLEAVED with the default being POINT_INTERLEAVED. --- include/pdal/PointBuffer.hpp | 81 +++++++++++++++--- include/pdal/Schema.hpp | 22 ++++- schemas/8-dimension-schema.xml | 3 +- schemas/LAS.xsd | 18 +++- src/PointBuffer.cpp | 111 +++++++++++++++++++++++-- src/Schema.cpp | 36 +++++++- src/XMLSchema.cpp | 11 ++- src/drivers/nitf/Writer.cpp | 4 +- src/drivers/oci/Writer.cpp | 23 +---- src/filters/Scaling.cpp | 9 +- test/unit/PointBufferTest.cpp | 148 +++++++++++++++++++++++++++++++++ test/unit/SchemaTest.cpp | 37 +++++++++ test/unit/XMLSchemaTest.cpp | 3 + 13 files changed, 451 insertions(+), 55 deletions(-) diff --git a/include/pdal/PointBuffer.hpp b/include/pdal/PointBuffer.hpp index 80e196468c..6bdc353a53 100644 --- a/include/pdal/PointBuffer.hpp +++ b/include/pdal/PointBuffer.hpp @@ -60,13 +60,6 @@ namespace pdal typedef boost::interprocess::allocator ShmemAllocator; typedef boost::container::vector PointBufferVector; - enum Orientation - { - POINT_INTERLEAVED = 1, - DIMENSION_INTERLEAVED = 2, - UNKNOWN_INTERLEAVED = 256 - }; - } // pointbuffer @@ -275,7 +268,23 @@ class PDAL_DLL PointBuffer /// @param pointIndex position to start accessing inline boost::uint8_t* getData(boost::uint32_t pointIndex) const { - return const_cast(&(m_data.front())) + m_byteSize * pointIndex; +#if DEBUG +#endif + pointbuffer::PointBufferByteSize position(0); + if (m_orientation == schema::POINT_INTERLEAVED) + { + position = static_cast(m_byteSize) * \ + static_cast(pointIndex); + + } + else if (m_orientation == schema::DIMENSION_INTERLEAVED) + { + pointbuffer::PointBufferByteSize offset(0); + offset = m_schema.getDimension(pointIndex).getByteOffset(); + position = static_cast(m_numPoints) * offset; + } + return const_cast(&(m_data.front())) + position; + } /// copies the raw data into your own byte array and sets the size @@ -323,6 +332,9 @@ class PDAL_DLL PointBuffer /// with the given point size and force a new reallocation of the data buffer. void resize(boost::uint32_t const& capacity, bool bExact=false); + /// @return a new PointBuffer with all ignored dimensions removed + PointBuffer pack() const; + /** @name Serialization */ /*! returns a boost::property_tree containing the point records, which is @@ -392,6 +404,10 @@ class PDAL_DLL PointBuffer // We cache m_schema.getByteSize() here because it would end up // being dereferenced for every point read otherwise. schema::size_type m_byteSize; + + // We cache m_schema.getOrientation() here because it would end + // up being dereferenced for every point read + schema::Orientation m_orientation; Metadata m_metadata; boost::interprocess::managed_shared_memory *m_segment; @@ -408,12 +424,30 @@ inline void PointBuffer::setField(pdal::Dimension const& dim, boost::uint32_t po { if (dim.getPosition() == -1) { - // this is a little harsh, but we'll keep it for now as we shake things out throw buffer_error("This dimension has no identified position in a schema. Use the setRawField method to access an arbitrary byte position."); } - pointbuffer::PointBufferByteSize point_start_byte_position = static_cast(pointIndex) * static_cast(m_byteSize); - pointbuffer::PointBufferByteSize offset = point_start_byte_position + static_cast(dim.getByteOffset()); + pointbuffer::PointBufferByteSize point_start_byte_position(0); + pointbuffer::PointBufferByteSize offset(0); + + if (m_orientation == schema::POINT_INTERLEAVED) + { + point_start_byte_position = static_cast(pointIndex) * \ + static_cast(m_byteSize); + offset = point_start_byte_position + \ + static_cast(dim.getByteOffset()); + } + else if (m_orientation == schema::DIMENSION_INTERLEAVED) + { + point_start_byte_position = static_cast(m_capacity) * \ + static_cast(dim.getByteOffset()); + offset = point_start_byte_position + \ + static_cast(dim.getByteSize()) * \ + static_cast(pointIndex); + } else + { + throw buffer_error("unknown pdal::Schema::m_orientation provided!"); + } #ifdef DEBUG assert(offset + sizeof(T) <= getBufferByteSize()); @@ -445,8 +479,29 @@ inline T const& PointBuffer::getField(pdal::Dimension const& dim, boost::uint32 throw buffer_error("This dimension has no identified position in a schema."); } - pointbuffer::PointBufferByteSize point_start_byte_position = static_cast(pointIndex) * static_cast(m_byteSize); - boost::uint64_t offset = point_start_byte_position + static_cast(dim.getByteOffset()); + // pointbuffer::PointBufferByteSize point_start_byte_position = static_cast(pointIndex) * static_cast(m_byteSize); + // boost::uint64_t offset = point_start_byte_position + static_cast(dim.getByteOffset()); + + pointbuffer::PointBufferByteSize point_start_byte_position(0); + pointbuffer::PointBufferByteSize offset(0); + + if (m_orientation == schema::POINT_INTERLEAVED) + { + point_start_byte_position = static_cast(pointIndex) * \ + static_cast(m_byteSize); + offset = point_start_byte_position + \ + static_cast(dim.getByteOffset()); + } else if (m_orientation == schema::DIMENSION_INTERLEAVED) + { + point_start_byte_position = static_cast(m_capacity) * \ + static_cast(dim.getByteOffset()); + offset = point_start_byte_position + \ + static_cast(dim.getByteSize()) * \ + static_cast(pointIndex); + } else + { + throw buffer_error("unknown pdal::Schema::m_orientation provided!"); + } #ifdef DEBUG // This test ends up being somewhat expensive when run for every field diff --git a/include/pdal/Schema.hpp b/include/pdal/Schema.hpp index 68179b111c..3b33b91117 100644 --- a/include/pdal/Schema.hpp +++ b/include/pdal/Schema.hpp @@ -101,6 +101,13 @@ typedef boost::uint32_t size_type; typedef std::map DimensionMap; +enum Orientation +{ + POINT_INTERLEAVED = 1, + DIMENSION_INTERLEAVED = 2, + UNKNOWN_INTERLEAVED = 256 +}; + } /// A pdal::Schema is a composition of pdal::Dimension instances that form @@ -216,6 +223,19 @@ class PDAL_DLL Schema return m_index.get().size(); } + inline schema::Orientation getOrientation() const + { + return m_orientation; + } + + inline void setOrientation(schema::Orientation v) + { + m_orientation = v; + } + + /// @return a new schema with all ignored fields removed. + Schema pack() const; + /// @name Summary and serialization /// @return a boost::property_tree representing the Schema /*! @@ -256,8 +276,8 @@ class PDAL_DLL Schema private: schema::size_type m_byteSize; - schema::Map m_index; + schema::Orientation m_orientation; }; diff --git a/schemas/8-dimension-schema.xml b/schemas/8-dimension-schema.xml index ce39e3b44f..922d727f7e 100644 --- a/schemas/8-dimension-schema.xml +++ b/schemas/8-dimension-schema.xml @@ -1,5 +1,5 @@ - + 1 4 @@ -249,4 +249,5 @@ trueAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiYw== + point diff --git a/schemas/LAS.xsd b/schemas/LAS.xsd index 2c4ec5d4be..856db727ef 100644 --- a/schemas/LAS.xsd +++ b/schemas/LAS.xsd @@ -1,5 +1,5 @@ - + @@ -51,7 +51,7 @@ The dimension's position in the block of point data - (counting from 0) + (counting from 1) @@ -153,12 +153,26 @@ + + + + + Used to describe the storage orientation of the word. The orientation of a dimension might be 'point' oriented or 'dimension' oriented. A 'point' oriented dimension, the default orientation, has its dimensions composed as XYZXYZXYZ. A 'dimension' oriented one has data composed as XXXYYYZZZ. + + + + + + + + + diff --git a/src/PointBuffer.cpp b/src/PointBuffer.cpp index 547c6cd777..30bc3c212d 100644 --- a/src/PointBuffer.cpp +++ b/src/PointBuffer.cpp @@ -50,6 +50,7 @@ PointBuffer::PointBuffer(const Schema& schema, boost::uint32_t capacity) , m_capacity(capacity) , m_bounds(Bounds::getDefaultSpatialExtent()) , m_byteSize(schema.getByteSize()) + , m_orientation(schema.getOrientation()) , m_metadata("pointbuffer") , m_segment(0) @@ -75,6 +76,7 @@ PointBuffer::PointBuffer(PointBuffer const& other) , m_capacity(other.m_capacity) , m_bounds(other.m_bounds) , m_byteSize(other.m_byteSize) + , m_orientation(other.m_orientation) , m_metadata(other.m_metadata) { @@ -96,6 +98,7 @@ PointBuffer& PointBuffer::operator=(PointBuffer const& rhs) m_capacity = rhs.getCapacity(); m_bounds = rhs.getSpatialBounds(); m_byteSize = rhs.m_byteSize; + m_orientation = rhs.m_orientation; m_data = rhs.m_data; m_metadata = rhs.m_metadata; } @@ -109,6 +112,7 @@ void PointBuffer::reset(Schema const& new_schema) m_schema = new_schema; m_byteSize = new_size; + m_orientation = new_schema.getOrientation(); if (m_byteSize != old_size) { @@ -151,7 +155,7 @@ void PointBuffer::setSpatialBounds(const Bounds& bounds) void PointBuffer::setData(boost::uint8_t* data, boost::uint32_t pointIndex) { - boost::uint64_t position = static_cast(m_byteSize) * static_cast(pointIndex); + boost::uint64_t position = static_cast(m_byteSize) * static_cast(pointIndex); memcpy(&(m_data.front()) + position, data, m_byteSize); } @@ -159,7 +163,7 @@ void PointBuffer::setDataStride(boost::uint8_t* data, boost::uint32_t pointIndex, boost::uint32_t byteCount) { - boost::uint64_t position = static_cast(m_byteSize) * static_cast(pointIndex); + boost::uint64_t position = static_cast(m_byteSize) * static_cast(pointIndex); memcpy(&(m_data.front()) + position, data, byteCount); } @@ -171,6 +175,58 @@ void PointBuffer::getData(boost::uint8_t** data, boost::uint64_t* array_size) co memcpy(*data, &(m_data.front()), static_cast(*array_size)); } +PointBuffer PointBuffer::pack() const +{ + + // Creates a new buffer that has the ignored dimensions removed from + // it. + + pdal::Schema const& schema = getSchema(); + schema::index_by_index const& idx = schema.getDimensions().get(); + pdal::Schema output_schema = schema.pack(); + pdal::PointBuffer output(output_schema, getNumPoints()); + + boost::uint8_t* src = getData(0); + + boost::uint8_t* current_position = output.getData(0); + + schema::Orientation orientation = getSchema().getOrientation(); + if (orientation == schema::POINT_INTERLEAVED) + { + for (boost::uint32_t i = 0; i < getNumPoints(); ++i) + { + boost::uint8_t* data = getData(i); + for (boost::uint32_t d = 0; d < idx.size(); ++d) + { + if (! idx[d].isIgnored()) + { + memcpy(current_position, data, idx[d].getByteSize()); + current_position = current_position+idx[d].getByteSize(); + } + data = data + idx[d].getByteSize(); + } + } + } + else if (orientation == schema::DIMENSION_INTERLEAVED) + { + for (boost::uint32_t i = 0; i < getSchema().size(); ++i) + { + // For each dimension, copy the data if it isn't ignored + boost::uint8_t* data = getData(i); + boost::uint64_t dimension_length = static_cast(idx[i].getByteSize()) * static_cast(getCapacity()); + if (! idx[i].isIgnored()) + { + + memcpy(current_position, data, dimension_length); + current_position = current_position+dimension_length; + } + data = data + dimension_length; + } + } + + return output; + +} pdal::Bounds PointBuffer::calculateBounds(bool is3d) const { @@ -517,21 +573,58 @@ void PointBuffer::copyLikeDimensions(PointBuffer const& source, assert(howMany <= source.getCapacity() - source_starting_position); typedef schema::DimensionMap::const_iterator Iterator; - + + if (source.getSchema().getOrientation() != destination.getSchema().getOrientation()) + throw buffer_error("Point Buffers do not have same orientation"); + + unsigned counter(0); for (Iterator d = dimensions.begin(); d != dimensions.end(); ++d) { Dimension const& source_dim = *d->first; Dimension const& dest_dim = *d->second; - - for (boost::uint32_t i = 0; i < howMany; ++i) + if (source_dim.getByteSize() != dest_dim.getByteSize()) + { + std::ostringstream oss; + oss << "Dimension '" << dest_dim.getName() << "' are not the same byte size and cannot be copied"; + throw buffer_error(oss.str()); + } + + if (source.getSchema().getOrientation() == schema::POINT_INTERLEAVED) { - boost::uint8_t* source_position = source.getData(source_starting_position+i) + source_dim.getByteOffset(); - boost::uint8_t* destination_position = destination.getData(destination_starting_position + i) + dest_dim.getByteOffset(); - memcpy(destination_position, source_position, dest_dim.getByteSize()); + for (boost::uint32_t i = 0; i < howMany; ++i) + { + boost::uint8_t* source_position = source.getData(source_starting_position+i) + source_dim.getByteOffset(); + boost::uint8_t* destination_position = destination.getData(destination_starting_position + i) + dest_dim.getByteOffset(); + memcpy(destination_position, source_position, dest_dim.getByteSize()); + } + } else if (source.getSchema().getOrientation() == schema::DIMENSION_INTERLEAVED) + { + pointbuffer::PointBufferByteSize source_point_start_byte_position(0); + pointbuffer::PointBufferByteSize source_offset(0); + source_point_start_byte_position = static_cast(source.getCapacity()) * \ + static_cast(source_dim.getByteOffset()); source_offset = source_point_start_byte_position + \ + static_cast(source_dim.getByteSize()) * \ + static_cast(source_starting_position); + + pointbuffer::PointBufferByteSize destination_point_start_byte_position(0); + pointbuffer::PointBufferByteSize destination_offset(0); + destination_point_start_byte_position = static_cast(destination.getCapacity()) * \ + static_cast(dest_dim.getByteOffset()); + destination_offset = destination_point_start_byte_position + \ + static_cast(dest_dim.getByteSize()) * \ + static_cast(destination_starting_position); + + boost::uint8_t* source_start = source.getData(0); + boost::uint8_t* destination_start = destination.getData(0); + pointbuffer::PointBufferByteSize dimension_size(0); + dimension_size = static_cast(source_dim.getByteSize()) * \ + static_cast(howMany); + memcpy(destination_start + destination_offset, source_start+source_offset, dimension_size); } + } - + destination.setNumPoints(howMany); } diff --git a/src/Schema.cpp b/src/Schema.cpp index 91b93642b0..69eb3a8cc0 100644 --- a/src/Schema.cpp +++ b/src/Schema.cpp @@ -61,12 +61,14 @@ namespace pdal Schema::Schema() : m_byteSize(0) + , m_orientation(schema::POINT_INTERLEAVED) { return; } Schema::Schema(std::vector const& dimensions) : m_byteSize(0) + , m_orientation(schema::POINT_INTERLEAVED) { for (std::vector::const_iterator i = dimensions.begin(); @@ -80,6 +82,8 @@ Schema::Schema(std::vector const& dimensions) Schema::Schema(Schema const& other) : m_byteSize(other.m_byteSize) , m_index(other.m_index) + , m_orientation(other.m_orientation) + { } @@ -92,6 +96,7 @@ Schema& Schema::operator=(Schema const& rhs) { m_byteSize = rhs.m_byteSize; m_index = rhs.m_index; + m_orientation = rhs.m_orientation; } return *this; @@ -103,6 +108,8 @@ bool Schema::operator==(const Schema& other) const if (m_byteSize != other.m_byteSize) return false; if (m_index.size() != other.m_index.size()) return false; + + if (m_orientation != other.m_orientation) return false; schema::index_by_index const& idx = m_index.get(); schema::index_by_index const& idx2 = other.m_index.get(); @@ -242,7 +249,7 @@ const Dimension* Schema::getDimensionPtr(string_ref nameIn, string_ref namespc, std::string* errorMsg) const { // getDimensionPtr is implemented in terms of string_ref so that we - // can guarentee not to allocate memory unless we really need to. + // can guarantee not to allocate memory unless we really need to. string_ref name = nameIn; string_ref ns = namespc; if (ns.empty()) @@ -563,6 +570,33 @@ void Schema::dump() const std::cout << *this; } +Schema Schema::pack() const +{ + + schema::index_by_index const& idx = getDimensions().get(); + + boost::uint32_t position(0); + + pdal::Schema output; + schema::index_by_index::size_type i(0); + for (i = 0; i < idx.size(); ++i) + { + if (! idx[i].isIgnored()) + { + + Dimension d(idx[i]); + d.setPosition(position); + + // Wipe off parent/child relationships if we're ignoring + // same-named dimensions + d.setParent(boost::uuids::nil_uuid()); + output.appendDimension(d); + position++; + } + } + output.setOrientation(getOrientation()); + return output; +} std::ostream& operator<<(std::ostream& os, pdal::Schema const& schema) { diff --git a/src/XMLSchema.cpp b/src/XMLSchema.cpp index 7e3214e758..193239fe9d 100644 --- a/src/XMLSchema.cpp +++ b/src/XMLSchema.cpp @@ -745,7 +745,7 @@ void Writer::write(TextWriterPtr writer) xmlTextWriterSetIndent(w, 1); xmlTextWriterStartDocument(w, NULL, "utf-8", NULL); xmlTextWriterStartElementNS(w, BAD_CAST "pc", BAD_CAST "PointCloudSchema", NULL); - xmlTextWriterWriteAttributeNS(w, BAD_CAST "xmlns", BAD_CAST "pc", NULL, BAD_CAST "http://pointcloud.org/schemas/PC/1.1"); + xmlTextWriterWriteAttributeNS(w, BAD_CAST "xmlns", BAD_CAST "pc", NULL, BAD_CAST "http://pointcloud.org/schemas/PC/"); xmlTextWriterWriteAttributeNS(w, BAD_CAST "xmlns", BAD_CAST "xsi", NULL, BAD_CAST "http://www.w3.org/2001/XMLSchema-instance"); writeSchema(writer); @@ -765,7 +765,14 @@ void Writer::write(TextWriterPtr writer) xmlTextWriterWriteRawLen(w, BAD_CAST xml.c_str(), xml.size()); xmlTextWriterEndElement(w); } - + + std::ostringstream orientation; + if (m_schema.getOrientation() == schema::POINT_INTERLEAVED) + orientation << "point"; + if (m_schema.getOrientation() == schema::DIMENSION_INTERLEAVED) + orientation << "dimension"; + xmlTextWriterWriteElementNS(w, BAD_CAST "pc", BAD_CAST "orientation", NULL, BAD_CAST orientation.str().c_str()); + xmlTextWriterEndElement(w); xmlTextWriterEndDocument(w); diff --git a/src/drivers/nitf/Writer.cpp b/src/drivers/nitf/Writer.cpp index f19136a1d3..f5d1063c39 100644 --- a/src/drivers/nitf/Writer.cpp +++ b/src/drivers/nitf/Writer.cpp @@ -146,7 +146,7 @@ void Writer::writeEnd(boost::uint64_t actualNumPointsWritten) header.getMessageCopyNum().set("00000"); header.getMessageNumCopies().set("00000"); header.getEncrypted().set("0"); - header.getBackgroundColor().setRawData((char*)"000", 3); + header.getBackgroundColor().setRawData(const_cast("000"), 3); header.getOriginatorName().set(getOptions().getValueOrDefault("ONAME","")); header.getOriginatorPhone().set(getOptions().getValueOrDefault("OPHONE","")); @@ -222,7 +222,7 @@ void Writer::writeEnd(boost::uint64_t actualNumPointsWritten) const char* buffer = "0000000000000000000000000000000000000000000000000000000000000000"; ::nitf::BandSource* band = - new ::nitf::MemorySource((char*) buffer, + new ::nitf::MemorySource(const_cast(buffer), strlen(buffer) /* memory size */, 0 /* starting offset */, 1 /* bytes per pixel */, diff --git a/src/drivers/oci/Writer.cpp b/src/drivers/oci/Writer.cpp index 36162c0dd0..bd58914d9c 100644 --- a/src/drivers/oci/Writer.cpp +++ b/src/drivers/oci/Writer.cpp @@ -841,28 +841,9 @@ void Writer::CreatePCEntry(Schema const& buffer_schema) bool pack = getOptions().getValueOrDefault("pack_ignored_fields", true); if (pack) { - schema::index_by_index const& idx = buffer_schema.getDimensions().get(); log()->get(logDEBUG3) << "Packing ignored dimension from PointBuffer " << std::endl; - - boost::uint32_t position(0); - - pdal::Schema clean_schema; - schema::index_by_index::size_type i(0); - for (i = 0; i < idx.size(); ++i) - { - if (! idx[i].isIgnored()) - { - - Dimension d(idx[i]); - d.setPosition(position); - - // Wipe off parent/child relationships if we're ignoring - // same-named dimensions - d.setParent(boost::uuids::nil_uuid()); - clean_schema.appendDimension(d); - position++; - } - } + + pdal::Schema clean_schema = buffer_schema.pack(); schema_data = pdal::Schema::to_xml(clean_schema); } diff --git a/src/filters/Scaling.cpp b/src/filters/Scaling.cpp index 685a5fdef8..f0ad23b445 100644 --- a/src/filters/Scaling.cpp +++ b/src/filters/Scaling.cpp @@ -365,9 +365,12 @@ void IteratorBase::scaleData(PointBuffer& buffer, boost::uint32_t numRead) { boost::optional f = d->first; boost::optional t = d->second; - Dimension const& from_dimension = *f; - Dimension const& to_dimension = *t; - writeScaledData(buffer, from_dimension, to_dimension, pointIndex); + if (f && t) + { + Dimension const& from_dimension = *f; + Dimension const& to_dimension = *t; + writeScaledData(buffer, from_dimension, to_dimension, pointIndex); + } } } } diff --git a/test/unit/PointBufferTest.cpp b/test/unit/PointBufferTest.cpp index ac8b3de493..8a1d2017cb 100644 --- a/test/unit/PointBufferTest.cpp +++ b/test/unit/PointBufferTest.cpp @@ -434,4 +434,152 @@ BOOST_AUTO_TEST_CASE(test_indexed) return; } + + +BOOST_AUTO_TEST_CASE(test_packing) +{ + + + Dimension cls("Classification", dimension::UnsignedInteger, 1); + Dimension x("X", dimension::SignedInteger, 4); + Dimension y("Y", dimension::Float, 8); + boost::uint32_t flags = y.getFlags(); + y.setFlags(flags | dimension::IsIgnored); + + Schema schema; + schema.appendDimension(x); + schema.appendDimension(y); + schema.appendDimension(cls); + + PointBuffer buffer(schema, 10); + Dimension const& dimX = buffer.getSchema().getDimension("X"); + Dimension const& dimY = buffer.getSchema().getDimension("Y"); + Dimension const& dimCls = buffer.getSchema().getDimension("Classification"); + + buffer.setNumPoints(10); + for(int i = 0; i < buffer.getNumPoints(); ++i) + { + buffer.setField(dimX, i, i); + buffer.setField(dimY, i, i + 100); + buffer.setField(dimCls, i, 7); + } + BOOST_CHECK_EQUAL(buffer.getNumPoints(), 10); + + PointBuffer packed = buffer.pack(); + pdal::schema::DimensionMap* dims = schema.mapDimensions(packed.getSchema()); + PointBuffer::copyLikeDimensions(buffer, packed, *dims, 0, 0, buffer.getNumPoints()); + + packed.setNumPoints(10); + + BOOST_CHECK_EQUAL(packed.getSchema().getByteSize(), 5); + BOOST_CHECK_EQUAL(packed.getNumPoints(), 10); + BOOST_CHECK_EQUAL(packed.getBufferByteLength(), 10*5); + + Dimension const& kls = packed.getSchema().getDimension("Classification"); + Dimension const& x2 = packed.getSchema().getDimension("X"); + BOOST_CHECK_EQUAL(packed.getField(kls,0),7); + BOOST_CHECK_EQUAL(packed.getField(x2,8),8); + + delete dims; + return; + +} + + +BOOST_AUTO_TEST_CASE(test_orientation) +{ + + + Dimension cls("Classification", dimension::UnsignedInteger, 1); + Dimension x("X", dimension::SignedInteger, 4); + Dimension y("Y", dimension::Float, 8); + + Schema schema; + schema.appendDimension(x); + schema.appendDimension(y); + schema.appendDimension(cls); + schema.setOrientation(schema::DIMENSION_INTERLEAVED); + + BOOST_CHECK_EQUAL(schema.getOrientation(), schema::DIMENSION_INTERLEAVED); + + PointBuffer buffer(schema, 10); + Dimension const& dimX = buffer.getSchema().getDimension("X"); + Dimension const& dimY = buffer.getSchema().getDimension("Y"); + Dimension const& dimCls = buffer.getSchema().getDimension("Classification"); + + buffer.setNumPoints(10); + for(int i = 0; i < buffer.getNumPoints(); ++i) + { + buffer.setField(dimX, i, i); + double yd = i + 100; + buffer.setField(dimY, i, yd); + buffer.setField(dimCls, i, 7); + } + BOOST_CHECK_EQUAL(buffer.getNumPoints(), 10); + + + for(int i = 0; i < buffer.getNumPoints(); ++i) + { + boost::int32_t x = buffer.getField(dimX, i); + double y = buffer.getField(dimY, i); + boost::uint8_t c = buffer.getField(dimCls, i); + BOOST_CHECK_EQUAL(x, i); + BOOST_CHECK_CLOSE(y, i + 100, 0.000001); + BOOST_CHECK_EQUAL(c, 7u); + } + return; +} + +BOOST_AUTO_TEST_CASE(test_orientation_packing) +{ + + + Dimension cls("Classification", dimension::UnsignedInteger, 1); + Dimension x("X", dimension::SignedInteger, 4); + Dimension y("Y", dimension::Float, 8); + boost::uint32_t flags = y.getFlags(); + y.setFlags(flags | dimension::IsIgnored); + + Schema schema; + schema.appendDimension(x); + schema.appendDimension(y); + schema.appendDimension(cls); + + PointBuffer buffer(schema, 10); + Dimension const& dimX = buffer.getSchema().getDimension("X"); + Dimension const& dimY = buffer.getSchema().getDimension("Y"); + Dimension const& dimCls = buffer.getSchema().getDimension("Classification"); + + buffer.setNumPoints(10); + for(int i = 0; i < buffer.getNumPoints(); ++i) + { + buffer.setField(dimX, i, i); + double yd = i + 100; + buffer.setField(dimY, i, yd); + buffer.setField(dimCls, i, 7); + } + BOOST_CHECK_EQUAL(buffer.getNumPoints(), 10); + + PointBuffer packed = buffer.pack(); + pdal::schema::DimensionMap* dims = schema.mapDimensions(packed.getSchema()); + PointBuffer::copyLikeDimensions(buffer, packed, *dims, 0, 0, buffer.getNumPoints()); + + BOOST_CHECK_EQUAL(packed.getSchema().getByteSize(), 5); + BOOST_CHECK_EQUAL(packed.getNumPoints(), 10); + BOOST_CHECK_EQUAL(packed.getBufferByteLength(), 10*5); + + Dimension const& kls = packed.getSchema().getDimension("Classification"); + Dimension const& x2 = packed.getSchema().getDimension("X"); + + BOOST_CHECK_EQUAL(packed.getField(kls,0),7); + BOOST_CHECK_EQUAL(packed.getField(x2,8),8); + + delete dims; + + + + return; + +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/unit/SchemaTest.cpp b/test/unit/SchemaTest.cpp index 69b34d410f..391caaa7a5 100644 --- a/test/unit/SchemaTest.cpp +++ b/test/unit/SchemaTest.cpp @@ -144,5 +144,42 @@ BOOST_AUTO_TEST_CASE(test_find) } +BOOST_AUTO_TEST_CASE(SchemaTest_orientation) +{ + + Dimension x("X", dimension::SignedInteger, 4); + Dimension y("Y", dimension::SignedInteger, 4); + Schema s; + s.appendDimension(x); + s.appendDimension(y); + + BOOST_CHECK_EQUAL(s.getOrientation(), pdal::schema::POINT_INTERLEAVED); + + + return; +} + + +BOOST_AUTO_TEST_CASE(SchemaTest_pack) +{ + + Dimension x("X", dimension::SignedInteger, 4); + Dimension y("Y", dimension::SignedInteger, 4); + boost::uint32_t flags = y.getFlags(); + y.setFlags(flags | dimension::IsIgnored); + Schema s; + s.appendDimension(x); + s.appendDimension(y); + + Schema p = s.pack(); + + BOOST_CHECK_EQUAL(p.size(), 1); + BOOST_CHECK_EQUAL(s.size(), 2); + + + + + return; +} BOOST_AUTO_TEST_SUITE_END() diff --git a/test/unit/XMLSchemaTest.cpp b/test/unit/XMLSchemaTest.cpp index 7e76bc5f16..d703183025 100644 --- a/test/unit/XMLSchemaTest.cpp +++ b/test/unit/XMLSchemaTest.cpp @@ -132,6 +132,9 @@ BOOST_AUTO_TEST_CASE(test_schema_read) writer.setMetadata(b.toPTree()); std::string xml_output = writer.getXML(); +// std::ostream* out = FileUtils::createFile("schemadump.xml"); +// out->write(xml_output.c_str(), strlen(xml_output.c_str())); +// FileUtils::closeFile(out); pdal::schema::Reader reader2(xml_output, xsd); pdal::Schema schema2 = reader2.getSchema();