Skip to content

Commit

Permalink
Merge pull request #450 from chambbj/random-ctx
Browse files Browse the repository at this point in the history
add random kernel
  • Loading branch information
hobu committed Sep 12, 2014
2 parents 0f55da3 + ebe6bcb commit cd36bf8
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 3 deletions.
7 changes: 7 additions & 0 deletions apps/pdal.cpp
Expand Up @@ -54,6 +54,7 @@ void outputVersion()
std::cout << " - pcl" << std::endl;
#endif
std::cout << " - pipeline" << std::endl;
std::cout << " - random" << std::endl;
std::cout << " - translate" << std::endl;
std::cout << std::endl;
std::cout << "See http://pdal.io/apps.html for more detail";
Expand Down Expand Up @@ -150,6 +151,12 @@ int main(int argc, char* argv[])
pdal::kernel::Diff app(count, args);
return app.run();
}

if (boost::iequals(action, "random"))
{
pdal::kernel::Random app(count, args);
return app.run();
}

std::cerr << "Action '" << action <<"' not recognized" << std::endl << std::endl;
outputVersion();
Expand Down
2 changes: 2 additions & 0 deletions include/pdal/Utils.hpp
Expand Up @@ -57,6 +57,8 @@ class PDAL_DLL Utils
public:
static void random_seed(unsigned int seed);
static double random(double minimum, double maximum);
static double uniform(const double& minimum=0.0f, const double& maximum=1.0f, boost::uint32_t seed=0);
static double normal(const double& mean=0.0f, const double& sigma=1.0f, boost::uint32_t seed=0);

// compares two values to within the datatype's epsilon
template<class T>
Expand Down
15 changes: 13 additions & 2 deletions include/pdal/drivers/faux/Reader.hpp
Expand Up @@ -47,7 +47,9 @@ enum Mode
{
Constant,
Random,
Ramp
Ramp,
Uniform,
Normal
};


Expand All @@ -68,6 +70,10 @@ enum Mode
// bounding box
// - "ramp" generates its points as a linear ramp from the minimum of the
// bbox to the maximum
// - "uniform" generates points that are uniformly distributed within the
// given bounding box
// - "normal" generates points that are normally distributed with a given
// mean and standard deviation in each of the XYZ dimensions
// In all these modes, however, the Time field is always set to the point
// number.
//
Expand All @@ -77,7 +83,6 @@ enum Mode
//
class PDAL_DLL Reader : public pdal::Reader
{

public:
SET_STAGE_NAME("drivers.faux.reader", "Faux Reader")
SET_STAGE_ENABLED(true)
Expand All @@ -94,6 +99,12 @@ class PDAL_DLL Reader : public pdal::Reader
double m_maxY;
double m_minZ;
double m_maxZ;
double m_mean_x;
double m_mean_y;
double m_mean_z;
double m_stdev_x;
double m_stdev_y;
double m_stdev_z;
uint64_t m_time;
int m_numReturns;
int m_returnNum;
Expand Down
1 change: 1 addition & 0 deletions include/pdal/kernel/Kernel.hpp
Expand Up @@ -45,6 +45,7 @@
#endif
#include "Pipeline.hpp"
#include "Delta.hpp"
#include "Random.hpp"
#include "Translate.hpp"
#include "Diff.hpp"

Expand Down
82 changes: 82 additions & 0 deletions include/pdal/kernel/Random.hpp
@@ -0,0 +1,82 @@
/******************************************************************************
* Copyright (c) 2014, Brad Chambers (brad.chambers@gmail.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#ifndef INCLUDED_PDAL_KERNEL_RANDOM_HPP
#define INCLUDED_PDAL_KERNEL_RANDOM_HPP

#include <pdal/FileUtils.hpp>

#include <pdal/drivers/faux/Reader.hpp>
#include <pdal/drivers/las/Writer.hpp>

#include <pdal/Bounds.hpp>

#include "Application.hpp"

#define SEPARATORS ",| "

#include <boost/tokenizer.hpp>
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;

namespace pdal
{
namespace kernel
{

class PDAL_DLL Random : public Application
{
public:
Random(int argc, const char* argv[]);
int execute();

private:
void addSwitches();
void validateSwitches();

Stage* makeReader(Options readerOptions);

std::string m_outputFile;
bool m_bCompress;
boost::uint64_t m_numPointsToWrite;
pdal::Bounds<double> m_bounds;
std::string m_distribution;
std::string m_means;
std::string m_stdevs;
};

} // kernel
} // pdal

#endif

2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Expand Up @@ -690,6 +690,7 @@ set(PDAL_KERNEL_HPP
${PDAL_KERNEL_HEADERS}/Kernel.hpp
${PDAL_KERNEL_HEADERS}/Pipeline.hpp
${PDAL_KERNEL_HEADERS}/Delta.hpp
${PDAL_KERNEL_HEADERS}/Random.hpp
${PDAL_KERNEL_HEADERS}/Translate.hpp
)

Expand All @@ -700,6 +701,7 @@ set(PDAL_KERNEL_CPP
${PDAL_KERNEL_SRC}/Info.cpp
${PDAL_KERNEL_SRC}/Pipeline.cpp
${PDAL_KERNEL_SRC}/Delta.cpp
${PDAL_KERNEL_SRC}/Random.cpp
${PDAL_KERNEL_SRC}/Translate.cpp
)

Expand Down
19 changes: 19 additions & 0 deletions src/Utils.cpp
Expand Up @@ -34,6 +34,9 @@

#include <boost/algorithm/string/erase.hpp>
#include <boost/filesystem.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/normal_distribution.hpp>

#include <pdal/Utils.hpp>

Expand Down Expand Up @@ -84,6 +87,22 @@ double Utils::random(double minimum, double maximum)
return t;
}

double Utils::uniform(const double& minimum, const double& maximum, boost::uint32_t seed)
{
boost::random::mt19937 gen(seed);
boost::random::uniform_real_distribution<double> dist(minimum, maximum);

return dist(gen);
}

double Utils::normal(const double& mean, const double& sigma, boost::uint32_t seed)
{
boost::random::mt19937 gen(seed);
boost::random::normal_distribution<double> dist(mean, sigma);

return dist(gen);
}

void* Utils::registerPlugin(void* stageFactoryPtr, string const& filename,
string const& registerMethod, string const& versionMethod)
{
Expand Down
30 changes: 29 additions & 1 deletion src/drivers/faux/Reader.cpp
Expand Up @@ -34,6 +34,8 @@

#include <pdal/drivers/faux/Reader.hpp>

#include <ctime>

#include <pdal/PointBuffer.hpp>

#include <boost/algorithm/string.hpp>
Expand All @@ -50,6 +52,8 @@ static Mode string2mode(const std::string& str)
if (boost::iequals(str, "constant")) return Constant;
if (boost::iequals(str, "random")) return Random;
if (boost::iequals(str, "ramp")) return Ramp;
if (boost::iequals(str, "uniform")) return Uniform;
if (boost::iequals(str, "normal")) return Normal;
throw pdal_error("invalid Mode option: " + str);
}

Expand All @@ -63,7 +67,7 @@ Reader::Reader(const Options& options)

void Reader::processOptions(const Options& options)
{
Bounds<double> bounds = options.getValueOrThrow<Bounds<double>>("bounds");
Bounds<double> bounds = options.getValueOrDefault<Bounds<double>>("bounds",Bounds<double>(0,0,0,1,1,1));
const std::vector<Range<double>>& ranges = bounds.dimensions();
m_minX = ranges[0].getMinimum();
m_maxX = ranges[0].getMaximum();
Expand All @@ -75,6 +79,13 @@ void Reader::processOptions(const Options& options)
// For backward compatibility.
if (m_count == 0)
m_count = options.getValueOrThrow<point_count_t>("num_points");

m_mean_x = options.getValueOrDefault<double>("mean_x",0.0);
m_mean_y = options.getValueOrDefault<double>("mean_y",0.0);
m_mean_z = options.getValueOrDefault<double>("mean_z",0.0);
m_stdev_x = options.getValueOrDefault<double>("stdev_x",1.0);
m_stdev_y = options.getValueOrDefault<double>("stdev_y",1.0);
m_stdev_z = options.getValueOrDefault<double>("stdev_z",1.0);
m_mode = string2mode(options.getValueOrThrow<std::string>("mode"));
m_numReturns = options.getValueOrDefault("number_of_returns", 0);
if (m_numReturns > 10)
Expand Down Expand Up @@ -115,6 +126,10 @@ point_count_t Reader::read(PointBuffer& buf, point_count_t count)
log()->get(LogLevel::Debug5) << "Reading a point buffer of " <<
count << " points." << std::endl;

boost::uint64_t time = count;

boost::uint32_t seed = static_cast<boost::uint32_t>(std::time(NULL));

for (PointId idx = 0; idx < count; ++idx)
{
double x;
Expand All @@ -137,6 +152,19 @@ point_count_t Reader::read(PointBuffer& buf, point_count_t count)
y = m_minY + delY * idx;
z = m_minZ + delZ * idx;
break;
case Uniform:
x = Utils::uniform(m_minX, m_maxX, seed++);
y = Utils::uniform(m_minY, m_maxY, seed++);
z = Utils::uniform(m_minZ, m_maxZ, seed++);
break;
case Normal:
x = Utils::normal(m_mean_x, m_stdev_x, seed++);
y = Utils::normal(m_mean_y, m_stdev_y, seed++);
z = Utils::normal(m_mean_z, m_stdev_z, seed++);
break;
default:
throw pdal_error("invalid mode in FauxReader");
break;
}

buf.setField(Dimension::Id::X, idx, x);
Expand Down

0 comments on commit cd36bf8

Please sign in to comment.