Skip to content

Commit

Permalink
Update example text and fix line numbers.
Browse files Browse the repository at this point in the history
  • Loading branch information
abellgithub committed Mar 22, 2018
1 parent c40f455 commit ade9555
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 151 deletions.
34 changes: 3 additions & 31 deletions doc/development/writing-filter.rst
Expand Up @@ -73,16 +73,14 @@ PDAL requires that filter names always begin with ``filters.``, and end with a
string that uniquely identifies the filter. The description will be displayed
to users of the PDAL CLI (``pdal --drivers``).

Next, we pass the following to the ``CREATE_STATIC_PLUGIN`` macro, in order:
PDAL plugin ABI major version, PDAL plugin ABI minor version, filter class
name, stage type (``Filter``), and our ``PluginInfo`` struct.
Next, we pass the following to the ``CREATE_STATIC_STAGE`` macro, passin in the name of the stage and the ``PluginInfo`` struct.

.. literalinclude:: ../../examples/writing-filter/MyFilter.cpp
:language: cpp
:lines: 19

To create a shared plugin, we simply change ``CREATE_STATIC_PLUGIN`` to
``CREATE_SHARED_PLUGIN``.
To create a shared stage, we simply change ``CREATE_STATIC_STAGE`` to
``CREATE_SHARED_STAGE``.

Finally, we implement a method to get the plugin name, which is primarily used
by the PDAL CLI when using the ``--drivers`` or ``--options`` arguments.
Expand Down Expand Up @@ -130,32 +128,6 @@ points.
We suggest you take a closer look at our existing filters to get an idea of the
power of the ``Filter`` stage and inspiration for your own filters!

StageFactory
...............................................................................

As of this writing, users must also make a couple of changes to
``StageFactory.cpp`` to properly register static plugins only (this is not
required for shared plugins). It is our goal to eventually remove this
requirement to further streamline development of add-on plugins.

.. note::

Modification of StageFactory is required for STATIC plugins only.
Dynamic plugins are registered at runtime.

First, add the following line to the beginning of ``StageFactory.cpp``
(adjusting the path and filename as necessary).

.. code-block:: cpp
#include <MyFilter.hpp>
Next, add the following line of code to the ``StageFactory`` constructor.

.. code-block:: cpp
PluginManager::initializePlugin(MyFilter_InitPlugin);

Compilation
...............................................................................
Expand Down
63 changes: 14 additions & 49 deletions doc/development/writing-kernel.rst
Expand Up @@ -21,12 +21,11 @@ First, we provide a full listing of the kernel header.
:language: cpp
:linenos:

As with other plugins, the MyKernel class needs to have the following three
methods declared for the plugin interface to be satisfied:
As with other plugins, the MyKernel class needs to return a name.

.. literalinclude:: ../../examples/writing-kernel/MyKernel.hpp
:language: cpp
:lines: 16-18
:lines: 17


The source
Expand All @@ -39,67 +38,33 @@ Again, we start with a full listing of the kernel source.
:linenos:

In your kernel implementation, you will use a macro defined in pdal_macros.
This macro registers the plugin with the Kernel factory. It is
only required by plugins.
This macro registers the plugin with the PluginManager.

.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp
:language: cpp
:lines: 25-26

.. note::

A static plugin macro can also be used to integrate the kernel with the
main code. This will not be described here. Using this as a shared plugin
will be described later.
:lines: 23

To build up a processing pipeline in this example, we need to create two
objects: the :cpp:class:`pdal::PointTable` and the
:cpp:class:`pdal::StageFactory`. The latter is used to create the various
stages that will be used within the kernel.

.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp
:language: cpp
:lines: 39-40

The :cpp:class:`pdal::Reader` is created from the
:cpp:class:`pdal::StageFactory`, and is specified by the stage name, in this
case an LAS reader. For brevity, we provide the reader a single option, the
filename of the file to be read.

.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp
:language: cpp
:lines: 42-45

The :cpp:class:`pdal::Filter` is also created from the
:cpp:class:`pdal::StageFactory`. Here, we create a decimation filter that will
pass every tenth point to subsequent stages. We also specify the input to this
stage, which is the reader.

.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp
:language: cpp
:lines: 47-51

Finally, the :cpp:class:`pdal::Writer` is created from the
:cpp:class:`pdal::StageFactory`. This :ref:`writers.text`, takes as input the previous
stage (the :ref:`filters.decimation`) and the output filename as its sole option.
objects: the :cpp:class:`pdal::PointTable`.

.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp
:language: cpp
:lines: 53-57
:lines: 35-53

The final two steps are to prepare and execute the pipeline. This is achieved
by calling prepare and execute on the final stage.
To implement the actual kernel logic we implement execute(). In this case,
the kernel reads a las file, decimates the data (eliminates some points) and
writes the result to a text file. The base kernel class provides functions
(makeReader, makeFilter, makeWriter) to create stages with options as desired.
The pipeline that has been created can be run by preparing and executing the
last stage in the pipeline.

.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp
:language: cpp
:lines: 58-59

When compiled, a dynamic library file will be created; in this case,
``libpdal_plugin_kernel_mykernel.dylib``

Put this file in whatever directory ``PDAL_DRIVER_PATH`` is pointing to. Then,
if you run ``pdal --help``, you should see ``mykernel`` listed in the possible
commands.
if you run ``pdal --drivers``, you should see ``mykernel`` listed in the
possible commands.

To run this kernel, you would use ``pdal mykernel -i <input las file> -o
<output text file>``.
Expand Down
71 changes: 30 additions & 41 deletions doc/development/writing-reader.rst
Expand Up @@ -21,19 +21,9 @@ First, we provide a full listing of the reader header.
:language: cpp
:linenos:

In your MyReader class, you will declare the necessary methods and variables
needed to make the reader work and meet the plugin specifications.

.. literalinclude:: ../../examples/writing-reader/MyReader.hpp
:language: cpp
:lines: 16-18
:linenos:

These methods are required to fulfill the specs for defining a new plugin.

.. literalinclude:: ../../examples/writing-reader/MyReader.hpp
:language: cpp
:lines: 21-23
:lines:18-20
:linenos:

``m_stream`` is used to process the input, while ``m_index`` is used to track
Expand All @@ -42,7 +32,7 @@ be described later.

.. literalinclude:: ../../examples/writing-reader/MyReader.hpp
:language: cpp
:lines: 27-31
:lines: 22-26
:linenos:

Various other override methods for the stage. There are a few others that
Expand All @@ -62,26 +52,17 @@ Again, we start with a full listing of the reader source.
:language: cpp
:linenos:

In your reader implementation, you will use a macro defined in pdal_macros.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 9-12
:linenos:

This macro registers the plugin with the PDAL code. In this case, we are
declaring this as a SHARED plugin, meaning that it will be located external
to the main PDAL installation. The macro is supplied with a version number
(major and minor), the class of the plugin, the parent class (in this case,
to identify it as a reader), and an object with information. This information
includes the name of the plugin, a description, and a link to documentation.

Creating STATIC plugins requires a few more steps which will not be covered
in this tutorial.
In your reader implementation, you will use a macro to create the plugin.
This macro registers the plugin with the PDAL PluginManager. In this case,
we are declaring this as a SHARED stage, meaning that it will be loaded at
runtime instead of being linked
to the main PDAL installation. The macro is supplied with the class name
of the plugin and a PluginInfo object. The PluginInfo objection includes
the name of the plugin, a description, and a link to documentation.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 18-21
:lines: 8-15
:linenos:

This method will process a options for the reader. In this
Expand All @@ -94,7 +75,7 @@ stage.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 23-29
:lines: 19-22
:linenos:

This method registers the various dimensions the reader will use. In our case,
Expand All @@ -103,7 +84,7 @@ dimension MyData.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 31-35
:lines: 24-30
:linenos:

This method is called when the Reader is ready for use. It will only be
Expand All @@ -112,21 +93,20 @@ processed.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 37-50
:lines: 32-36
:linenos:

This is a helper function, which will convert a string value into the type
specified when it's called. In our example, it will be used to convert
strings to doubles when reading from the input stream.


.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 53
:lines: 38-52
:linenos:

This method is the main processing method for the reader. It takes a
pointer to a Point View which we will build as we read from the file. We
pointer to a PointView which we will build as we read from the file. We
initialize some variables as well, and then reset the input stream with
the filename used for the reader. Note that in other readers, the contents
of this method could be very different depending on the format of the file
Expand All @@ -135,34 +115,33 @@ PointView object.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 62-64
:lines: 57-62
:linenos:

In preparation for reading the file, we prepare to skip some header lines. In
our case, the header is only a single line.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 65-70
:lines: 64-66
:linenos:

Here we begin our main loop. In our example file, the first line is a header,
and each line thereafter is a single point. If the file had a different format
the method of looping and reading would have to change as appropriate. We make
sure we are skipping the header lines here before moving on.


.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 73-82
:lines: 67-72
:linenos:

Here we take the line we read in the for block header, split it, and make sure
that we have the proper number of fields.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 84-97
:lines: 75-84
:linenos:

Here we take the values we read and put them into the PointView object. The
Expand All @@ -177,7 +156,7 @@ each iteration of the loop), and the dimension value.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 99-101
:lines: 86-99
:linenos:

Finally, we increment the nextId and make a call into the progress callback
Expand All @@ -186,9 +165,19 @@ and number read, and return that value as the number of points read.
This could differ in cases where we read multiple streams, but that won't
be covered here.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 101-108
:linenos:

When the read method is finished, the done method is called for any cleanup.
In this case, we simply make sure the stream is reset.

.. literalinclude:: ../../examples/writing-reader/MyReader.cpp
:language: cpp
:lines: 111-114
:linenos:


Compiling and Usage
-------------------------------------------------------------------------------
Expand Down

0 comments on commit ade9555

Please sign in to comment.