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