fixed issues with random walks
This commit is contained in:
94
math/stats/Histogram.h
Normal file
94
math/stats/Histogram.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#ifndef STATS_HISTOGRAM_H
|
||||||
|
#define STATS_HISTOGRAM_H
|
||||||
|
|
||||||
|
#define WITH_DEBUG_PLOT
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_PLOT
|
||||||
|
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||||
|
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
||||||
|
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Stats {
|
||||||
|
|
||||||
|
template <typename Scalar> class Histogram {
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_PLOT
|
||||||
|
K::Gnuplot gp;
|
||||||
|
K::GnuplotPlot plot;
|
||||||
|
K::GnuplotPlotElementLines lines;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Scalar min;
|
||||||
|
Scalar max;
|
||||||
|
int bins;
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
std::vector<Scalar> counts;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** ctor */
|
||||||
|
Histogram(Scalar min, Scalar max, int bins) : min(min), max(max), bins(bins) {
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_PLOT
|
||||||
|
plot.add(&lines);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int count() const {
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const Scalar x) {
|
||||||
|
const int idx = binIdx(x);
|
||||||
|
counts.at(idx) += 1;
|
||||||
|
++cnt;
|
||||||
|
if (cnt % 200 == 0) {showPlot();}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
counts.clear();
|
||||||
|
counts.resize(bins);
|
||||||
|
cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_PLOT
|
||||||
|
void showPlot() {
|
||||||
|
|
||||||
|
lines.clear();
|
||||||
|
|
||||||
|
lines.add(K::GnuplotPoint2(-1,0));
|
||||||
|
for (size_t idx = 0; idx < counts.size(); ++idx) {
|
||||||
|
const Scalar val = binValue(idx);
|
||||||
|
const Scalar sum = counts[idx];
|
||||||
|
const K::GnuplotPoint2 gp2(val, sum);
|
||||||
|
lines.add(gp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
gp.draw(plot);
|
||||||
|
gp.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int binIdx(const Scalar val) const {
|
||||||
|
return (val - min) / (max-min) * bins;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scalar binValue(const int idx) {
|
||||||
|
return idx * (max-min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STATS_HISTOGRAM_H
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "../math/DrawList.h"
|
#include "../math/DrawList.h"
|
||||||
#include "../geo/Point3.h"
|
#include "../geo/Point3.h"
|
||||||
#include "../misc/PerfCheck.h"
|
#include "../misc/PerfCheck.h"
|
||||||
|
#include "../math/stats/Histogram.h"
|
||||||
|
|
||||||
#include "NavMeshLocation.h"
|
#include "NavMeshLocation.h"
|
||||||
|
|
||||||
@@ -20,27 +21,22 @@ namespace NM {
|
|||||||
template <typename Tria> class NavMeshRandom {
|
template <typename Tria> class NavMeshRandom {
|
||||||
|
|
||||||
DrawList<size_t> lst;
|
DrawList<size_t> lst;
|
||||||
std::minstd_rand gen;
|
|
||||||
std::uniform_real_distribution<float> dOnTriangle = std::uniform_real_distribution<float>(0.0f, 1.0f);
|
std::uniform_real_distribution<float> dOnTriangle = std::uniform_real_distribution<float>(0.0f, 1.0f);
|
||||||
std::uniform_real_distribution<float> dHeading = std::uniform_real_distribution<float>(0, M_PI*2);
|
std::uniform_real_distribution<float> dHeading = std::uniform_real_distribution<float>(0, M_PI*2);
|
||||||
std::vector<const Tria*> triangles;
|
std::vector<const Tria*> triangles;
|
||||||
|
|
||||||
|
|
||||||
uint32_t nextSeed() {
|
uint32_t nextSeed() {
|
||||||
static uint32_t seed = 0;
|
static uint32_t seed = 0;
|
||||||
return ++seed;
|
return seed += 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** ctor (const/non-const using T) */
|
/** ctor (const/non-const using T) */
|
||||||
template <typename T> NavMeshRandom(const std::vector<T*>& srcTriangles) : lst(nextSeed()), gen(nextSeed()) {
|
template <typename T> NavMeshRandom(const std::vector<T*>& srcTriangles) : lst(nextSeed()) {
|
||||||
|
|
||||||
Assert::isFalse(srcTriangles.empty(), "no triangles given. mesh is empty");
|
Assert::isFalse(srcTriangles.empty(), "no triangles given. mesh is empty");
|
||||||
|
|
||||||
// 1st = almost always the same number?!
|
|
||||||
gen(); gen();
|
|
||||||
|
|
||||||
// construct a DrawList (probability = size[area] of the triangle
|
// construct a DrawList (probability = size[area] of the triangle
|
||||||
// bigger triangles must be choosen more often
|
// bigger triangles must be choosen more often
|
||||||
for (size_t idx = 0; idx < srcTriangles.size(); ++idx) {
|
for (size_t idx = 0; idx < srcTriangles.size(); ++idx) {
|
||||||
@@ -53,6 +49,9 @@ namespace NM {
|
|||||||
/** draw a random point */
|
/** draw a random point */
|
||||||
NavMeshLocation<Tria> draw() {
|
NavMeshLocation<Tria> draw() {
|
||||||
|
|
||||||
|
// re-use to provide stable random numbers!
|
||||||
|
static std::mt19937 gen;
|
||||||
|
|
||||||
PERF_REGION(3, "NavMeshRandom::draw()");
|
PERF_REGION(3, "NavMeshRandom::draw()");
|
||||||
|
|
||||||
// pick a random triangle to draw from
|
// pick a random triangle to draw from
|
||||||
@@ -63,6 +62,15 @@ namespace NM {
|
|||||||
float u = dOnTriangle(gen);
|
float u = dOnTriangle(gen);
|
||||||
float v = dOnTriangle(gen);
|
float v = dOnTriangle(gen);
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_PLOT_2
|
||||||
|
static Stats::Histogram<float> histU(0, 1, 200);
|
||||||
|
static Stats::Histogram<float> histV(0, 1, 200);
|
||||||
|
if (histU.count() > 200) {histU.showPlot(); histU.clear();}
|
||||||
|
if (histV.count() > 200) {histV.showPlot(); histV.clear();}
|
||||||
|
histU.add(u);
|
||||||
|
histV.add(v);
|
||||||
|
#endif
|
||||||
|
|
||||||
// if the (u,v) is outside of the triangle, mirror it so its inside the triangle again
|
// if the (u,v) is outside of the triangle, mirror it so its inside the triangle again
|
||||||
if ((u+v) > 1) {
|
if ((u+v) > 1) {
|
||||||
u = 1.0f - u;
|
u = 1.0f - u;
|
||||||
@@ -78,15 +86,25 @@ namespace NM {
|
|||||||
/** draw a random location within the given radius */
|
/** draw a random location within the given radius */
|
||||||
NavMeshLocation<Tria> drawWithin(const Point3 center, const float radius) {
|
NavMeshLocation<Tria> drawWithin(const Point3 center, const float radius) {
|
||||||
|
|
||||||
|
// re-use to provide stable random numbers!
|
||||||
|
static std::mt19937 gen;
|
||||||
|
|
||||||
std::uniform_real_distribution<float> dDistance(0.001, radius);
|
std::uniform_real_distribution<float> dDistance(0.001, radius);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|
||||||
const float head = dHeading(gen);
|
const float head = dHeading(gen);
|
||||||
const float dist = dDistance(gen);
|
const float dist = dDistance(gen);
|
||||||
|
|
||||||
const float ox = std::cos(head) * dist;
|
const float ox = std::cos(head) * dist;
|
||||||
const float oy = std::sin(head) * dist;
|
const float oy = std::sin(head) * dist;
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_PLOT_2
|
||||||
|
static Stats::Histogram<float> hist(0, 10, 200);
|
||||||
|
if (hist.count() > 1000) {hist.showPlot(); hist.clear();}
|
||||||
|
hist.add(dist);
|
||||||
|
#endif
|
||||||
|
|
||||||
// 2D destination (ignore z)
|
// 2D destination (ignore z)
|
||||||
const Point2 dst(center.x + ox, center.y + oy);
|
const Point2 dst(center.x + ox, center.y + oy);
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace NM {
|
|||||||
template <typename Tria> float inMeter(const int steps, const NavMeshLocation<Tria>& start) const {
|
template <typename Tria> float inMeter(const int steps, const NavMeshLocation<Tria>& start) const {
|
||||||
|
|
||||||
Assert::isTrue(isValid(), "invalid step-sizes given");
|
Assert::isTrue(isValid(), "invalid step-sizes given");
|
||||||
|
Assert::isNotNull(start.tria, "no starting triangle given");
|
||||||
|
|
||||||
if (start.tria->getType() == (int) NM::NavMeshType::STAIR_SKEWED) {
|
if (start.tria->getType() == (int) NM::NavMeshType::STAIR_SKEWED) {
|
||||||
return stepSizeStair_m * steps;
|
return stepSizeStair_m * steps;
|
||||||
|
|||||||
Reference in New Issue
Block a user