Wildmeshing Toolkit
Loading...
Searching...
No Matches
CompositeEnvelopes.hpp
1#pragma once
2
3#include <wmtk/SurfaceTagAttributes.h>
4#include <wmtk/envelope/Envelope.hpp>
5#include <wmtk/utils/Logger.hpp>
6
7#include <cstdint>
8#include <map>
9#include <memory>
10#include <mutex>
11#include <shared_mutex>
12#include <utility>
13#include <vector>
14
15namespace wmtk {
16
44class IntersectionEnvelope final : public Envelope
45{
46public:
47 explicit IntersectionEnvelope(std::vector<std::shared_ptr<Envelope>> members)
48 : Envelope(/*exact=*/false)
49 , m_members(std::move(members))
50 {}
51
52 bool is_outside(const std::array<Eigen::Vector3d, 3>& tris) const override
53 {
54 for (const auto& e : m_members) {
55 if (e->is_outside(tris)) return true;
56 }
57 return false;
58 }
59
60 bool is_outside(const Eigen::Vector3d& pts) const override
61 {
62 for (const auto& e : m_members) {
63 if (e->is_outside(pts)) return true;
64 }
65 return false;
66 }
67
68 bool is_outside(const std::array<Eigen::Vector2d, 2>& edge) const override
69 {
70 for (const auto& e : m_members) {
71 if (e->is_outside(edge)) return true;
72 }
73 return false;
74 }
75
76 bool is_outside(const Eigen::Vector2d& pts) const override
77 {
78 for (const auto& e : m_members) {
79 if (e->is_outside(pts)) return true;
80 }
81 return false;
82 }
83
84 const std::vector<std::shared_ptr<Envelope>>& members() const { return m_members; }
85
86private:
87 std::vector<std::shared_ptr<Envelope>> m_members;
88};
89
93class UnionEnvelope final : public Envelope
94{
95public:
96 explicit UnionEnvelope(std::vector<std::shared_ptr<Envelope>> members)
97 : Envelope(/*exact=*/false)
98 , m_members(std::move(members))
99 {}
100
101 bool is_outside(const std::array<Eigen::Vector3d, 3>& tris) const override
102 {
103 for (const auto& e : m_members) {
104 if (!e->is_outside(tris)) return false;
105 }
106 return true;
107 }
108
109 bool is_outside(const Eigen::Vector3d& pts) const override
110 {
111 for (const auto& e : m_members) {
112 if (!e->is_outside(pts)) return false;
113 }
114 return true;
115 }
116
117 bool is_outside(const std::array<Eigen::Vector2d, 2>& edge) const override
118 {
119 for (const auto& e : m_members) {
120 if (!e->is_outside(edge)) return false;
121 }
122 return true;
123 }
124
125 bool is_outside(const Eigen::Vector2d& pts) const override
126 {
127 for (const auto& e : m_members) {
128 if (!e->is_outside(pts)) return false;
129 }
130 return true;
131 }
132
133private:
134 std::vector<std::shared_ptr<Envelope>> m_members;
135};
136
152{
153public:
156 void set(std::vector<std::shared_ptr<Envelope>> members)
157 {
158 if (members.size() > size_t(SurfaceTagAttributes::max_inputs)) {
159 log_and_throw_error(
160 "{} inputs; a tracked simplex records its inputs in {} bits, so at most {} are "
161 "supported",
162 members.size(),
165 }
166 m_members = std::move(members);
167 m_intersections.clear();
168 }
169
170 size_t size() const { return m_members.size(); }
171 bool empty() const { return m_members.empty(); }
172 const std::shared_ptr<Envelope>& member(size_t i) const { return m_members[i]; }
173
174 std::shared_ptr<Envelope> containment(const InputSet set) const
175 {
176 check(set);
177 if ((set & (set - 1)) == 0) return m_members[lowest_bit(set)];
178 // Read-mostly: a set's intersection is built once, then every check only looks it up,
179 // concurrently. An exclusive lock on every lookup serialized the operations' threads.
180 {
181 std::shared_lock<std::shared_mutex> lock(m_mutex);
182 const auto it = m_intersections.find(set);
183 if (it != m_intersections.end()) return it->second;
184 }
185 std::unique_lock<std::shared_mutex> lock(m_mutex);
186 std::shared_ptr<Envelope>& e = m_intersections[set];
187 if (!e) {
188 std::vector<std::shared_ptr<Envelope>> members;
189 for (size_t i = 0; i < m_members.size(); ++i) {
190 if (set & (InputSet(1) << i)) members.push_back(m_members[i]);
191 }
192 e = std::make_shared<IntersectionEnvelope>(std::move(members));
193 }
194 return e;
195 }
196
198 template <typename Point>
199 std::shared_ptr<Envelope> pull(const InputSet set, const Point& p) const
200 {
201 check(set);
202 if ((set & (set - 1)) == 0) return m_members[lowest_bit(set)];
203 std::shared_ptr<Envelope> best;
204 double worst = -1.;
205 for (size_t i = 0; i < m_members.size(); ++i) {
206 if (!(set & (InputSet(1) << i))) continue;
207 const double d2 = m_members[i]->squared_distance(p);
208 if (d2 > worst) {
209 worst = d2;
210 best = m_members[i];
211 }
212 }
213 return best;
214 }
215
216private:
217 void check(const InputSet set) const
218 {
219 if (set == 0) {
220 log_and_throw_error(
221 "a tracked simplex has an empty input set: the insertion or an operation did "
222 "not carry it");
223 }
224 if (m_members.size() < size_t(SurfaceTagAttributes::max_inputs) &&
225 (set >> m_members.size())) {
226 log_and_throw_error(
227 "input set {:#x} names an input beyond the {} that have envelopes",
228 set,
229 m_members.size());
230 }
231 }
232 static size_t lowest_bit(const InputSet set)
233 {
234 size_t i = 0;
235 while (!(set & (InputSet(1) << i))) ++i;
236 return i;
237 }
238
239 std::vector<std::shared_ptr<Envelope>> m_members;
241 mutable std::map<InputSet, std::shared_ptr<Envelope>> m_intersections;
242 mutable std::shared_mutex m_mutex;
243};
244
245} // namespace wmtk
Definition Envelope.hpp:19
One envelope per input, and the containment and the pull of an INPUT SET (bit i = input i; see Surfac...
Definition CompositeEnvelopes.hpp:152
void set(std::vector< std::shared_ptr< Envelope > > members)
Definition CompositeEnvelopes.hpp:156
std::shared_ptr< Envelope > pull(const InputSet set, const Point &p) const
The member of set farthest from p (Vector2d or Vector3d). Ties go to the lower input.
Definition CompositeEnvelopes.hpp:199
std::map< InputSet, std::shared_ptr< Envelope > > m_intersections
Built on first use, under the mutex: the operations ask concurrently.
Definition CompositeEnvelopes.hpp:241
Definition CompositeEnvelopes.hpp:45
bool is_outside(const std::array< Eigen::Vector3d, 3 > &tris) const override
Definition CompositeEnvelopes.hpp:52
static constexpr int max_inputs
One input per bit of InputSet: the width is set there, and only there.
Definition SurfaceTagAttributes.h:130
Definition CompositeEnvelopes.hpp:94
bool is_outside(const std::array< Eigen::Vector3d, 3 > &tris) const override
Definition CompositeEnvelopes.hpp:101