diff --git a/extern/glow-extras b/extern/glow-extras index 3097d90d45c6778ed72911f64ce3e08f9f5c6eb0..f53a709b1a5926ce12dd00d3514d7d730c859748 160000 --- a/extern/glow-extras +++ b/extern/glow-extras @@ -1 +1 @@ -Subproject commit 3097d90d45c6778ed72911f64ce3e08f9f5c6eb0 +Subproject commit f53a709b1a5926ce12dd00d3514d7d730c859748 diff --git a/extern/polymesh b/extern/polymesh index 65025e1af6e6abb89401e0337d49310b01ba8833..5719ed1860a475ddfcf3d7119027e4bd7910b0a9 160000 --- a/extern/polymesh +++ b/extern/polymesh @@ -1 +1 @@ -Subproject commit 65025e1af6e6abb89401e0337d49310b01ba8833 +Subproject commit 5719ed1860a475ddfcf3d7119027e4bd7910b0a9 diff --git a/extern/typed-geometry b/extern/typed-geometry index f8a5e56373e3da67e7ea543424d0704950cbdfc1..23d12b23ad62e2c0bef0be2d569e100dca2ce846 160000 --- a/extern/typed-geometry +++ b/extern/typed-geometry @@ -1 +1 @@ -Subproject commit f8a5e56373e3da67e7ea543424d0704950cbdfc1 +Subproject commit 23d12b23ad62e2c0bef0be2d569e100dca2ce846 diff --git a/samples/03-triangle-properties/main.cc b/samples/03-triangle-properties/main.cc new file mode 100644 index 0000000000000000000000000000000000000000..fce193d893fa5c62b908835fea043567480370b2 --- /dev/null +++ b/samples/03-triangle-properties/main.cc @@ -0,0 +1,41 @@ +#include <typed-geometry/tg.hh> + +#include <imgui/imgui.h> + +#include <glow-extras/glfw/GlfwContext.hh> +#include <glow-extras/viewer/canvas.hh> +#include <glow-extras/viewer/view.hh> + +int main() +{ + glow::glfw::GlfwContext ctx; + + tg::triangle3 t = {{1, 0, -2}, {-1, 0, -2}, {0, 0, 1.5f}}; + + gv::interactive([&](float) { + ImGui::SliderFloat3("pos0", &t.pos0.x, -2, 2); + ImGui::SliderFloat3("pos1", &t.pos1.x, -2, 2); + ImGui::SliderFloat3("pos2", &t.pos2.x, -2, 2); + + ImGui::Separator(); + ImGui::Text("Area: %f", tg::area_of(t)); + ImGui::Text("Perimeter: %f", tg::perimeter_of(t)); + ImGui::Text("Circumradius: %f", tg::circumradius_of(t)); + ImGui::Text("Inradius: %f", tg::inradius_of(t)); + + auto c = gv::canvas(); + c.add_lines(t); + c.add_face(t); + + c.add_point(tg::centroid_of(t), tg::color3::red); + c.add_label(tg::centroid_of(t), "centroid"); + + c.add_point(tg::circumcenter_of(t), tg::color3::blue); + c.add_lines(tg::circumcircle_of(t), tg::color3::blue); + c.add_label(tg::circumcenter_of(t), "circumcenter"); + + c.add_point(tg::incenter_of(t), tg::color3::green); + c.add_lines(tg::incircle_of(t), tg::color3::green); + c.add_label(tg::incenter_of(t), "incenter"); + }); +} diff --git a/tests/feature/objects/triangles.cc b/tests/feature/objects/triangles.cc new file mode 100644 index 0000000000000000000000000000000000000000..4a36bf4a57845ad9ac43d8c45b321d48b1818d1d --- /dev/null +++ b/tests/feature/objects/triangles.cc @@ -0,0 +1,53 @@ +#include "test.hh" + +TG_FUZZ_TEST(Triangle, Circles) +{ + auto const execute_test = [&](auto bb) { + auto const p0 = uniform(rng, bb); + auto const p1 = uniform(rng, bb); + auto const p2 = uniform(rng, bb); + + auto const t = tg::triangle(p0, p1, p2); + + auto const p = tg::perimeter_of(t); + + CHECK(distance(p0, p1) + distance(p1, p2) + distance(p2, p0) == approx(p).epsilon(0.001f)); + + // + // circumcenter + // + if (tg::min_height_of(t) > 0.1f) // flat triangles have extreme/unstable circles + { + auto const cc = tg::circumcenter_of(t); + auto const cs = tg::circumcircle_of(t); + auto const cr = tg::circumradius_of(t); + + CHECK(distance(p0, cc) == approx(distance(p1, cc)).epsilon(0.001f)); + CHECK(distance(p1, cc) == approx(distance(p2, cc)).epsilon(0.001f)); + CHECK(distance(p2, cc) == approx(distance(p0, cc)).epsilon(0.001f)); + + CHECK(cs.radius == approx(distance(p0, cc)).epsilon(0.001f)); + CHECK(cs.center == approx(cc, 0.001f)); + CHECK(cr == approx(cs.radius).epsilon(0.001f)); + } + + // + // incenter + // + if (tg::min_height_of(t) > 0.1f) // flat triangles have unstable circles + { + auto const ic = tg::incenter_of(t); + auto const is = tg::incircle_of(t); + auto const ir = tg::inradius_of(t); + + for (auto e : tg::edges_of(t)) + CHECK(distance(e, ic) == approx(ir).epsilon(0.001f)); + + CHECK(is.center == approx(ic, 0.001f)); + CHECK(ir == approx(is.radius).epsilon(0.001f)); + } + }; + + execute_test(tg::aabb2(-10, 10)); + execute_test(tg::aabb3(-10, 10)); +}