| /* |
| * 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. |
| */ |
| |
| #ifndef INK_STROKE_MODELER_INTERNAL_STYLUS_STATE_MODELER_H_ |
| #define INK_STROKE_MODELER_INTERNAL_STYLUS_STATE_MODELER_H_ |
| |
| #include <deque> |
| #include <ostream> |
| |
| #include "ink_stroke_modeler/internal/internal_types.h" |
| #include "ink_stroke_modeler/params.h" |
| #include "ink_stroke_modeler/types.h" |
| |
| namespace ink { |
| namespace stroke_model { |
| |
| // This class is used to model the state of the stylus for a given position, |
| // based on the state of the stylus at the original input points. |
| // |
| // The stylus is modeled by storing the last max_input_samples positions and |
| // states received via Update(); when queried, it treats the stored positions as |
| // a polyline, and finds the closest segment. The returned stylus state is a |
| // linear interpolation between the states associated with the endpoints of the |
| // segment, correcting angles to account for the "wraparound" that occurs at 0 |
| // and 2π. The value used for interpolation is based on how far along the |
| // segment the closest point lies. |
| // |
| // If Update() is called with a state in which a field (i.e. pressure, tilt, or |
| // orientation) has a negative value (indicating no information), then the |
| // results of Query() will be -1 for that field until Reset() is called. This is |
| // tracked independently for each field; e.g., if you pass in tilt = -1, then |
| // pressure and orientation will continue to be interpolated normally. |
| class StylusStateModeler { |
| public: |
| // Adds a position and state pair to the model. During stroke modeling, these |
| // values will be taken from the raw input. |
| void Update(Vec2 position, const StylusState &state); |
| |
| // Clear the model and reset. |
| void Reset(const StylusStateModelerParams ¶ms); |
| |
| // Query the model for the state at the given position. During stroke |
| // modeling, the position will be taken from the modeled input. |
| // |
| // If no Update() calls have been received since the last Reset(), this will |
| // return {.pressure = -1, .tilt = -1, .orientation = -1}. |
| StylusState Query(Vec2 position) const; |
| |
| private: |
| struct PositionAndState { |
| Vec2 position{0}; |
| StylusState state; |
| |
| PositionAndState(Vec2 position_in, const StylusState &state_in) |
| : position(position_in), state(state_in) {} |
| }; |
| |
| bool received_unknown_pressure_ = false; |
| bool received_unknown_tilt_ = false; |
| bool received_unknown_orientation_ = false; |
| |
| std::deque<PositionAndState> positions_and_states_; |
| StylusStateModelerParams params_; |
| }; |
| |
| } // namespace stroke_model |
| } // namespace ink |
| |
| #endif // INK_STROKE_MODELER_INTERNAL_STYLUS_STATE_MODELER_H_ |