# Writing with PDAL

Author: | Bradley Chambers
Contact: | brad.chambers@gmail.com
Date: | 01/21/2015

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 reader stage.

Note

If you implement your own Readers that conforms to PDAL’s `pdal::Stage`, you can implement a simple read-filter-write pipeline using Pipeline and not have to code anything explicit yourself.

## Includes

First, our code.

    #include <pdal/PointView.hpp>
    #include <pdal/PointTable.hpp>
    #include <pdal/Dimension.hpp>
    #include <pdal/Options.hpp>
    #include <pdal/StageFactory.hpp>

    #include <io/BufferReader.hpp>

    #include <vector>

    void fillView(pdal::PointViewPtr view)
    {
        struct Point
        {
            double x;
            double y;
            double z;
        };

        for (int i = 0; i < 1000; ++i)
        {
            Point p;

            p.x = -93.0 + i*0.001;
            p.y = 42.0 + i*0.001;
            p.z = 106.0 + i;

            view->setField(pdal::Dimension::Id::X, i, p.x);
            view->setField(pdal::Dimension::Id::Y, i, p.y);
            view->setField(pdal::Dimension::Id::Z, i, p.z);
        }
    }

    int main(int argc, char* argv[])
    {
        using namespace pdal;

        Options options;
        options.add("filename", "myfile.las");

        PointTable table;
        table.layout()->registerDim(Dimension::Id::X);
        table.layout()->registerDim(Dimension::Id::Y);
        table.layout()->registerDim(Dimension::Id::Z);

        PointViewPtr view(new PointView(table));

        fillView(view);

        BufferReader reader;
        reader.addView(view);

        StageFactory factory;

        // Set second argument to 'true' to let factory take ownership of
        // stage and facilitate clean up.
        Stage *writer = factory.createStage("writers.las");

        writer->setInput(reader);
        writer->setOptions(options);
        writer->prepare(table);
        writer->execute(table);
    }

Take a closer look. We will need to include several PDAL headers.

    #include <pdal/PointView.hpp>
    #include <pdal/PointTable.hpp>
    #include <pdal/Dimension.hpp>
    #include <pdal/Options.hpp>
    #include <pdal/StageFactory.hpp>

    #include <io/BufferReader.hpp>

BufferReader will not be required by all users. Here is it used to populate a bare PointBuffer. This will often be accomplished by a Reader stage.

Instead of directly including headers for individual stages, e.g., LasWriter, we rely on the StageFactory which has the ability to query available stages at runtime and return pointers to the created stages.

We proceed by providing a mechanism for generating dummy data for the x, y, and z dimensions.

    void fillView(pdal::PointViewPtr view)
    {
        struct Point
        {
            double x;
            double y;
            double z;
        };

        for (int i = 0; i < 1000; ++i)
        {
            Point p;

            p.x = -93.0 + i*0.001;
            p.y = 42.0 + i*0.001;
            p.z = 106.0 + i;

            view->setField(pdal::Dimension::Id::X, i, p.x);
            view->setField(pdal::Dimension::Id::Y, i, p.y);
            view->setField(pdal::Dimension::Id::Z, i, p.z);

    int main(int argc, char* argv[])
    {
        using namespace pdal;

        Options options;
        options.add("filename", "myfile.las");

        PointTable table;

Finally, the main code which creates the dummy data, puts it into a BufferReader and sends it to a writer.

        table.layout()->registerDim(Dimension::Id::Z);

        PointViewPtr view(new PointView(table));

        fillView(view);

        BufferReader reader;
        reader.addView(view);

        StageFactory factory;

        // Set second argument to 'true' to let factory take ownership of
        // stage and facilitate clean up.
        Stage *writer = factory.createStage("writers.las");

        writer->setInput(reader);
        writer->setOptions(options);
        writer->prepare(table);
        writer->execute(table);
    }

## Compiling and running the program

Note

Refer to Compilation for information on how to build PDAL.

To build this example, simply copy the files tutorial.cpp and CMakeLists.txt from the examples/writing directory of the PDAL source tree.

    cmake_minimum_required(VERSION 2.8.12)
    project(WritingTutorial)

    find_package(PDAL 1.0.0 REQUIRED CONFIG)

    set(CMAKE_CXX_FLAGS "-std=c++11")
    add_executable(tutorial tutorial.cpp)
    target_link_libraries(tutorial PRIVATE ${PDAL_LIBRARIES})
    target_include_directories(tutorial PRIVATE
        ${PDAL_INCLUDE_DIRS}
        ${PDAL_INCLUDE_DIRS}/pdal)

Note

Refer to Using PDAL with CMake for an explanation of the basic CMakeLists.

Begin by configuring your project using CMake (shown here on Unix) and building using make.

    $ cd /PATH/TO/WRITING/TUTORIAL
    $ mkdir build
    $ cd build
    $ cmake ..
    $ make

After the project is built, you can run it by typing:

    $ ./tutorial