Merge pull request #238 from openscad/issue234

Issue234
felipesanches-svg
Marius Kintel 2013-01-21 16:38:48 -08:00
commit 2e65c6ddc5
1 changed files with 34 additions and 13 deletions

View File

@ -35,6 +35,28 @@
#include "stl-utils.h"
#include "printutils.h"
/*
Random numbers
Newer versions of boost/C++ include a non-deterministic random_device and
auto/bind()s for random function objects, but we are supporting older systems.
*/
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#ifdef __WIN32__
#include <process.h>
int process_id = _getpid();
#else
#include <sys/types.h>
#include <unistd.h>
int process_id = getpid();
#endif
boost::random::mt19937 deterministic_rng;
boost::random::mt19937 lessdeterministic_rng( std::time(0) + process_id );
AbstractFunction::~AbstractFunction()
{
}
@ -119,24 +141,15 @@ Value builtin_sign(const Context *, const std::vector<std::string>&, const std::
return Value();
}
double frand()
{
return rand()/(double(RAND_MAX)+1);
}
double frand(double min, double max)
{
return (min>max) ? frand()*(min-max)+max : frand()*(max-min)+min;
}
Value builtin_rands(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
bool deterministic = false;
if (args.size() == 3 &&
args[0].type() == Value::NUMBER &&
args[1].type() == Value::NUMBER &&
args[2].type() == Value::NUMBER)
{
srand((unsigned int)time(0));
deterministic = false;
}
else if (args.size() == 4 &&
args[0].type() == Value::NUMBER &&
@ -144,16 +157,24 @@ Value builtin_rands(const Context *, const std::vector<std::string>&, const std:
args[2].type() == Value::NUMBER &&
args[3].type() == Value::NUMBER)
{
srand((unsigned int)args[3].toDouble());
deterministic_rng.seed( (unsigned int) args[3].toDouble() );
deterministic = true;
}
else
{
return Value();
}
double min = std::min( args[0].toDouble(), args[1].toDouble() );
double max = std::max( args[0].toDouble(), args[1].toDouble() );
boost::random::uniform_real_distribution<> distributor( min, max );
Value::VectorType vec;
for (int i=0; i<args[2].toDouble(); i++) {
vec.push_back(Value(frand(args[0].toDouble(), args[1].toDouble())));
if ( deterministic ) {
vec.push_back( Value( distributor( deterministic_rng ) ) );
} else {
vec.push_back( Value( distributor( lessdeterministic_rng ) ) );
}
}
return Value(vec);