FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
WakeBlend.h
1#pragma once
4
5#include <marenv/wake/WakeField.h>
6#include <marenv/wake/WakeTypes.h>
7
8#include <atomic>
9#include <concepts>
10#include <memory>
11#include <stdexcept>
12
13namespace marenv::wake
14{
22template<class S>
23concept WakeBlendSnapshot = requires(const S& snapshot, double t, const double* pos, WakeSample& out) {
24 { snapshot.Sample(t, pos, out) } -> std::convertible_to<bool>;
25};
26
52template<WakeBlendSnapshot S>
54{
55public:
57 struct State
58 {
59 std::shared_ptr<const S> current;
60 std::shared_ptr<const State> previous;
61 double start;
62 double time;
63 };
64
67
69 static double Weight(double t, double start, double time) { return BlendWeight(t, start, time); }
70
72 [[nodiscard]] std::shared_ptr<const State> Load() const { return m_state.load(); }
73
81 void Publish(std::shared_ptr<const S> next, double start, double time)
82 {
83 const auto inUse = Load();
84 if (inUse && inUse->start + inUse->time > start)
85 throw std::logic_error("WakeBlend::Publish: the previous blend has not ended (R22)");
86 auto previous = inUse && time > 0.0 ? Settled(inUse->current) : nullptr;
87 Install(std::move(next), std::move(previous), start, time);
88 }
89
91 static Sum Evaluate(const State& state, double t, const double pos[3])
92 {
93 Sum sum;
94 const double weight = Weight(t, state.start, state.time);
95 WakeSample sample {};
96 if (weight > 0.0 && state.current->Sample(t, pos, sample))
97 sum.Add(weight, sample);
98 if (weight < 1.0 && state.previous) {
99 const Sum previous = Evaluate(*state.previous, t, pos);
100 if (previous.inside)
101 sum.Add(1.0 - weight, previous);
102 }
103 return sum;
104 }
105
107 static bool Blends(const State& state, double t) { return Weight(t, state.start, state.time) < 1.0; }
108
116 static WakeBlendSamples Samples(const State& state, double t, const double pos[3])
117 {
118 WakeBlendSamples samples;
119 samples.currentInside = state.current->Sample(t, pos, samples.current);
120 if (state.previous)
121 samples.previous = Evaluate(*state.previous, t, pos);
122 samples.start = state.start;
123 samples.time = state.time;
124 return samples;
125 }
126
134 static bool MayReach(const State& state, const WakeQueryRegion& region)
135 {
136 const bool previousSampled = state.previous && Weight(region.tBegin, state.start, state.time) < 1.0;
137 return state.current->MayReach(region) || (previousSampled && MayReach(*state.previous, region));
138 }
139
140private:
142 static std::shared_ptr<const State> Settled(std::shared_ptr<const S> snapshot)
143 {
144 return std::make_shared<const State>(State {std::move(snapshot), nullptr, 0.0, 0.0});
145 }
146
154 void Install(std::shared_ptr<const S> next, std::shared_ptr<const State> previous, double start, double time)
155 {
156 m_state.store(std::make_shared<const State>(State {std::move(next), std::move(previous), start, time}));
157 }
158
159 std::atomic<std::shared_ptr<const State>> m_state;
160};
161} // namespace marenv::wake
Definition WakeBlend.h:54
static bool Blends(const State &state, double t)
Whether the state blends at t or later: the weight of t is below 1, so it still changes (owner ruling...
Definition WakeBlend.h:107
std::shared_ptr< const State > Load() const
The published state, one atomic load; null before the first Publish(). A query loads it once and uses...
Definition WakeBlend.h:72
void Publish(std::shared_ptr< const S > next, double start, double time)
Definition WakeBlend.h:81
static Sum Evaluate(const State &state, double t, const double pos[3])
The sums of the snapshots of state at pos and t, weighted by the blend.
Definition WakeBlend.h:91
static double Weight(double t, double start, double time)
Smoothstep weight of the new snapshot at t; 1 without blending (time <= 0 or NaN)....
Definition WakeBlend.h:69
static WakeBlendSamples Samples(const State &state, double t, const double pos[3])
Definition WakeBlend.h:116
static bool MayReach(const State &state, const WakeQueryRegion &region)
Definition WakeBlend.h:134
Definition WakeBlend.h:23
double BlendWeight(double t, double start, double time)
Definition WakeSampleParts.h:13
Definition WakeSampleParts.h:79
WakeSample current
The snapshot blended to, unweighted.
Definition WakeSampleParts.h:81
bool currentInside
The snapshot blended to has extent at the point.
Definition WakeSampleParts.h:80
double time
Duration of the blend, s.
Definition WakeSampleParts.h:84
WakeBlendSum previous
The state blended from at full weight (a single snapshot, R22); not inside without one.
Definition WakeSampleParts.h:82
double start
Start of the blend, s.
Definition WakeSampleParts.h:83
Definition WakeSampleParts.h:29
void Add(double share, const WakeSample &sample)
Adds a snapshot's sample with its share of the blend.
Definition WakeSampleParts.h:35
bool inside
True once a snapshot contributed.
Definition WakeSampleParts.h:30
One immutable step of the blend chain.
Definition WakeBlend.h:58
double time
Duration of the blend, s; 0 means no blending.
Definition WakeBlend.h:62
double start
Start of the blend, s.
Definition WakeBlend.h:61
std::shared_ptr< const State > previous
The state blended from; null means no wake.
Definition WakeBlend.h:60
std::shared_ptr< const S > current
The snapshot blended to.
Definition WakeBlend.h:59
Definition WakeField.h:17
double tBegin
First query time, s.
Definition WakeField.h:20
Definition WakeTypes.h:21