Commit ac9e89dc authored by Philip Trettner's avatar Philip Trettner
Browse files

Merge branch 'agrabowy' into 'develop'

intersects aabb

See merge request !104
parents cd349b55 3ba10c66
......@@ -134,6 +134,7 @@ template <class ScalarT, class TraitsT>
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr pos<1, ScalarT> caps_of(hemisphere<1, ScalarT, TraitsT> const& v)
{
static_assert(!std::is_same_v<TraitsT, boundary_no_caps_tag> && "1D hemisphere_boundary_no_caps does not have any caps");
return v.center;
}
......
......@@ -2,13 +2,9 @@
#include <typed-geometry/detail/utility.hh>
#include <typed-geometry/types/objects/line.hh>
#include <typed-geometry/types/objects/plane.hh>
#include <typed-geometry/types/objects/segment.hh>
#include <typed-geometry/types/pos.hh>
#include <typed-geometry/types/quadric.hh>
#include <typed-geometry/functions/basic/mix.hh>
#include "coordinates.hh"
#include "project.hh"
......@@ -45,7 +41,7 @@ template <class ScalarT>
auto d0d1 = dot(l0.dir, l1.dir);
auto b0 = dot(l1.pos - l0.pos, l0.dir);
auto b1 = dot(l1.pos - l0.pos, l1.dir);
auto [t0, t1] = inverse(tg::mat<2, 2, ScalarT>::from_cols({1, d0d1}, {-d0d1, -1})) * tg::vec2(b0, b1);
auto [t0, t1] = inverse(mat<2, 2, ScalarT>::from_cols({1, d0d1}, {-d0d1, -1})) * vec2(b0, b1);
return {t0, t1};
}
......@@ -56,6 +52,17 @@ template <class ScalarT>
return {l0[t0], l1[t1]};
}
template <class ScalarT>
[[nodiscard]] constexpr pair<ScalarT, ScalarT> closest_points_parameters(segment<3, ScalarT> const& s, line<3, ScalarT> const& l)
{
auto ls = inf_of(s);
auto len = length(s);
auto [ts, tl] = closest_points_parameters(ls, l);
auto tClamped = clamp(ts, ScalarT(0), len);
return {tClamped / len, coordinates(l, ls[tClamped])};
}
// =========== Other Implementations ===========
......
......@@ -46,6 +46,20 @@ template <int D, class ScalarT>
return b == o;
}
// default implementation for contains(objA, objB) that works when objA is solid and vertices_of(objB) is defined
template <class A, class B>
[[nodiscard]] constexpr auto contains(A const& a, B const& b, dont_deduce<typename B::scalar_t> eps = static_cast<typename B::scalar_t>(0))
-> enable_if<std::is_same_v<typename object_traits<A>::tag_t, default_object_tag>, decltype(vertices_of(b), false)>
{
for (auto const& vertex : vertices_of(b))
if (!contains(a, vertex, eps))
return false;
return true;
}
// object specific implementations for contains(obj, pos)
template <class ScalarT>
[[nodiscard]] constexpr bool contains(aabb<1, ScalarT> const& b, ScalarT const& o, dont_deduce<ScalarT> eps = ScalarT(0))
{
......@@ -120,8 +134,7 @@ template <int D, class ScalarT>
if (ri > bi + eps)
return false; // False if outside of the aabb in any dimension
if (!onSomeBoundary && (ri >= bi - eps))
onSomeBoundary = true;
onSomeBoundary = onSomeBoundary || (ri >= bi - eps);
}
return onSomeBoundary; // True, if at on the boundary in at least one dimension
}
......
......@@ -91,45 +91,72 @@ template <class ScalarT>
}
template <class ScalarT>
[[nodiscard]] constexpr fractional_result<ScalarT> distance(segment<2, ScalarT> const& s0, segment<2, ScalarT> const& s1)
[[nodiscard]] constexpr fractional_result<ScalarT> distance_sqr(segment<2, ScalarT> const& s0, segment<2, ScalarT> const& s1)
{
auto l0 = line<2, ScalarT>::from_points(s0.pos0, s0.pos1);
auto l1 = line<2, ScalarT>::from_points(s1.pos0, s1.pos1);
auto sl0 = distance(s0.pos0, s0.pos1);
auto sl1 = distance(s1.pos0, s1.pos1);
auto l0 = inf_of(s0);
auto l1 = inf_of(s1);
auto len0 = length(s0);
auto len1 = length(s1);
auto [t0, t1] = intersection_parameters(l0, l1);
if (ScalarT(0) <= t0 && t0 <= ScalarT(sl0) && //
ScalarT(0) <= t1 && t1 <= ScalarT(sl1))
if (ScalarT(0) <= t0 && t0 <= len0 && //
ScalarT(0) <= t1 && t1 <= len1)
return ScalarT(0); // intersects
auto p0 = t0 < ScalarT(0) ? s0.pos0 : s0.pos1;
auto p1 = t1 < ScalarT(0) ? s1.pos0 : s1.pos1;
auto p0 = t0 * ScalarT(2) < len0 ? s0.pos0 : s0.pos1;
auto p1 = t1 * ScalarT(2) < len1 ? s1.pos0 : s1.pos1;
return min(distance(p0, s1), distance(p1, s0));
return min(distance_sqr(p0, s1), distance_sqr(p1, s0));
}
template <class ScalarT>
[[nodiscard]] constexpr fractional_result<ScalarT> distance(segment<3, ScalarT> const& s0, segment<3, ScalarT> const& s1)
[[nodiscard]] constexpr fractional_result<ScalarT> distance_sqr(segment<3, ScalarT> const& s0, segment<3, ScalarT> const& s1)
{
auto l0 = line<3, ScalarT>::from_points(s0.pos0, s0.pos1);
auto l1 = line<3, ScalarT>::from_points(s1.pos0, s1.pos1);
auto sl0 = distance(s0.pos0, s0.pos1);
auto sl1 = distance(s1.pos0, s1.pos1);
auto l0 = inf_of(s0);
auto l1 = inf_of(s1);
auto len0 = length(s0);
auto len1 = length(s1);
auto [t0, t1] = closest_points_parameters(l0, l1);
if (ScalarT(0) <= t0 && t0 <= ScalarT(sl0) && //
ScalarT(0) <= t1 && t1 <= ScalarT(sl1))
return distance(l0[t0], l1[t1]); // closest points is inside segments
if (ScalarT(0) <= t0 && t0 <= len0 && //
ScalarT(0) <= t1 && t1 <= len1)
return distance_sqr(l0[t0], l1[t1]); // closest points is inside segments
auto p0 = t0 * ScalarT(2) < len0 ? s0.pos0 : s0.pos1;
auto p1 = t1 * ScalarT(2) < len1 ? s1.pos0 : s1.pos1;
return min(distance_sqr(p0, s1), distance_sqr(p1, s0));
}
template <class ScalarT>
[[nodiscard]] constexpr fractional_result<ScalarT> distance_sqr(segment<2, ScalarT> const& s, line<2, ScalarT> const& l)
{
auto ls = inf_of(s);
auto len = length(s);
auto [ts, tl] = intersection_parameters(ls, l);
if (ScalarT(0) <= ts && ts <= len)
return ScalarT(0); // intersects
auto p0 = t0 < ScalarT(0) ? s0.pos0 : s0.pos1;
auto p1 = t1 < ScalarT(0) ? s1.pos0 : s1.pos1;
auto p = ts * ScalarT(2) < len ? s.pos0 : s.pos1;
return distance_sqr(p, l);
}
template <class ScalarT>
[[nodiscard]] constexpr fractional_result<ScalarT> distance_sqr(segment<3, ScalarT> const& s, line<3, ScalarT> const& l)
{
auto ls = inf_of(s);
auto len = length(s);
return min(distance(p0, s1), distance(p1, s0));
auto [ts, tl] = closest_points_parameters(ls, l);
auto tClamped = clamp(ts, ScalarT(0), len);
return distance_sqr(ls[tClamped], l);
}
template <int D, class ScalarT>
[[nodiscard]] constexpr fractional_result<ScalarT> distance_sqr(line<D, ScalarT> const& l, segment<D, ScalarT> const& s)
{
return distance_sqr(s, l);
}
// TODO: use GJK or something?
......
......@@ -17,7 +17,7 @@ template <int D, class ScalarT>
}
template <int D, class ScalarT>
[[nodiscard]] constexpr array<segment<2, ScalarT>, 4> edges_of(quad<D, ScalarT> const& q)
[[nodiscard]] constexpr array<segment<D, ScalarT>, 4> edges_of(quad<D, ScalarT> const& q)
{
return {{{q.pos00, q.pos10}, {q.pos10, q.pos11}, {q.pos11, q.pos01}, {q.pos01, q.pos00}}};
}
......@@ -60,14 +60,14 @@ template <class ScalarT, class TraitsT>
}
template <class ScalarT, int DomainD, class TraitsT>
[[nodiscard]] constexpr array<segment<2, ScalarT>, 4> edges_of(box<2, ScalarT, DomainD, TraitsT> const& b)
[[nodiscard]] constexpr array<segment<DomainD, ScalarT>, 4> edges_of(box<2, ScalarT, DomainD, TraitsT> const& b)
{
const auto vs = vertices_of(b);
return {{{vs[0], vs[1]}, {vs[1], vs[2]}, {vs[2], vs[3]}, {vs[3], vs[0]}}};
}
template <class ScalarT, int DomainD, class TraitsT>
[[nodiscard]] constexpr array<segment<3, ScalarT>, 12> edges_of(box<3, ScalarT, DomainD, TraitsT> const& b)
[[nodiscard]] constexpr array<segment<DomainD, ScalarT>, 12> edges_of(box<3, ScalarT, DomainD, TraitsT> const& b)
{
const auto vs = vertices_of(b);
return {{
......@@ -79,12 +79,10 @@ template <class ScalarT, int DomainD, class TraitsT>
}};
}
template <class BaseT, class TraitsT>
template <class BaseT, class TraitsT, typename = std::enable_if_t<!std::is_same_v<BaseT, sphere<2, typename BaseT::scalar_t, 3>>>>
[[nodiscard]] constexpr auto edges_of(pyramid<BaseT, TraitsT> const& py)
{
using ScalarT = typename BaseT::scalar_t;
static_assert(!std::is_same_v<BaseT, sphere<2, ScalarT, 3>>, "not possible for cones");
const auto apex = apex_of(py);
const auto edgesBase = edges_of(py.base);
auto res = array<segment<3, ScalarT>, edgesBase.size() * 2>();
......
......@@ -62,12 +62,11 @@ template <class ScalarT, class TraitsT>
return {{faceX0, faceX1, faceY0, faceY1, faceZ0, faceZ1}};
}
template <class BaseT>
template <class BaseT, typename = std::enable_if_t<!std::is_same_v<BaseT, sphere<2, typename BaseT::scalar_t, 3>>>>
[[nodiscard]] constexpr auto faces_of(pyramid<BaseT, boundary_no_caps_tag> const& py)
{
using ScalarT = typename BaseT::scalar_t;
static_assert(is_floating_point<ScalarT>, "cannot be guaranteed for integers");
static_assert(!std::is_same_v<BaseT, sphere<2, ScalarT, 3>>, "not possible for cones");
const auto apex = apex_of(py);
const auto verts = vertices_of(py.base);
......@@ -77,7 +76,7 @@ template <class BaseT>
return triangles;
}
template <class BaseT, class TraitsT>
template <class BaseT, class TraitsT, typename = std::enable_if_t<!std::is_same_v<BaseT, sphere<2, typename BaseT::scalar_t, 3>>>>
[[nodiscard]] constexpr auto faces_of(pyramid<BaseT, TraitsT> const& py)
{
auto mantle = faces_of(boundary_no_caps_of(py));
......
......@@ -28,39 +28,70 @@ template <int D, class ScalarT>
return {{q.pos00, q.pos10, q.pos11, q.pos01}}; // in ccw order
}
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr array<pos<1, ScalarT>, 2> vertices_of(aabb<1, ScalarT, TraitsT> const& bb)
{
return {{bb.min, bb.max}};
}
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr array<pos<2, ScalarT>, 4> vertices_of(aabb<2, ScalarT, TraitsT> const& bb)
{
auto p00 = pos<2, ScalarT>(bb.min.x, bb.min.y);
auto p10 = pos<2, ScalarT>(bb.max.x, bb.min.y);
auto p11 = pos<2, ScalarT>(bb.max.x, bb.max.y);
auto p01 = pos<2, ScalarT>(bb.min.x, bb.max.y);
auto const p10 = pos<2, ScalarT>(bb.max.x, bb.min.y);
auto const p01 = pos<2, ScalarT>(bb.min.x, bb.max.y);
return {{p00, p10, p11, p01}}; // in ccw order
return {{bb.min, p10, bb.max, p01}}; // in ccw order
}
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr array<pos<3, ScalarT>, 8> vertices_of(aabb<3, ScalarT, TraitsT> const& bb)
{
auto p000 = pos<3, ScalarT>(bb.min.x, bb.min.y, bb.min.z);
auto p001 = pos<3, ScalarT>(bb.min.x, bb.min.y, bb.max.z);
auto p010 = pos<3, ScalarT>(bb.min.x, bb.max.y, bb.min.z);
auto p011 = pos<3, ScalarT>(bb.min.x, bb.max.y, bb.max.z);
auto p100 = pos<3, ScalarT>(bb.max.x, bb.min.y, bb.min.z);
auto p101 = pos<3, ScalarT>(bb.max.x, bb.min.y, bb.max.z);
auto p110 = pos<3, ScalarT>(bb.max.x, bb.max.y, bb.min.z);
auto p111 = pos<3, ScalarT>(bb.max.x, bb.max.y, bb.max.z);
return {{p000, p001, p010, p011, p100, p101, p110, p111}};
auto const p001 = pos<3, ScalarT>(bb.min.x, bb.min.y, bb.max.z);
auto const p010 = pos<3, ScalarT>(bb.min.x, bb.max.y, bb.min.z);
auto const p011 = pos<3, ScalarT>(bb.min.x, bb.max.y, bb.max.z);
auto const p100 = pos<3, ScalarT>(bb.max.x, bb.min.y, bb.min.z);
auto const p101 = pos<3, ScalarT>(bb.max.x, bb.min.y, bb.max.z);
auto const p110 = pos<3, ScalarT>(bb.max.x, bb.max.y, bb.min.z);
return {{bb.min, p001, p010, p011, p100, p101, p110, bb.max}};
}
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr array<pos<4, ScalarT>, 16> vertices_of(aabb<4, ScalarT, TraitsT> const& bb)
{
auto const p0001 = pos<4, ScalarT>(bb.min.x, bb.min.y, bb.min.z, bb.max.w);
auto const p0010 = pos<4, ScalarT>(bb.min.x, bb.min.y, bb.max.z, bb.min.w);
auto const p0011 = pos<4, ScalarT>(bb.min.x, bb.min.y, bb.max.z, bb.max.w);
auto const p0100 = pos<4, ScalarT>(bb.min.x, bb.max.y, bb.min.z, bb.min.w);
auto const p0101 = pos<4, ScalarT>(bb.min.x, bb.max.y, bb.min.z, bb.max.w);
auto const p0110 = pos<4, ScalarT>(bb.min.x, bb.max.y, bb.max.z, bb.min.w);
auto const p0111 = pos<4, ScalarT>(bb.min.x, bb.max.y, bb.max.z, bb.max.w);
auto const p1000 = pos<4, ScalarT>(bb.max.x, bb.min.y, bb.min.z, bb.min.w);
auto const p1001 = pos<4, ScalarT>(bb.max.x, bb.min.y, bb.min.z, bb.max.w);
auto const p1010 = pos<4, ScalarT>(bb.max.x, bb.min.y, bb.max.z, bb.min.w);
auto const p1011 = pos<4, ScalarT>(bb.max.x, bb.min.y, bb.max.z, bb.max.w);
auto const p1100 = pos<4, ScalarT>(bb.max.x, bb.max.y, bb.min.z, bb.min.w);
auto const p1101 = pos<4, ScalarT>(bb.max.x, bb.max.y, bb.min.z, bb.max.w);
auto const p1110 = pos<4, ScalarT>(bb.max.x, bb.max.y, bb.max.z, bb.min.w);
return {{bb.min, p0001, p0010, p0011, p0100, p0101, p0110, p0111, p1001, p1010, p1011, p1100, p1101, p1110, bb.max}};
}
template <class ScalarT, int DomainD, class TraitsT>
[[nodiscard]] constexpr array<pos<DomainD, ScalarT>, 2> vertices_of(box<1, ScalarT, DomainD, TraitsT> const& b)
{
auto const p0 = b[comp<1, ScalarT>(-1)];
auto const p1 = b[comp<1, ScalarT>(1)];
return {{p0, p1}};
}
template <class ScalarT, int DomainD, class TraitsT>
[[nodiscard]] constexpr array<pos<DomainD, ScalarT>, 4> vertices_of(box<2, ScalarT, DomainD, TraitsT> const& b)
{
const auto p00 = b[comp<2, ScalarT>(-1, -1)];
const auto p10 = b[comp<2, ScalarT>(1, -1)];
const auto p11 = b[comp<2, ScalarT>(1, 1)];
const auto p01 = b[comp<2, ScalarT>(-1, 1)];
auto const p00 = b[comp<2, ScalarT>(-1, -1)];
auto const p10 = b[comp<2, ScalarT>(1, -1)];
auto const p11 = b[comp<2, ScalarT>(1, 1)];
auto const p01 = b[comp<2, ScalarT>(-1, 1)];
return {{p00, p10, p11, p01}}; // in ccw order
}
......@@ -68,25 +99,47 @@ template <class ScalarT, int DomainD, class TraitsT>
template <class ScalarT, int DomainD, class TraitsT>
[[nodiscard]] constexpr array<pos<DomainD, ScalarT>, 8> vertices_of(box<3, ScalarT, DomainD, TraitsT> const& b)
{
const auto p000 = b[comp<3, ScalarT>(-1, -1, -1)];
const auto p100 = b[comp<3, ScalarT>(1, -1, -1)];
const auto p110 = b[comp<3, ScalarT>(1, 1, -1)];
const auto p010 = b[comp<3, ScalarT>(-1, 1, -1)];
const auto p001 = b[comp<3, ScalarT>(-1, -1, 1)];
const auto p101 = b[comp<3, ScalarT>(1, -1, 1)];
const auto p111 = b[comp<3, ScalarT>(1, 1, 1)];
const auto p011 = b[comp<3, ScalarT>(-1, 1, 1)];
auto const p000 = b[comp<3, ScalarT>(-1, -1, -1)];
auto const p100 = b[comp<3, ScalarT>(1, -1, -1)];
auto const p110 = b[comp<3, ScalarT>(1, 1, -1)];
auto const p010 = b[comp<3, ScalarT>(-1, 1, -1)];
auto const p001 = b[comp<3, ScalarT>(-1, -1, 1)];
auto const p101 = b[comp<3, ScalarT>(1, -1, 1)];
auto const p111 = b[comp<3, ScalarT>(1, 1, 1)];
auto const p011 = b[comp<3, ScalarT>(-1, 1, 1)];
return {{p000, p100, p110, p010, p001, p101, p111, p011}};
}
template <class BaseT, class TraitsT>
template <class ScalarT, int DomainD, class TraitsT>
[[nodiscard]] constexpr array<pos<DomainD, ScalarT>, 16> vertices_of(box<4, ScalarT, DomainD, TraitsT> const& b)
{
auto const p0000 = b[comp<4, ScalarT>(-1, -1, -1, -1)];
auto const p1000 = b[comp<4, ScalarT>(1, -1, -1, -1)];
auto const p1100 = b[comp<4, ScalarT>(1, 1, -1, -1)];
auto const p0100 = b[comp<4, ScalarT>(-1, 1, -1, -1)];
auto const p0010 = b[comp<4, ScalarT>(-1, -1, 1, -1)];
auto const p1010 = b[comp<4, ScalarT>(1, -1, 1, -1)];
auto const p1110 = b[comp<4, ScalarT>(1, 1, 1, -1)];
auto const p0110 = b[comp<4, ScalarT>(-1, 1, 1, -1)];
auto const p0001 = b[comp<4, ScalarT>(-1, -1, -1, 1)];
auto const p1001 = b[comp<4, ScalarT>(1, -1, -1, 1)];
auto const p1101 = b[comp<4, ScalarT>(1, 1, -1, 1)];
auto const p0101 = b[comp<4, ScalarT>(-1, 1, -1, 1)];
auto const p0011 = b[comp<4, ScalarT>(-1, -1, 1, 1)];
auto const p1011 = b[comp<4, ScalarT>(1, -1, 1, 1)];
auto const p1111 = b[comp<4, ScalarT>(1, 1, 1, 1)];
auto const p0111 = b[comp<4, ScalarT>(-1, 1, 1, 1)];
return {{p0000, p1000, p1100, p0100, p0010, p1010, p1110, p0110, p0001, p1001, p1101, p0101, p0011, p1011, p1111, p0111}};
}
template <class BaseT, class TraitsT, typename = std::enable_if_t<!std::is_same_v<BaseT, sphere<2, typename BaseT::scalar_t, 3>>>>
[[nodiscard]] constexpr auto vertices_of(pyramid<BaseT, TraitsT> const& py)
{
using ScalarT = typename BaseT::scalar_t;
static_assert(!std::is_same_v<BaseT, sphere<2, ScalarT, 3>>, "not possible for cones");
const auto vertsBase = vertices_of(py.base);
auto const vertsBase = vertices_of(py.base);
auto res = array<pos<3, ScalarT>, vertsBase.size() + 1>();
for (size_t i = 0; i < vertsBase.size(); ++i)
res[i] = vertsBase[i];
......
......@@ -336,6 +336,12 @@ constexpr auto uniform_by_volume(Rng& rng, ObjectA const& obj, ObjectRest const&
// ======== Uniform point on an object ========
template <int D, class ScalarT, class Rng>
[[nodiscard]] constexpr pos<D, ScalarT> uniform(Rng&, pos<D, ScalarT> const& p)
{
return p; // not really a random position, but this makes some generic implementations easier
}
template <class Rng>
[[nodiscard]] constexpr int uniform(Rng& rng, range1 const& b)
{
......@@ -656,6 +662,8 @@ template <int D, class ScalarT, class Rng>
[[nodiscard]] constexpr pos<D, ScalarT> uniform(Rng& rng, hemisphere_boundary<D, ScalarT> const& h)
{
ScalarT ratio;
if constexpr (D == 1)
ratio = ScalarT(0.5);
if constexpr (D == 2)
ratio = ScalarT(2) / (ScalarT(2) + pi_scalar<ScalarT>); // round length = pi * r, flat length = 2 * r => ratio pi : 2
if constexpr (D == 3)
......
......@@ -19,6 +19,7 @@ namespace tg
// abs
TG_IMPL_DEFINE_COMPWISE_FUNC_UNARY(pos, abs);
TG_IMPL_DEFINE_COMPWISE_FUNC_UNARY(vec, abs);
TG_IMPL_DEFINE_COMPWISE_FUNC_UNARY(dir, abs);
TG_IMPL_DEFINE_COMPWISE_FUNC_UNARY(size, abs);
TG_IMPL_DEFINE_COMPWISE_FUNC_UNARY(comp, abs);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment