Skip to content

Commit

Permalink
Start swapping the math of calculating the mesh over to using n directly
Browse files Browse the repository at this point in the history
  • Loading branch information
TrentHouliston committed Jul 16, 2019
1 parent 67868d1 commit 414d59e
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 113 deletions.
7 changes: 4 additions & 3 deletions example/main.cpp
Expand Up @@ -15,6 +15,7 @@
#include "Timer.hpp"
#include "engine/opencl/opencl_engine.hpp"
#include "geometry/Sphere.hpp"
#include "mesh/test_mesh.hpp"
#include "util/fourcc.hpp"
#include "visualmesh.hpp"

Expand Down Expand Up @@ -57,9 +58,9 @@ int main() {

// Construct our VisualMesh
Timer t;
visualmesh::geometry::Sphere<float> sphere(0.0949996, 6, 20);
visualmesh::VisualMesh<float, visualmesh::engine::opencl::Engine> cl_mesh(sphere, 0.5, 1.5, 100);
visualmesh::VisualMesh<float, visualmesh::engine::cpu::Engine> cpu_mesh(sphere, 0.5, 1.5, 100);
visualmesh::geometry::Sphere<float> sphere(0.0949996);
visualmesh::VisualMesh<float, visualmesh::engine::opencl::Engine> cl_mesh(sphere, 0.5, 1.5, 100, 6, 20);
visualmesh::VisualMesh<float, visualmesh::engine::cpu::Engine> cpu_mesh(sphere, 0.5, 1.5, 100, 6, 20);
t.measure("Built Visual Mesh");

// Build our classification network
Expand Down
61 changes: 20 additions & 41 deletions src/geometry/Circle.hpp
Expand Up @@ -34,34 +34,30 @@ namespace geometry {
* @param intersections the number of intersections to ensure with this object
* @param max_distance the maximum distance we want to look for this object
*/
Circle(const Scalar& radius, const unsigned int& intersections, const Scalar& max_distance)
: r(radius), k(intersections), d(max_distance) {}
Circle(const Scalar& radius) : r(radius) {}

/**
* @brief Given a value for phi and a camera height, return the value to the next phi in the sequence.
* @brief Given a number of radial jumps (n) give the phi angle required
*
* @param phi_n the current phi value in the series
* @param h the height of the camera above the observation plane
*
* @return the next phi in the sequence (phi_{n+1})
* @param n the number of whole objects to jump from the origin to reach this point (from object centres)
* @param h the height of the camera above the observation plane
*/
Scalar phi(const Scalar& phi_n, const Scalar& h) const {

// If we are beyond our max distance return nan
if (std::abs(h) * std::tan(phi_n > M_PI_2 ? M_PI - phi_n : phi_n) > d) {
return std::numeric_limits<Scalar>::quiet_NaN();
}
Scalar phi(const Scalar& n, const Scalar& h) const {
return std::atan((2.0 * n * r) / h);
}

// Below the horizon with positive height
if (h > 0 && phi_n < M_PI_2) { return std::atan((2 * r / k + h * std::tan(phi_n)) / h); }
// Above the horizon with negative height
else if (h < 0 && phi_n > M_PI_2) {
return M_PI - phi(phi_n, -h);
}
// Other situations are invalid so return NaN
else {
return std::numeric_limits<Scalar>::quiet_NaN();
}
/**
* @brief Given a phi angle calculate how many object jumps from the origin are required to reach this location
*
* @details
* This equation can also be used to calculate the n difference between any two objects by calculating the
* augmented height above the ground h' and the two φ' angles and using those in this equation instead of the real
* values
*
* @param phi the phi angle measured from below the camera
*/
Scalar n(const Scalar& phi, const Scalar& h) const {
return (h * std::tan(phi)) / (2.0 * r);
}

/**
Expand All @@ -73,28 +69,11 @@ namespace geometry {
* @return the angular width of the object around a phi circle
*/
Scalar theta(const Scalar& phi, const Scalar& h) const {

// If we are beyond our max distance return nan
if (std::abs(h) * tan(phi > M_PI_2 ? M_PI - phi : phi) > d) { return std::numeric_limits<Scalar>::quiet_NaN(); }

// Below the horizon with positive height
if (h > 0 && phi < M_PI_2) { return 2 * std::asin(r / (h * std::tan(phi) + r)) / k; }
// Above the horizon with negative height
else if (h < 0 && phi > M_PI_2) {
return theta(M_PI - phi, -h);
}
// Other situations are invalid so return NaN
else {
return std::numeric_limits<Scalar>::quiet_NaN();
}
return 2.0 * std::asin(r / (h * std::tan(phi)));
}

// The radius of the circle
Scalar r;
// The number of intersections the mesh should have with this circle
unsigned int k;
/// The maximum distance we want to see this object
Scalar d;
};

} // namespace geometry
Expand Down
18 changes: 3 additions & 15 deletions src/geometry/Cylinder.hpp
Expand Up @@ -35,11 +35,7 @@ namespace geometry {
* @param intersections the number of intersections to ensure with a spherical section of the cylinder
* @param max_distance the maximum distance we want to look for this object
*/
Cylinder(const Scalar& cylinder_height,
const Scalar& radius,
const unsigned int& intersections,
const Scalar& max_distance)
: sphere(radius, intersections, max_distance), ch(cylinder_height) {}
Cylinder(const Scalar& cylinder_height, const Scalar& radius) : sphere(radius), ch(cylinder_height) {}

/**
* @brief Given a value for phi and a camera height, return the value to the next phi in the sequence.
Expand All @@ -50,19 +46,11 @@ namespace geometry {
* @return the next phi in the sequence (phi_{n+1})
*/
Scalar phi(const Scalar& phi_n, const Scalar& h) const {
// Calculate if either of our spheres are valid

// Get values from the upper and lower observation planes
Scalar u = sphere.phi(phi_n, h - ch);
Scalar l = sphere.phi(phi_n, h);

// If one is nan return the other one
if (std::isnan(u)) {
// If both are nan this will return nan here
return l;
}
else {
// If l is nan return u, otherwise return the smallest change
return std::isnan(l) ? u : std::abs(u - phi_n) < std::abs(l - phi_n) ? u : l;
}
}

/**
Expand Down
82 changes: 36 additions & 46 deletions src/geometry/Sphere.hpp
Expand Up @@ -34,38 +34,47 @@ namespace geometry {
* @param intersections the number of intersections to ensure with this object
* @param max_distance the maximum distance we want to look for this object
*/
Sphere(const Scalar& radius, const Scalar& intersections, const Scalar& max_distance)
: r(radius), k(intersections), d(max_distance) {}
Sphere(const Scalar& radius) : r(radius) {}

/**
* @brief Given a value for phi and a camera height, return the value to the next phi in the sequence.
* @brief Given a number of radial jumps (n) give the phi angle required
*
* @param phi_n the current phi value in the series
* @param h the height of the camera above the observation plane
* @details
* To calculate the angle to the base of the object we can use the following equation
*
* @return the next phi in the sequence (phi_{n+1})
* ⎛ n⎞
* π -1 ⎜⎛ 2⋅r⎞ ⎟
* φ(n) = ─ - 2⋅tan ⎜⎜1 - ───⎟ ⎟
* 2 ⎝⎝ h ⎠ ⎠
*
* Then to get the equation for the centre of the sphere, we calculate given the average angle of n ± 0.5
*
* @param n the number of whole objects to jump from the origin to reach this point (from object centres)
* @param h the height of the camera above the observation plane
*/
Scalar phi(const Scalar& phi_n, const Scalar& h) const {

// If we are beyond our max distance return nan
if (std::abs(h) * std::tan(phi_n > M_PI_2 ? M_PI - phi_n : phi_n) > d) {
return std::numeric_limits<Scalar>::quiet_NaN();
}
Scalar phi(const Scalar& n, const Scalar& h) const {
Scalar v = 1 - 2 * r / h;
return M_PI_2 - std::atan(pow(v, n - 0.5)) - std::atan(std::pow(v, n + 0.5));
}

// Below the horizon with positive height
if (h > 0 && phi_n < M_PI_2) {
// Our effective radius for the number of intersections
Scalar er = (h / 2) * (1 - std::pow(1 - 2 * r / h, 1 / k));
return 2 * std::atan(er / (std::cos(phi_n) * (h - er)) + std::tan(phi_n)) - phi_n;
}
// Above the horizon with negative height
else if (h < 0 && phi_n > M_PI_2) {
return M_PI - phi(M_PI - phi_n, -h);
}
// Other situations are invalid so return NaN
else {
return std::numeric_limits<Scalar>::quiet_NaN();
}
/**
* @brief Given a phi angle calculate how many object jumps from the origin are required to reach this location
*
* @details
* This equation can also be used to calculate the n difference between any two objects by calculating the
* augmented height above the ground h' and the two φ' angles and using those in this equation instead of the real
* values
*
* ⎛ ⎛φ π⎞⎞
* log⎜cot⎜─ + ─⎟⎟
* ⎝ ⎝2 4⎠⎠
* ─────────────────────
* log(h - 2⋅r) - log(h)
*
* @param phi the phi angle measured from below the camera
*/
Scalar n(const Scalar& phi, const Scalar& h) const {
return std::log(1 / std::tan(phi * 0.5 + M_PI_4)) / (std::log(h - 2 * r) - log(h));
}

/**
Expand All @@ -77,30 +86,11 @@ namespace geometry {
* @return the angular width of the object around a phi circle
*/
Scalar theta(const Scalar& phi, const Scalar& h) const {

// If we are beyond our max distance return nan
if (std::abs(h) * std::tan(phi > M_PI_2 ? M_PI - phi : phi) > d) {
return std::numeric_limits<Scalar>::quiet_NaN();
}

// Below the horizon with positive height
if (h > 0 && phi < M_PI_2) { return 2 * std::asin(r / ((h - r) * std::tan(phi))) / k; }
// Above the horizon with negative height
else if (h < 0 && phi > M_PI_2) {
return theta(M_PI - phi, -h);
}
// Other situations are invalid so return NaN
else {
return std::numeric_limits<Scalar>::quiet_NaN();
}
return 2 * std::asin(r / ((h - r) * std::tan(phi)));
}

// The radius of the sphere
Scalar r;
// The number of intersections the mesh should have with this sphere
Scalar k;
/// The maximum distance we want to see this object
Scalar d;
};

} // namespace geometry
Expand Down
12 changes: 6 additions & 6 deletions src/tf_op.cpp
Expand Up @@ -100,18 +100,18 @@ class VisualMeshOp : public tensorflow::OpKernel {
visualmesh::engine::cpu::Engine<T> engine;
visualmesh::ProjectedMesh<T> projected;
if (geometry == "SPHERE") {
visualmesh::geometry::Sphere<T> shape(g_params(0), g_params(1), g_params(2));
visualmesh::Mesh<T> mesh(shape, height);
visualmesh::geometry::Sphere<T> shape(g_params(0));
visualmesh::Mesh<T> mesh(shape, height, g_params(1), g_params(2));
projected = engine.project(mesh, mesh.lookup(Hoc, lens), Hoc, lens);
}
else if (geometry == "CIRCLE") {
visualmesh::geometry::Circle<T> shape(g_params(0), g_params(1), g_params(2));
visualmesh::Mesh<T> mesh(shape, height);
visualmesh::geometry::Circle<T> shape(g_params(0));
visualmesh::Mesh<T> mesh(shape, height, g_params(1), g_params(2));
projected = engine.project(mesh, mesh.lookup(Hoc, lens), Hoc, lens);
}
else if (geometry == "CYLINDER") {
visualmesh::geometry::Cylinder<T> shape(g_params(0), g_params(1), g_params(2), g_params(3));
visualmesh::Mesh<T> mesh(shape, height);
visualmesh::geometry::Cylinder<T> shape(g_params(0), g_params(1));
visualmesh::Mesh<T> mesh(shape, height, g_params(2), g_params(3));
projected = engine.project(mesh, mesh.lookup(Hoc, lens), Hoc, lens);
}
else {
Expand Down
9 changes: 7 additions & 2 deletions src/visualmesh.hpp
Expand Up @@ -51,13 +51,18 @@ class VisualMesh {
* @param n_heights the number of look up tables to generated (height gradations)
*/
template <typename Shape>
explicit VisualMesh(const Shape& shape, const Scalar& min_height, const Scalar& max_height, const uint& n_heights) {
explicit VisualMesh(const Shape& shape,
const Scalar& min_height,
const Scalar& max_height,
const uint& n_heights,
const Scalar& k,
const Scalar& max_distance) {

// Loop through to make a mesh for each of our height possibilities
for (Scalar h = min_height; h < max_height; h += (max_height - min_height) / n_heights) {

// Insert our constructed mesh into the lookup
luts.insert(std::make_pair(h, Mesh<Scalar>(shape, h)));
luts.insert(std::make_pair(h, Mesh<Scalar>(shape, h, k, max_distance)));
}
}

Expand Down

0 comments on commit 414d59e

Please sign in to comment.