File indexing completed on 2024-11-10 04:57:09

0001 /*
0002     SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QtGlobal>
0010 
0011 #include <chrono>
0012 
0013 namespace KWin
0014 {
0015 
0016 /**
0017  * The SpringMotion class simulates the motion of a spring along one dimension using the
0018  * mass-spring-damper model. The sping constant parameter controls the acceleration of the
0019  * spring. The damping ratio controls the oscillation of the spring.
0020  */
0021 class SpringMotion
0022 {
0023 public:
0024     SpringMotion();
0025     SpringMotion(qreal springConstant, qreal dampingRatio);
0026 
0027     /**
0028      * Advance the simulation by the given @a delta milliseconds.
0029      */
0030     void advance(std::chrono::milliseconds delta);
0031     bool isMoving() const;
0032 
0033     /**
0034      * Returns the current velocity.
0035      */
0036     qreal velocity() const;
0037     void setVelocity(qreal velocity);
0038 
0039     /**
0040      * Returns the current position.
0041      */
0042     qreal position() const;
0043     void setPosition(qreal position);
0044 
0045     /**
0046      * Returns the anchor position. It's the position that the spring is pulled towards.
0047      */
0048     qreal anchor() const;
0049     void setAnchor(qreal anchor);
0050 
0051     /**
0052      * Returns the spring constant. It controls the acceleration of the spring.
0053      */
0054     qreal springConstant() const;
0055 
0056     /**
0057      * Returns the damping ratio. It controls the oscillation of the spring. Potential values:
0058      *
0059      * - 0 or undamped: the spring will oscillate indefinitely
0060      * - less than 1 or underdamped: the mass tends to overshoot its starting position, but with
0061      *   every oscillation some energy is dissipated and the oscillation dies away
0062      * - 1 or critically damped: the mass will fail to overshoot and make a single oscillation
0063      * - greater than 1 or overdamped: the mass slowly returns to the anchor position without
0064      *   overshooting
0065      */
0066     qreal dampingRatio() const;
0067 
0068     /**
0069      * If the distance of the mass between two consecutive simulations is smaller than the epsilon
0070      * value, consider that the mass has stopped moving.
0071      */
0072     qreal epsilon() const;
0073     void setEpsilon(qreal epsilon);
0074 
0075 private:
0076     struct State
0077     {
0078         qreal position;
0079         qreal velocity;
0080     };
0081 
0082     struct Slope
0083     {
0084         qreal dp;
0085         qreal dv;
0086     };
0087 
0088     State integrate(const State &state, qreal dt);
0089     Slope evaluate(const State &state, qreal dt, const Slope &slope);
0090 
0091     State m_prev;
0092     State m_next;
0093     qreal m_t;
0094     qreal m_timestep;
0095 
0096     qreal m_anchor;
0097     qreal m_springConstant;
0098     qreal m_dampingRatio;
0099     qreal m_dampingCoefficient;
0100     qreal m_epsilon;
0101 };
0102 
0103 } // namespace KWin