Skip to content

Commit

Permalink
Merge pull request #496 from /issues/496-naked-write
Browse files Browse the repository at this point in the history
There's no mechanism to write Buffers without using a Reader
  • Loading branch information
hobu committed Sep 25, 2014
2 parents ef53e59 + ffa1dee commit c47d7c9
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 136 deletions.
172 changes: 44 additions & 128 deletions doc/tutorial/writing.rst
Expand Up @@ -4,15 +4,15 @@
Writing with PDAL
=====================

This tutorial will describe a complete example of using PDAL C++ objects to write
a LAS file. The example will show fetching data from your own data source rather than
interacting with a :ref:`reader stage <stage_index>`.
This tutorial will describe a complete example of using PDAL C++ objects to write
a LAS file. The example will show fetching data from your own data source rather than
interacting with a :ref:`reader stage <stage_index>`.

.. note::
If you implement your own :ref:`reader <stage_index>` that conforms to
PDAL's :cpp:class:`pdal::Stage`, you can implement a simple read-filter-write
pipeline using :ref:`pipeline` and not have to code anything explicit

If you implement your own :ref:`reader <stage_index>` that conforms to
PDAL's :cpp:class:`pdal::Stage`, you can implement a simple read-filter-write
pipeline using :ref:`pipeline` and not have to code anything explicit
yourself.

Compilation
Expand All @@ -29,14 +29,14 @@ issue a compilation command something like the following:
.. note::

Refer to :ref:`building` for information on how to build PDAL.


Includes
-------------------------------------------------------------------------------

As of PDAL 1.0.0, there's a couple of include files available for use. The
main one, `<pdal/pdal.hpp>`, brings in most of the utility and basic classes
used throughout the PDAL system. Additionally, the following includes are
As of PDAL 1.0.0, there's a couple of include files available for use. The
main one, `<pdal/pdal.hpp>`, brings in most of the utility and basic classes
used throughout the PDAL system. Additionally, the following includes are
available subject to having the required include directories pathed:

* `#include <pdal/Drivers.hpp>`
Expand All @@ -46,19 +46,23 @@ available subject to having the required include directories pathed:

.. note::

Drivers, Filters, and Kernel bring in *all* of the respective sub includes
for those sections of the source tree. You are not required to include
everything if you don't need it, however, and it is still possible to
Drivers, Filters, and Kernel bring in *all* of the respective sub includes
for those sections of the source tree. You are not required to include
everything if you don't need it, however, and it is still possible to
selectively include the classes you need as shown in the example below.


Compile the example code with the following compile line:

.. code-block:: cpp
::

g++ -g -std=c++11 -o example -I./include -L./lib -lpdalcpp example.cpp


.. code-block:: cpp
#include <pdal/pdal.hpp>
#include <pdal/drivers/buffer/Reader.hpp>
#include <pdal/filters/Scaling.hpp>
#include <pdal/PointBuffer.hpp>
#include <pdal/drivers/las/Writer.hpp>
#include <vector>
Expand All @@ -72,10 +76,10 @@ available subject to having the required include directories pathed:
std::vector<Point> getMyData()
{
std::vector<Point> output;
Point p;
for (int i = 0; i < 1000; ++i)
{
p.x = -93.0 + i*0.001;
Expand All @@ -86,136 +90,48 @@ available subject to having the required include directories pathed:
return output;
}
pdal::PointBuffer* createBuffer()
{
pdal::Schema schema;
pdal::Dimension x("X", pdal::dimension::Float, 8);
pdal::Dimension y("Y", pdal::dimension::Float, 8);
pdal::Dimension z("Z", pdal::dimension::Float, 8);
x.setNamespace("myvector");
y.setNamespace("myvector");
z.setNamespace("myvector");
x.createUUID(); y.createUUID(); z.createUUID();
schema.appendDimension(x);
schema.appendDimension(y);
schema.appendDimension(z);
// 1000 is the capacity of the PointBuffer you wish to have
pdal::PointBuffer* output = new pdal::PointBuffer(schema, 1000);
return output;
}
void fillBuffer(pdal::PointBuffer* buffer, std::vector<Point> const& data)
void fillBuffer(pdal::PointBufferPtr buffer, std::vector<Point> const& data)
{
// You must fetch the buffer's schema & and get a reference
// to the X dimension. Some operation may have updated the
// buffer's schema
pdal::Dimension const& x = buffer->getSchema().getDimension("X");
pdal::Dimension const& y = buffer->getSchema().getDimension("Y");
pdal::Dimension const& z = buffer->getSchema().getDimension("Z");
for (int i = 0; i < data.size(); ++i)
{
// You must set the "raw" xyz values that have
// been descaled by the setNumericOffset and setNumericScale
// you provided when you created the dimensions and added
// them to the schema
Point const& pt = data[i];
buffer->setField<double>(x, i, pt.x);
buffer->setField<double>(y, i, pt.y);
buffer->setField<double>(z, i, pt.z);
buffer->setField<double>(pdal::Dimension::Id::X, i, pt.x);
buffer->setField<double>(pdal::Dimension::Id::Y, i, pt.y);
buffer->setField<double>(pdal::Dimension::Id::Z, i, pt.z);
}
buffer->setNumPoints(data.size());
}
pdal::Options getOptions()
{
pdal::Options opts;
pdal::Option scalex("scale", 0.001f, "fpscale");
pdal::Option offsetx("offset", 0.0f, "offset");
pdal::Option xdim("dimension", "X", "dimension to scale");
pdal::Option sizex("size", 4, "size");
pdal::Option typex("type", "SignedInteger", "tye");
pdal::Options xs;
xs.add(scalex);
xs.add(offsetx);
xs.add(sizex);
xs.add(typex);
xdim.setOptions(xs);
opts.add(xdim);
pdal::Option scaley("scale", 0.001f, "fpscale");
pdal::Option offsety("offset", 0.0f, "offset");
pdal::Option sizey("size", 4, "size");
pdal::Option typey("type", "SignedInteger", "tye");
pdal::Option ydim("dimension", "Y", "dimension to scale");
pdal::Options ys;
ys.add(scaley);
ys.add(offsety);
ys.add(sizey);
ys.add(typey);
ydim.setOptions(ys);
opts.add(ydim);
pdal::Option scalez("scale", 0.01f, "fpscale");
pdal::Option offsetz("offset", 0, "offset");
pdal::Option sizez("size", 4, "size");
pdal::Option typez("type", "SignedInteger", "tye");
pdal::Option zdim("dimension", "Z", "dimension to scale");
pdal::Options zs;
zs.add(scalez);
zs.add(offsetz);
zs.add(sizez);
zs.add(typez);
zdim.setOptions(zs);
opts.add(zdim);
return opts;
}
int main( int argc, const char* argv[] )
{
// No options are used for PointBuffer reader
pdal::Options options = getOptions();
pdal::Options options;
pdal::Option debug("debug", true, "");
pdal::Option verbose("verbose", 7, "");
// options.add(debug);
// options.add(verbose);
// options.add(verbose);
pdal::Option filename("filename", "myfile.las");
options.add(filename);
{
pdal::PointBuffer* buffer = createBuffer();
std::vector<Point> data = getMyData();
fillBuffer(buffer, data);
pdal::PointContextRef ctx;
ctx.registerDim(pdal::Dimension::Id::X);
ctx.registerDim(pdal::Dimension::Id::Y);
ctx.registerDim(pdal::Dimension::Id::Z);
pdal::drivers::buffer::Reader reader(options, *buffer);
pdal::filters::Scaling scaling(reader, options);
pdal::drivers::las::Writer writer(scaling, options);
{
pdal::PointBufferPtr buffer = pdal::PointBufferPtr(new pdal::PointBuffer(ctx));
std::vector<Point> data = getMyData();
writer.initialize();
writer.write(buffer->getNumPoints());
fillBuffer(buffer, data);
pdal::drivers::las::Writer writer(options);
writer.prepare(ctx);
writer.execute(ctx, buffer);
}
}
6 changes: 3 additions & 3 deletions include/pdal/Stage.hpp
Expand Up @@ -71,7 +71,7 @@ class PDAL_DLL Stage
{ m_inputs.push_back(input); }

void prepare(PointContextRef ctx);
PointBufferSet execute(PointContextRef ctx);
PointBufferSet execute(PointContextRef ctx, PointBufferPtr buffer=0);

void setSpatialReference(SpatialReference const&);
const SpatialReference& getSpatialReference() const;
Expand Down Expand Up @@ -99,7 +99,7 @@ class PDAL_DLL Stage
{ return Dimension::IdList(); }
static std::string s_getInfoLink()
{ return std::string(); }
virtual boost::property_tree::ptree toPTree(PointContextRef ctx) const
virtual boost::property_tree::ptree toPTree(PointContextRef ctx) const
{ return boost::property_tree::ptree(); }

#define SET_STAGE_NAME(name, description) \
Expand All @@ -118,7 +118,7 @@ class PDAL_DLL Stage

virtual StageSequentialIterator* createSequentialIterator() const
{ return NULL; }
inline MetadataNode getMetadata() const
inline MetadataNode getMetadata() const
{ return m_metadata; }

protected:
Expand Down
1 change: 0 additions & 1 deletion include/pdal/pdal.hpp
Expand Up @@ -38,6 +38,5 @@
#include <pdal/pdal_config.hpp>
#include <pdal/PointBuffer.hpp>
#include <pdal/StageFactory.hpp>
#include <pdal/StageIterator.hpp>

#endif
16 changes: 12 additions & 4 deletions src/Stage.cpp
Expand Up @@ -80,11 +80,19 @@ void Stage::prepare(PointContextRef ctx)
}


PointBufferSet Stage::execute(PointContextRef ctx)
PointBufferSet Stage::execute(PointContextRef ctx, PointBufferPtr buffer)
{
PointBufferSet buffers;
if (m_inputs.empty())
buffers.insert(PointBufferPtr(new PointBuffer(ctx)));
{
if (buffer)
{
buffers.insert(PointBufferPtr(buffer));
} else
{
buffers.insert(PointBufferPtr(new PointBuffer(ctx)));
}
}
else
{
for (size_t i = 0; i < m_inputs.size(); ++i)
Expand Down Expand Up @@ -206,7 +214,7 @@ std::vector<Stage*> Stage::findStage(std::string name)
std::vector<Stage*> output;
if (boost::iequals(getName(), name))
output.push_back(this);

for (auto s = m_inputs.begin(); s != m_inputs.end(); ++s)
{
Stage* stage = (*s);
Expand All @@ -219,7 +227,7 @@ std::vector<Stage*> Stage::findStage(std::string name)
output.insert(output.end(), hits.begin(), hits.end());
}
}

return output;
}

Expand Down

0 comments on commit c47d7c9

Please sign in to comment.