aboutsummaryrefslogtreecommitdiff
path: root/ink_stroke_modeler/params.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ink_stroke_modeler/params.cc')
-rw-r--r--ink_stroke_modeler/params.cc157
1 files changed, 157 insertions, 0 deletions
diff --git a/ink_stroke_modeler/params.cc b/ink_stroke_modeler/params.cc
new file mode 100644
index 0000000..99542e1
--- /dev/null
+++ b/ink_stroke_modeler/params.cc
@@ -0,0 +1,157 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "ink_stroke_modeler/params.h"
+
+#include <cmath>
+
+#include "absl/status/status.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "absl/types/variant.h"
+#include "ink_stroke_modeler/internal/validation.h"
+
+// This convenience macro evaluates the given expression, and if it does not
+// return an OK status, returns and propagates the status.
+#define RETURN_IF_ERROR(expr) \
+ do { \
+ if (auto status = (expr); !status.ok()) return status; \
+ } while (false)
+
+namespace ink {
+namespace stroke_model {
+
+absl::Status ValidatePositionModelerParams(
+ const PositionModelerParams& params) {
+ RETURN_IF_ERROR(ValidateGreaterThanZero(params.spring_mass_constant,
+ "PredictionParams::spring_mass"));
+ return ValidateGreaterThanZero(params.drag_constant,
+ "PredictionParams::drag_ratio");
+}
+
+absl::Status ValidateSamplingParams(const SamplingParams& params) {
+ RETURN_IF_ERROR(ValidateGreaterThanZero(params.min_output_rate,
+ "PredictionParams::min_output_rate"));
+ RETURN_IF_ERROR(ValidateGreaterThanZero(
+ params.end_of_stroke_stopping_distance,
+ "PredictionParams::end_of_stroke_stopping_distance"));
+ return ValidateGreaterThanZero(
+ params.end_of_stroke_max_iterations,
+ "PredictionParams::end_of_stroke_stopping_distance");
+}
+
+absl::Status ValidateStylusStateModelerParams(
+ const StylusStateModelerParams& params) {
+ return ValidateGreaterThanZero(params.max_input_samples,
+ "StylusStateModelerParams::max_input_samples");
+}
+
+absl::Status ValidateWobbleSmootherParams(const WobbleSmootherParams& params) {
+ RETURN_IF_ERROR(ValidateGreaterThanOrEqualToZero(
+ params.timeout.Value(), "WobbleSmootherParams::timeout"));
+ RETURN_IF_ERROR(ValidateGreaterThanOrEqualToZero(
+ params.speed_floor, "WobbleSmootherParams::speed_floor"));
+ RETURN_IF_ERROR(ValidateIsFiniteNumber(
+ params.speed_ceiling, "WobbleSmootherParams::speed_ceiling"));
+ if (params.speed_ceiling < params.speed_floor) {
+ return absl::InvalidArgumentError(absl::Substitute(
+ "WobbleSmootherParams::speed_ceiling must be greater than or "
+ "equal to WobbleSmootherParams::speed_floor ($0). Actual "
+ "value: $1",
+ params.speed_floor, params.speed_ceiling));
+ }
+ return absl::OkStatus();
+}
+
+absl::Status ValidatePredictionParams(const PredictionParams& params) {
+ if (absl::holds_alternative<StrokeEndPredictorParams>(params)) {
+ // Nothing to validate.
+ return absl::OkStatus();
+ }
+
+ const KalmanPredictorParams& kalman_params =
+ absl::get<KalmanPredictorParams>(params);
+ RETURN_IF_ERROR(ValidateGreaterThanZero(
+ kalman_params.process_noise, "KalmanPredictorParams::process_noise"));
+ RETURN_IF_ERROR(
+ ValidateGreaterThanZero(kalman_params.measurement_noise,
+ "KalmanPredictorParams::measurement_noise"));
+ RETURN_IF_ERROR(
+ ValidateGreaterThanZero(kalman_params.min_stable_iteration,
+ "KalmanPredictorParams::min_stable_iteration"));
+ RETURN_IF_ERROR(
+ ValidateGreaterThanZero(kalman_params.max_time_samples,
+ "KalmanPredictorParams::max_time_samples"));
+ RETURN_IF_ERROR(
+ ValidateGreaterThanZero(kalman_params.min_catchup_velocity,
+ "KalmanPredictorParams::min_catchup_velocity"));
+ RETURN_IF_ERROR(
+ ValidateIsFiniteNumber(kalman_params.acceleration_weight,
+ "KalmanPredictorParams::acceleration_weight"));
+ RETURN_IF_ERROR(ValidateIsFiniteNumber(kalman_params.jerk_weight,
+ "KalmanPredictorParams::jerk_weight"));
+ RETURN_IF_ERROR(
+ ValidateGreaterThanZero(kalman_params.prediction_interval.Value(),
+ "KalmanPredictorParams::jerk_weight"));
+
+ const KalmanPredictorParams::ConfidenceParams& confidence_params =
+ kalman_params.confidence_params;
+ RETURN_IF_ERROR(ValidateGreaterThanZero(
+ confidence_params.desired_number_of_samples,
+ "KalmanPredictorParams::ConfidenceParams::desired_number_of_samples"));
+ RETURN_IF_ERROR(ValidateGreaterThanZero(
+ confidence_params.max_estimation_distance,
+ "KalmanPredictorParams::ConfidenceParams::max_estimation_distance"));
+ RETURN_IF_ERROR(ValidateGreaterThanOrEqualToZero(
+ confidence_params.min_travel_speed,
+ "KalmanPredictorParams::ConfidenceParams::min_travel_speed"));
+ RETURN_IF_ERROR(ValidateIsFiniteNumber(
+ confidence_params.max_travel_speed,
+ "KalmanPredictorParams::ConfidenceParams::max_travel_speed"));
+ if (confidence_params.max_travel_speed < confidence_params.min_travel_speed) {
+ return absl::InvalidArgumentError(
+ absl::Substitute("KalmanPredictorParams::ConfidenceParams::max_"
+ "travel_speed must be greater than or equal to "
+ "KalmanPredictorParams::ConfidenceParams::min_"
+ "travel_speed ($0). Actual value: $1",
+ confidence_params.min_travel_speed,
+ confidence_params.max_travel_speed));
+ }
+ RETURN_IF_ERROR(ValidateGreaterThanZero(
+ confidence_params.max_linear_deviation,
+ "KalmanPredictorParams::ConfidenceParams::max_linear_deviation"));
+ if (confidence_params.baseline_linearity_confidence < 0 ||
+ confidence_params.baseline_linearity_confidence > 1) {
+ return absl::InvalidArgumentError(absl::Substitute(
+ "KalmanPredictorParams::ConfidenceParams::baseline_linearity_"
+ "confidence must lie in the interval [0, 1]. Actual value: $0",
+ confidence_params.baseline_linearity_confidence));
+ }
+ return absl::OkStatus();
+}
+
+absl::Status ValidateStrokeModelParams(const StrokeModelParams& params) {
+ RETURN_IF_ERROR(ValidateWobbleSmootherParams(params.wobble_smoother_params));
+ RETURN_IF_ERROR(
+ ValidatePositionModelerParams(params.position_modeler_params));
+ RETURN_IF_ERROR(ValidateSamplingParams(params.sampling_params));
+ RETURN_IF_ERROR(
+ ValidateStylusStateModelerParams(params.stylus_state_modeler_params));
+ return ValidatePredictionParams(params.prediction_params);
+}
+
+} // namespace stroke_model
+} // namespace ink
+
+#undef RETURN_IF_ERROR