Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions ink/strokes/internal/brush_tip_modeler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,8 @@ bool SourceDependsOnNextModeledInput(BrushBehavior::Source source) {
}

Duration32 TimeSinceLastInput(const InputModelerState& input_modeler_state) {
// TODO: b/287041801 - Do we need to consider predicted inputs here too?
return input_modeler_state.complete_elapsed_time -
input_modeler_state.total_real_elapsed_time;
input_modeler_state.full_input_metrics.elapsed_time;
}

} // namespace
Expand Down Expand Up @@ -536,9 +535,10 @@ InputMetrics BrushTipModeler::CalculateMaxFixedInputMetrics(
return {
.traveled_distance =
last_stable_input.traveled_distance -
std::max(distance_remaining_behavior_upper_bound_,
distance_fraction_behavior_upper_bound_ *
input_modeler_state.complete_traveled_distance),
std::max(
distance_remaining_behavior_upper_bound_,
distance_fraction_behavior_upper_bound_ *
input_modeler_state.full_input_metrics.traveled_distance),
.elapsed_time = last_stable_input.elapsed_time -
time_since_input_behavior_upper_bound_,
};
Expand Down
21 changes: 12 additions & 9 deletions ink/strokes/internal/brush_tip_modeler_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,16 @@ std::optional<float> GetTiltY(Angle tilt, Angle orientation) {
float GetPredictedDistanceTraveledInStrokeUnits(
const InputModelerState& input_modeler_state,
const ModeledStrokeInput& input) {
return std::max(
0.f, input.traveled_distance - input_modeler_state.total_real_distance);
return std::max(0.f,
input.traveled_distance -
input_modeler_state.real_input_metrics.traveled_distance);
}

Duration32 GetPredictedTimeElapsed(const InputModelerState& input_modeler_state,
const ModeledStrokeInput& input) {
return std::max(
Duration32::Zero(),
input.elapsed_time - input_modeler_state.total_real_elapsed_time);
input.elapsed_time - input_modeler_state.real_input_metrics.elapsed_time);
}

// Returns the value of the given `Source` at the given modeled input, or
Expand Down Expand Up @@ -154,7 +155,7 @@ std::optional<float> GetSourceValue(
case BrushBehavior::Source::kPredictedTimeElapsedInSeconds:
return GetPredictedTimeElapsed(input_modeler_state, input).ToSeconds();
case BrushBehavior::Source::kDistanceRemainingInMultiplesOfBrushSize:
return (input_modeler_state.complete_traveled_distance -
return (input_modeler_state.full_input_metrics.traveled_distance -
input.traveled_distance) /
brush_size;
case BrushBehavior::Source::kTimeSinceInputInSeconds:
Expand All @@ -163,7 +164,7 @@ std::optional<float> GetSourceValue(
case BrushBehavior::Source::kTimeSinceStrokeEndInSeconds:
if (!input_modeler_state.inputs_are_finished) return 0.0f;
return (input_modeler_state.complete_elapsed_time -
input_modeler_state.total_real_elapsed_time)
input_modeler_state.full_input_metrics.elapsed_time)
.ToSeconds();
case BrushBehavior::Source::
kAccelerationInMultiplesOfBrushSizePerSecondSquared:
Expand Down Expand Up @@ -229,11 +230,13 @@ std::optional<float> GetSourceValue(
return Vec::DotProduct(input.acceleration,
input.velocity.AsUnitVec().Orthogonal()) *
input_modeler_state.stroke_unit_length->ToCentimeters();
case BrushBehavior::Source::kDistanceRemainingAsFractionOfStrokeLength:
return input_modeler_state.complete_traveled_distance == 0.0f
case BrushBehavior::Source::kDistanceRemainingAsFractionOfStrokeLength: {
float stroke_length =
input_modeler_state.full_input_metrics.traveled_distance;
return stroke_length == 0.0f
? 0.0f
: 1.0f - input.traveled_distance /
input_modeler_state.complete_traveled_distance;
: 1.0f - input.traveled_distance / stroke_length;
}
}
return std::nullopt;
}
Expand Down
14 changes: 7 additions & 7 deletions ink/strokes/internal/brush_tip_modeler_helpers_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ TEST_F(ProcessBehaviorNodeTest,
};
context_.brush_size = 3;
current_input_.traveled_distance = 15;
input_modeler_state_.total_real_distance = 9;
input_modeler_state_.real_input_metrics.traveled_distance = 9;
ProcessBehaviorNode(source_node, context_);
EXPECT_THAT(stack_, ElementsAre(0.2f));
}
Expand All @@ -380,7 +380,7 @@ TEST_F(ProcessBehaviorNodeTest, SourceNodePredictedTimeElapsedInSeconds) {
.source_value_range = {0, 10},
};
current_input_.elapsed_time = Duration32::Seconds(15);
input_modeler_state_.total_real_elapsed_time = Duration32::Seconds(9);
input_modeler_state_.real_input_metrics.elapsed_time = Duration32::Seconds(9);
ProcessBehaviorNode(source_node, context_);
EXPECT_THAT(stack_, ElementsAre(0.6f));
}
Expand All @@ -393,7 +393,7 @@ TEST_F(ProcessBehaviorNodeTest,
};
context_.brush_size = 3;
current_input_.traveled_distance = 9;
input_modeler_state_.complete_traveled_distance = 15;
input_modeler_state_.full_input_metrics.traveled_distance = 15;
ProcessBehaviorNode(source_node, context_);
EXPECT_THAT(stack_, ElementsAre(0.2f));
}
Expand All @@ -416,7 +416,7 @@ TEST_F(ProcessBehaviorNodeTest, SourceNodeTimeSinceStrokeEndInSeconds) {
};

// If `inputs_are_finished` is still `false`, the source node emits zero.
input_modeler_state_.total_real_elapsed_time = Duration32::Seconds(3);
input_modeler_state_.full_input_metrics.elapsed_time = Duration32::Seconds(3);
input_modeler_state_.complete_elapsed_time = Duration32::Seconds(5);
input_modeler_state_.inputs_are_finished = false;
ProcessBehaviorNode(source_node, context_);
Expand Down Expand Up @@ -628,7 +628,7 @@ TEST_F(ProcessBehaviorNodeTest,

input_modeler_state_.stroke_unit_length = PhysicalDistance::Centimeters(0.1f);
current_input_.traveled_distance = 50;
input_modeler_state_.total_real_distance = 46;
input_modeler_state_.real_input_metrics.traveled_distance = 46;
ProcessBehaviorNode(source_node, context_);
EXPECT_THAT(stack_, ElementsAre(FloatNear(0.4f, 1e-5)));

Expand Down Expand Up @@ -776,7 +776,7 @@ TEST_F(ProcessBehaviorNodeTest,
};

current_input_.traveled_distance = 3.0f;
input_modeler_state_.complete_traveled_distance = 12.0f;
input_modeler_state_.full_input_metrics.traveled_distance = 12.0f;
ProcessBehaviorNode(source_node, context_);
EXPECT_THAT(stack_, ElementsAre(0.75f));
}
Expand All @@ -793,7 +793,7 @@ TEST_F(ProcessBehaviorNodeTest,
// then the fraction of distance remaining isn't well-defined (0/0), so we
// arbitrarily define that as 0% distance remaining.
current_input_.traveled_distance = 0.0f;
input_modeler_state_.complete_traveled_distance = 0.0f;
input_modeler_state_.full_input_metrics.traveled_distance = 0.0f;
ProcessBehaviorNode(source_node, context_);
EXPECT_THAT(stack_, ElementsAre(0.0f));
}
Expand Down
18 changes: 8 additions & 10 deletions ink/strokes/internal/modeled_stroke_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,19 @@ struct InputModelerState {
// space and physical space is unknown (possibly because the current stroke
// has no inputs yet) or ill-defined.
std::optional<PhysicalDistance> stroke_unit_length;
// The total modeled distance/time from the start of the stroke until the last
// "real" (i.e. non-predicted) modeled input so far.
InputMetrics real_input_metrics;
// The total modeled distance/time from the start of the stroke until the last
// modeled input so far (including unstable/predicted modeled inputs).
InputMetrics full_input_metrics;
// The modeled time elapsed from the start of the stroke until either "now" or
// the last modeled input, whichever comes later.
//
// This value may be different from the `current_elapsed_time` value passed to
// `ExtendStroke()` due to modeling and prediction. If `GetModeledInputs()` is
// not empty, this value will always be greater than or equal to
// `GetModeledInputs().back().elapsed_time`.
// `ExtendStroke()` due to modeling and prediction. This value will always be
// greater than or equal to `full_input_metrics.elapsed_time`.
Duration32 complete_elapsed_time = Duration32::Zero();
// The modeled distance traveled from the start of the stroke to the last
// modeled input (including unstable/predicted modeled inputs).
float complete_traveled_distance = 0;
// The total elapsed time for "real" (i.e. non-predicted) inputs only.
Duration32 total_real_elapsed_time = Duration32::Zero();
// The total traveled distance for "real" (i.e. non-predicted) inputs only.
float total_real_distance = 0;
// The number of "stable" elements at the start of `GetModeledInputs()`.
//
// These will not be removed or modified by subsequent calls to
Expand Down
25 changes: 21 additions & 4 deletions ink/strokes/internal/stroke_input_modeler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
#include "ink/strokes/internal/stroke_input_modeler.h"

#include <algorithm>
#include <cstddef>
#include <memory>
#include <variant>

#include "absl/base/nullability.h"
#include "absl/log/absl_check.h"
#include "ink/brush/brush_family.h"
#include "ink/strokes/input/stroke_input_batch.h"
#include "ink/strokes/internal/modeled_stroke_input.h"
#include "ink/strokes/internal/stroke_input_modeler/input_model_impl.h"
#include "ink/strokes/internal/stroke_input_modeler/naive_input_modeler.h"
#include "ink/strokes/internal/stroke_input_modeler/sliding_window_input_modeler.h"
Expand Down Expand Up @@ -78,15 +80,17 @@ void StrokeInputModeler::ExtendStroke(const StrokeInputBatch& real_inputs,
input_model_impl_->ExtendStroke(state_, modeled_inputs_, real_inputs,
predicted_inputs);
ABSL_DCHECK_LE(state_.stable_input_count, state_.real_input_count);
ABSL_DCHECK_LE(state_.real_input_count, modeled_inputs_.size());

SetMetricsFromInputCount(state_.real_input_count, state_.real_input_metrics);
SetMetricsFromInputCount(modeled_inputs_.size(), state_.full_input_metrics);
state_.complete_elapsed_time =
std::max(state_.complete_elapsed_time, current_elapsed_time);
std::max(state_.full_input_metrics.elapsed_time, current_elapsed_time);
}

void StrokeInputModeler::ErasePredictedModeledInputs() {
modeled_inputs_.resize(state_.real_input_count);
state_.complete_elapsed_time = state_.total_real_elapsed_time;
state_.complete_traveled_distance = state_.total_real_distance;
state_.full_input_metrics = state_.real_input_metrics;
state_.complete_elapsed_time = state_.real_input_metrics.elapsed_time;
}

void StrokeInputModeler::SetToolTypeAndStrokeUnitLength(
Expand All @@ -101,4 +105,17 @@ void StrokeInputModeler::SetToolTypeAndStrokeUnitLength(
}
}

void StrokeInputModeler::SetMetricsFromInputCount(size_t modeled_input_count,
InputMetrics& metrics) {
ABSL_DCHECK_LE(modeled_input_count, modeled_inputs_.size());
if (modeled_input_count == 0) {
metrics.elapsed_time = Duration32::Zero();
metrics.traveled_distance = 0;
} else {
const ModeledStrokeInput& input = modeled_inputs_[modeled_input_count - 1];
metrics.elapsed_time = input.elapsed_time;
metrics.traveled_distance = input.traveled_distance;
}
}

} // namespace ink::strokes_internal
5 changes: 5 additions & 0 deletions ink/strokes/internal/stroke_input_modeler.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ class StrokeInputModeler {
void SetToolTypeAndStrokeUnitLength(const StrokeInputBatch& real_inputs,
const StrokeInputBatch& predicted_inputs);

// Helper method for `ExtendStroke()`. Sets `metrics` based on the first
// `modeled_input_count` inputs in `modeled_inputs_`.
void SetMetricsFromInputCount(size_t modeled_input_count,
InputMetrics& metrics);

InputModelerState state_;
std::vector<ModeledStrokeInput> modeled_inputs_;
absl_nullable std::unique_ptr<InputModelImpl> input_model_impl_;
Expand Down
1 change: 0 additions & 1 deletion ink/strokes/internal/stroke_input_modeler/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ cc_library(
"//ink/types:duration",
"//ink/types:numbers",
"//ink/types:physical_distance",
"@com_google_absl//absl/cleanup",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/types:span",
"@ink_stroke_modeler//ink_stroke_modeler:params",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ void NaiveInputModeler::ExtendStroke(
const StrokeInputBatch& real_inputs,
const StrokeInputBatch& predicted_inputs) {
AppendInputs(state, modeled_inputs, real_inputs);
if (!modeled_inputs.empty()) {
const ModeledStrokeInput& last_real_input = modeled_inputs.back();
state.total_real_elapsed_time = last_real_input.elapsed_time;
state.total_real_distance = last_real_input.traveled_distance;
}
state.real_input_count = modeled_inputs.size();
state.stable_input_count = state.real_input_count;
AppendInputs(state, modeled_inputs, predicted_inputs);
Expand All @@ -60,8 +55,6 @@ void NaiveInputModeler::AppendInputs(
acceleration = (velocity - last_input.velocity) / delta_seconds;
}
}
state.complete_elapsed_time = input.elapsed_time;
state.complete_traveled_distance = traveled_distance;
modeled_inputs.push_back(ModeledStrokeInput{
.position = input.position,
.velocity = velocity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,10 @@ TEST(NaiveInputModelerTest, RealAndCompleteElapsedTime) {
/*brush_epsilon=*/0.001);
modeler.ExtendStroke(input_batches[1], input_batches[2], Duration32::Zero());

EXPECT_THAT(modeler.GetState().total_real_elapsed_time,
EXPECT_THAT(modeler.GetState().real_input_metrics.elapsed_time,
Duration32Eq(Duration32::Seconds(1)));
EXPECT_THAT(modeler.GetState().full_input_metrics.elapsed_time,
Duration32Eq(Duration32::Seconds(2)));
EXPECT_THAT(modeler.GetState().complete_elapsed_time,
Duration32Eq(Duration32::Seconds(2)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ void SlidingWindowInputModeler::ExtendStroke(
int raw_input_queue_real_input_count = raw_input_queue_.Size();
AppendRawInputsToQueue(state, predicted_inputs);
ModelUnstableInputs(state, modeled_inputs, raw_input_queue_real_input_count);
UpdateRealAndCompleteDistanceAndTime(state, modeled_inputs);
MarkStableModeledInputs(state, modeled_inputs);
TrimRawInputQueue(state, modeled_inputs, raw_input_queue_real_input_count);
}
Expand Down Expand Up @@ -465,29 +464,19 @@ void SlidingWindowInputModeler::ModelUnstableInputs(
modeled_inputs, state.stable_input_count, half_window_size_);
}

void SlidingWindowInputModeler::UpdateRealAndCompleteDistanceAndTime(
InputModelerState& state, std::vector<ModeledStrokeInput>& modeled_inputs) {
if (state.real_input_count > 0) {
const ModeledStrokeInput& last_real_input =
modeled_inputs[state.real_input_count - 1];
state.total_real_elapsed_time = last_real_input.elapsed_time;
state.total_real_distance = last_real_input.traveled_distance;
}
if (!modeled_inputs.empty()) {
const ModeledStrokeInput& last_input = modeled_inputs.back();
state.complete_traveled_distance = last_input.traveled_distance;
state.complete_elapsed_time = last_input.elapsed_time;
}
}

void SlidingWindowInputModeler::MarkStableModeledInputs(
InputModelerState& state, std::vector<ModeledStrokeInput>& modeled_inputs) {
ABSL_DCHECK_LE(state.stable_input_count, state.real_input_count);
ABSL_DCHECK_LE(state.real_input_count, modeled_inputs.size());

if (state.real_input_count == 0) return;
const ModeledStrokeInput& last_real_input =
modeled_inputs[state.real_input_count - 1];

while (state.stable_input_count < state.real_input_count &&
modeled_inputs[state.stable_input_count].elapsed_time +
half_window_size_ <
state.total_real_elapsed_time) {
last_real_input.elapsed_time) {
++state.stable_input_count;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,6 @@ class SlidingWindowInputModeler : public InputModelImpl {
std::vector<ModeledStrokeInput>& modeled_inputs, Duration32 elapsed_time,
int& start_index, int& end_index);

// Helper method for `ExtendStroke()`. Updates `state` fields for `total_real`
// and `complete` distance and time, based on current `modeled_inputs` and
// `state.real_input_count`.
void UpdateRealAndCompleteDistanceAndTime(
InputModelerState& state,
std::vector<ModeledStrokeInput>& modeled_inputs);

// Helper method for `ExtendStroke()`. Marks stable all real modeled inputs
// that are at least `half_window_size_` before
// `state.total_real_elapsed_time` (and which will therefore not change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <optional>
#include <vector>

#include "absl/cleanup/cleanup.h"
#include "absl/log/absl_check.h"
#include "ink/brush/brush_family.h"
#include "ink/geometry/angle.h"
Expand Down Expand Up @@ -149,10 +148,6 @@ void SpringBasedInputModeler::ExtendStroke(
InputModelerState& state, std::vector<ModeledStrokeInput>& modeled_inputs,
const StrokeInputBatch& real_inputs,
const StrokeInputBatch& predicted_inputs) {
absl::Cleanup update_time_and_distance = [&]() {
UpdateStateTimeAndDistance(state, modeled_inputs);
};

if (!last_real_stroke_input_.has_value()) {
ResetStrokeModeler(stroke_modeler_, version_, brush_epsilon_,
state.stroke_unit_length);
Expand Down Expand Up @@ -278,22 +273,4 @@ void SpringBasedInputModeler::ModelInput(
}
}

void SpringBasedInputModeler::UpdateStateTimeAndDistance(
InputModelerState& state, std::vector<ModeledStrokeInput>& modeled_inputs) {
if (modeled_inputs.empty()) {
return;
}

const ModeledStrokeInput& last_input = modeled_inputs.back();
state.complete_elapsed_time = last_input.elapsed_time;
state.complete_traveled_distance = last_input.traveled_distance;

if (state.real_input_count == 0) return;

const ModeledStrokeInput& last_real_input =
modeled_inputs[state.real_input_count - 1];
state.total_real_distance = last_real_input.traveled_distance;
state.total_real_elapsed_time = last_real_input.elapsed_time;
}

} // namespace ink::strokes_internal
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ class SpringBasedInputModeler : public InputModelImpl {
void ModelInput(std::vector<ModeledStrokeInput>& modeled_inputs,
const StrokeInput& input, bool last_input_in_update);

// Updates `state` elapsed time and distance properties.
void UpdateStateTimeAndDistance(
InputModelerState& state,
std::vector<ModeledStrokeInput>& modeled_inputs);

Version version_;
// We use `brush_epsilon` to set up the parameters for `stroke_modeler_`, and
// to determine the minimum distance that a new `stroke_model::Result` must
Expand Down
Loading
Loading