mirror of
https://github.com/orange-cpp/omath.git
synced 2026-04-19 11:43:26 +00:00
improvement
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <memory_resource>
|
#include <memory_resource>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -64,9 +65,9 @@ namespace omath::collision
|
|||||||
|
|
||||||
Result out{};
|
Result out{};
|
||||||
|
|
||||||
// Hoisted outside the loop to reuse the allocation across iterations.
|
// Hoisted outside the loop to reuse bucket allocation across iterations.
|
||||||
std::pmr::vector<Edge> boundary{&mem_resource};
|
// Initial bucket count 16 covers a typical horizon without rehashing.
|
||||||
boundary.reserve(16);
|
BoundaryMap boundary{16, &mem_resource};
|
||||||
|
|
||||||
for (int it = 0; it < params.max_iterations; ++it)
|
for (int it = 0; it < params.max_iterations; ++it)
|
||||||
{
|
{
|
||||||
@@ -102,7 +103,7 @@ namespace omath::collision
|
|||||||
|
|
||||||
// Stitch new faces around the horizon and push them directly onto the
|
// Stitch new faces around the horizon and push them directly onto the
|
||||||
// heap — no full O(n log n) rebuild needed.
|
// heap — no full O(n log n) rebuild needed.
|
||||||
for (const auto& e : boundary)
|
for (const auto& [key, e] : boundary)
|
||||||
{
|
{
|
||||||
const int fi = static_cast<int>(faces.size());
|
const int fi = static_cast<int>(faces.size());
|
||||||
faces.emplace_back(make_face(vertexes, e.a, e.b, new_idx));
|
faces.emplace_back(make_face(vertexes, e.a, e.b, new_idx));
|
||||||
@@ -160,6 +161,16 @@ namespace omath::collision
|
|||||||
|
|
||||||
using Heap = std::priority_queue<HeapItem, std::pmr::vector<HeapItem>, HeapCmp>;
|
using Heap = std::priority_queue<HeapItem, std::pmr::vector<HeapItem>, HeapCmp>;
|
||||||
|
|
||||||
|
// Horizon boundary: maps packed(a,b) → Edge.
|
||||||
|
// Opposite edges cancel in O(1) via hash lookup instead of O(h) linear scan.
|
||||||
|
using BoundaryMap = std::pmr::unordered_map<int64_t, Edge>;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr int64_t pack_edge(int a, int b) noexcept
|
||||||
|
{
|
||||||
|
return (static_cast<int64_t>(a) << 32) | static_cast<uint32_t>(b);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static Heap rebuild_heap(const std::pmr::vector<Face>& faces, auto& memory_resource)
|
static Heap rebuild_heap(const std::pmr::vector<Face>& faces, auto& memory_resource)
|
||||||
{
|
{
|
||||||
@@ -178,14 +189,16 @@ namespace omath::collision
|
|||||||
return f.n.dot(p) - f.d > static_cast<FloatingType>(1e-7);
|
return f.n.dot(p) - f.d > static_cast<FloatingType>(1e-7);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_edge_boundary(std::pmr::vector<Edge>& boundary, int a, int b)
|
static void add_edge_boundary(BoundaryMap& boundary, int a, int b)
|
||||||
{
|
{
|
||||||
// Keep edges that appear only once; cancel if opposite already present.
|
// O(1) cancel: if the opposite edge (b→a) is already in the map it is an
|
||||||
auto itb = std::ranges::find_if(boundary, [&](const Edge& e) { return e.a == b && e.b == a; });
|
// internal edge shared by two visible faces and must be removed.
|
||||||
if (itb != boundary.end())
|
// Otherwise this is a horizon edge and we insert it.
|
||||||
boundary.erase(itb);
|
const int64_t rev = pack_edge(b, a);
|
||||||
|
if (const auto it = boundary.find(rev); it != boundary.end())
|
||||||
|
boundary.erase(it);
|
||||||
else
|
else
|
||||||
boundary.emplace_back(a, b);
|
boundary.emplace(pack_edge(a, b), Edge{a, b});
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@@ -266,7 +279,7 @@ namespace omath::collision
|
|||||||
best = &f;
|
best = &f;
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
static void tombstone_visible_faces(std::pmr::vector<Face>& faces, std::pmr::vector<Edge>& boundary,
|
static void tombstone_visible_faces(std::pmr::vector<Face>& faces, BoundaryMap& boundary,
|
||||||
const VectorType& p)
|
const VectorType& p)
|
||||||
{
|
{
|
||||||
boundary.clear();
|
boundary.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user