TU-Programmieren_2/exercise5/task3.cpp
2025-04-09 10:22:44 +02:00

79 lines
3.1 KiB
C++

/// @file
/// @brief Task3: implementation
#include "task3.hpp" // task3::generate_double_annulus
#include "task2.hpp" // task2::select, task2::select_union
#include "TriangleMesh.hpp" // ex5::TriangleMesh
#include <cmath> // for std::sqrt
namespace task3 {
using namespace task2;
/// @todo Implement function 'generate_double_annulus' as declared and specified in task3.hpp
/// Implementation Hints:
/// - calculate the required bounding box for the annuluses using the centers coordinates +- outer radius
/// - create a triangle mesh using the desired bounding box and resolution (h)
/// - use the source code of task2.test.cpp for ideas how to create the boolean functions for circular regions
/// - select the union of the two inner circles and remove the triangles using the following functions:
/// mesh.getVertices
/// task2::select_union(...)
/// mesh.remove_vertices(...)
/// - analoguously, select the union of the two outer circles and remove the INVERSE of this union using
/// - mesh.getVertices()
/// - task2::select_union(..., true)
/// - mesh.remove_vertices(...)
/// @brief Generates a triangle mesh placed of two (potentially merged) annuluses (Kreisringe)
/// @param c1 Center coordinate of the first annulus
/// @param c2 Center coordinate of the second annulus
/// @param r inner radius of both annuluses
/// @param R outer radius of both annuluses
/// @param h lower bound for the triangle egde length of the resulting mesh
/// @return Resulting triangle mesh
ex5::TriangleMesh generate_double_annulus(task2::Vec2d c1, task2::Vec2d c2, double r, double R, double h) {
// Calculate bounding box based on center coordinates, radii and a small offset
double offset = h / 2.0; // Adjust as needed
auto bb_min = task2::Vec2d{std::min(c1[0], c2[0]) - R - offset,
std::min(c1[1], c2[1]) - R - offset};
auto bb_max = task2::Vec2d{std::max(c1[0], c2[0]) + R + offset,
std::max(c1[1], c2[1]) + R + offset};
// Create triangle mesh using bounding box and edge length
ex5::TriangleMesh mesh(ex5::TriangleMesh::BBox{bb_min, bb_max}, h);
// Function to select points within circles (assuming select_union is defined in task2)
auto in_circle = [&](const task2::Vec2d& p, task2::Vec2d center, double radius) {
return std::sqrt(std::pow(p[0] - center[0], 2) + std::pow(p[1] - center[1], 2)) <= radius;
};
// Select and remove vertices inside both inner circles (union)
std::unordered_set<size_t> remove_inner;
for (size_t i = 0; i < mesh.getVertices().size(); ++i) {
const auto& v = mesh.getVertices()[i];
if (in_circle(v, c1, r) && in_circle(v, c2, r)) {
remove_inner.insert(i);
}
}
mesh.remove_vertices(remove_inner);
// Select and remove vertices outside both outer circles (union - inverted)
std::unordered_set<size_t> remove_outer;
for (size_t i = 0; i < mesh.getVertices().size(); ++i) {
const auto& v = mesh.getVertices()[i];
if (!in_circle(v, c1, R) && !in_circle(v, c2, R)) {
remove_outer.insert(i);
}
}
mesh.remove_vertices(remove_outer);
return mesh;
}
} // namespace task3