Commit 9b48a947 authored by Philip Trettner's avatar Philip Trettner
Browse files

more intersections and triangulate_uv

parent eaf7915e
......@@ -19,11 +19,13 @@
#include <typed-geometry/functions/objects/intersection.hh>
#include <typed-geometry/functions/objects/normal.hh>
#include <typed-geometry/functions/objects/perimeter.hh>
#include <typed-geometry/functions/objects/plane.hh>
#include <typed-geometry/functions/objects/project.hh>
#include <typed-geometry/functions/objects/rasterize.hh>
#include <typed-geometry/functions/objects/size.hh>
#include <typed-geometry/functions/objects/tangent.hh>
#include <typed-geometry/functions/objects/triangle.hh>
#include <typed-geometry/functions/objects/triangulate.hh>
#include <typed-geometry/functions/objects/triangulation.hh>
#include <typed-geometry/functions/objects/vertices.hh>
#include <typed-geometry/functions/objects/volume.hh>
......@@ -32,6 +32,7 @@
#include "direction.hh"
#include "faces.hh"
#include "normal.hh"
#include "plane.hh"
#include "project.hh"
#include <utility>
......@@ -943,6 +944,7 @@ template <class ScalarT>
// ====================================== Object - Object Intersections ======================================
// sphere boundary - sphere boundary
// returns intersection circle of sphere and sphere (normal points from a to b)
// for now does not work if spheres are identical (result would be a sphere3 again)
template <class ScalarT>
......@@ -996,6 +998,7 @@ template <class ScalarT>
return sphere_boundary<2, ScalarT, 3>{ipos, irad, dir<3, ScalarT>((b.center - a.center) / d)};
}
// sphere boundary - sphere boundary
// returns intersection points of two circles in 2D
// for now does not work if circles are identical (result would be a circle2 again)
template <class ScalarT>
......@@ -1035,6 +1038,7 @@ template <class ScalarT>
return pair{p_above, p_below};
}
// sphere boundary - plane
// returns intersection circle of sphere and sphere (normal points from a to b)
// for now does not work if spheres are identical (result would be a sphere3 again)
template <class ScalarT>
......@@ -1065,7 +1069,65 @@ template <class ScalarT>
return r;
}
// circle - plane
template <class ScalarT>
[[nodiscard]] constexpr hits<2, pos<3, ScalarT>> intersection(sphere<2, ScalarT, 3, boundary_tag> const& a, plane<3, ScalarT> const& b)
{
auto const l = intersection(plane_of(a), b);
return intersection(l, sphere_boundary<3, ScalarT>(a.center, a.radius));
}
template <class ScalarT>
[[nodiscard]] constexpr hits<2, pos<3, ScalarT>> intersection(plane<3, ScalarT> const& a, sphere<2, ScalarT, 3, boundary_tag> const& b)
{
return intersection(b, a);
}
// circle - sphere
template <class ScalarT>
[[nodiscard]] constexpr hits<2, pos<3, ScalarT>> intersection(sphere<2, ScalarT, 3, boundary_tag> const& a, sphere_boundary<3, ScalarT> const& s)
{
auto const is = intersection(plane_of(a), s);
if (!is.has_value())
return {};
auto const b = is.value();
auto d2 = distance_sqr(a.center, b.center);
auto d = sqrt(d2);
auto ar = a.radius;
auto br = b.radius;
if (ar + br < d) // no intersection
return {};
if (d < abs(ar - br)) // no intersection (one inside the other)
return {};
TG_INTERNAL_ASSERT(d > ScalarT(0));
auto t = (ar * ar - br * br + d2) / (2 * d);
auto h2 = ar * ar - t * t;
TG_INTERNAL_ASSERT(h2 >= ScalarT(0));
auto h = sqrt(h2);
auto h_by_d = h / d;
auto p_between = a.center + t / d * (b.center - a.center);
auto bitangent = cross(b.center - a.center, a.normal);
// imagining circle a on the left side of circle b...
auto p_above = p_between + h_by_d * bitangent;
auto p_below = p_between - h_by_d * bitangent;
return {p_above, p_below};
}
template <class ScalarT>
[[nodiscard]] constexpr hits<2, pos<3, ScalarT>> intersection(sphere_boundary<3, ScalarT> const& a, sphere<2, ScalarT, 3, boundary_tag> const& b)
{
return intersection(b, a);
}
// plane - plane
template <class ScalarT>
[[nodiscard]] constexpr line<3, ScalarT> intersection(plane<3, ScalarT> const& a, plane<3, ScalarT> const& b)
{
......
#pragma once
#include <typed-geometry/functions/objects/normal.hh>
#include <typed-geometry/types/objects/box.hh>
#include <typed-geometry/types/objects/ellipse.hh>
#include <typed-geometry/types/objects/plane.hh>
#include <typed-geometry/types/objects/sphere.hh>
#include <typed-geometry/types/objects/triangle.hh>
// tg::plane_of(obj) returns the supporting plane of an object
// (when unambiguously defined)
// TODO: maybe also for "base planes" as in cone / hemisphere / pyramid?
namespace tg
{
template <int D, class ScalarT>
[[nodiscard]] constexpr plane<D, ScalarT> plane_of(plane<D, ScalarT> const& p)
{
return p;
}
template <int D, class ScalarT>
[[nodiscard]] constexpr plane<D, ScalarT> plane_of(halfspace<D, ScalarT> const& p)
{
return plane<3, ScalarT>(p.normal, p.dis);
}
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr plane<3, ScalarT> plane_of(box<2, ScalarT, 3, TraitsT> const& b)
{
return plane<3, ScalarT>(normal_of(b), b.center);
}
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr plane<3, ScalarT> plane_of(ellipse<2, ScalarT, 3, TraitsT> const& e)
{
return plane<3, ScalarT>(normal_of(e), e.center);
}
template <class ScalarT, class TraitsT>
[[nodiscard]] constexpr plane<3, ScalarT> plane_of(sphere<2, ScalarT, 3, TraitsT> const& s)
{
return plane<3, ScalarT>(s.normal, s.center);
}
template <class ScalarT>
[[nodiscard]] constexpr plane<3, ScalarT> plane_of(triangle<3, ScalarT> const& t)
{
return plane<3, ScalarT>(normal_of(t), t.pos0);
}
}
#pragma once
#include <typed-geometry/feature/basic.hh>
#include <typed-geometry/functions/objects/triangulation.hh>
namespace tg
{
/// calls on_triangle for each triangle of the objects triangulation
/// on_triangle: (tg::triangle) -> void
template <class Obj, class OnTriangle, std::enable_if_t<has_triangulation_of<Obj>, int> = 0>
constexpr void triangulate(Obj const& obj, OnTriangle&& on_triangle)
{
for (auto&& t : triangulation_of(obj))
on_triangle(t);
}
/// computes a uv triangulation of the given sphere and calls on_triangle with each triangle
/// on_triangle: (tg::triangle) -> void
/// NOTE: currently recomputes a lot of sin/cos and thus is not the fastest
/// NOTE: normal_of(t) points outwards
/// NOTE: segs_u must be >= 3, segs_v must be >= 2
template <class ScalarT, class TraitsT, class OnTriangle>
void triangulate_uv(sphere<3, ScalarT, 3, TraitsT> const& s, int segs_u, int segs_v, OnTriangle&& on_triangle)
{
TG_ASSERT(segs_u >= 3);
TG_ASSERT(segs_v >= 2);
// TODO: some caching of sin/cos
using dir_t = dir<3, ScalarT>;
auto const dir_of = [&](int u, int v) -> dir_t {
if (v == 0)
return dir_t(0, 1, 0);
else if (v == segs_v)
return dir_t(0, -1, 0);
auto [su, cu] = tg::sin_cos(tau<ScalarT> * (u == segs_u ? 0 : u) / ScalarT(segs_u));
auto [sv, cv] = tg::sin_cos(pi<ScalarT> * v / ScalarT(segs_v));
return dir_t(sv * su, cv, sv * cu);
};
auto const pos_of = [&](int u, int v) {
auto d = dir_of(u, v);
return s.center + d * s.radius;
};
// cap u
{
auto p0 = pos_of(0, 0);
for (auto i = 0; i < segs_u; ++i)
{
auto p1 = pos_of(i, 1);
auto p2 = pos_of(i + 1, 1);
on_triangle(tg::triangle3(p0, p1, p2));
}
}
// inner grid
for (auto j = 1; j < segs_v - 1; ++j)
{
for (auto i = 0; i < segs_u; ++i)
{
auto p00 = pos_of(i + 0, j + 0);
auto p01 = pos_of(i + 0, j + 1);
auto p10 = pos_of(i + 1, j + 0);
auto p11 = pos_of(i + 1, j + 1);
on_triangle(tg::triangle3(p00, p01, p11));
on_triangle(tg::triangle3(p00, p11, p10));
}
}
// cap v
{
auto p0 = pos_of(0, segs_v);
for (auto i = 0; i < segs_u; ++i)
{
auto p1 = pos_of(i, segs_v - 1);
auto p2 = pos_of(i + 1, segs_v - 1);
on_triangle(tg::triangle3(p0, p2, p1));
}
}
}
}
......@@ -8,13 +8,13 @@
namespace tg
{
template <int D, class ScalarT>
[[nodiscard]] array<triangle<D, ScalarT>, 1> triangulation_of(triangle<D, ScalarT> const& t)
[[nodiscard]] constexpr array<triangle<D, ScalarT>, 1> triangulation_of(triangle<D, ScalarT> const& t)
{
return {{t}};
}
template <int D, class ScalarT>
[[nodiscard]] array<triangle<D, ScalarT>, 2> triangulation_of(quad<D, ScalarT> const& q)
[[nodiscard]] constexpr array<triangle<D, ScalarT>, 2> triangulation_of(quad<D, ScalarT> const& q)
{
// TODO: orientation guarantees?
return {{
......
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