File indexing completed on 2024-04-14 03:49:28

0001 /*
0002     SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 /** \file spring.h
0008  *  \brief Spring class
0009  */
0010 
0011 #ifndef STEPCORE_SPRING_H
0012 #define STEPCORE_SPRING_H
0013 
0014 #include "force.h"
0015 #include "object.h"
0016 #include "particle.h"
0017 #include "rigidbody.h"
0018 #include "vector.h"
0019 
0020 #include <QString>
0021 #include <cmath>
0022 
0023 namespace StepCore
0024 {
0025 
0026 class Spring;
0027 
0028 /** \ingroup errors
0029  *  \brief Errors object for Spring
0030  */
0031 class SpringErrors: public ObjectErrors
0032 {
0033     STEPCORE_OBJECT(SpringErrors)
0034 
0035 public:
0036     /** Constructs SpringErrors */
0037     explicit SpringErrors(Item* owner = nullptr)
0038         : ObjectErrors(owner), _restLengthVariance(0), _stiffnessVariance(0),
0039           _dampingVariance(0), _localPosition1Variance(0,0), _localPosition2Variance(0,0) {}
0040 
0041     /** Get owner as String */
0042     Spring* spring() const;
0043 
0044     /** Get restLength variance */
0045     double restLengthVariance() const { return _restLengthVariance; }
0046     /** Set restLength variance */
0047     void   setRestLengthVariance(double restLengthVariance) {
0048         _restLengthVariance = restLengthVariance; }
0049 
0050     /** Get current length of the spring */
0051     double lengthVariance() const;
0052 
0053     /** Get stiffness variance */
0054     double stiffnessVariance() const { return _stiffnessVariance; }
0055     /** Set stiffness variance */
0056     void   setStiffnessVariance(double stiffnessVariance) {
0057         _stiffnessVariance = stiffnessVariance; }
0058 
0059     /** Get damping variance */
0060     double dampingVariance() const { return _dampingVariance; }
0061     /** Set damping variance */
0062     void   setDampingVariance(double dampingVariance) {
0063         _dampingVariance = dampingVariance; }
0064 
0065     /** Get localPosition1 variance */
0066     Vector2d localPosition1Variance() const { return _localPosition1Variance; }
0067     /** Set localPosition1 variance */
0068     void setLocalPosition1Variance(const Vector2d& localPosition1Variance) {
0069         _localPosition1Variance = localPosition1Variance; }
0070 
0071     /** Get localPosition2 variance */
0072     Vector2d localPosition2Variance() const { return _localPosition2Variance; }
0073     /** Set localPosition2 variance */
0074     void setLocalPosition2Variance(const Vector2d& localPosition2Variance) {
0075         _localPosition2Variance = localPosition2Variance; }
0076 
0077     /** Get position1 variance */
0078     Vector2d position1Variance() const;
0079     /** Get position2 variance */
0080     Vector2d position2Variance() const;
0081 
0082     /** Get velocity1 variance */
0083     Vector2d velocity1Variance() const;
0084     /** Get velocity2 variance */
0085     Vector2d velocity2Variance() const;
0086 
0087     /** Get force variance */
0088     double forceVariance() const;
0089 
0090 protected:
0091     double _restLengthVariance;
0092     double _stiffnessVariance;
0093     double _dampingVariance;
0094 
0095     StepCore::Vector2d _localPosition1Variance;
0096     StepCore::Vector2d _localPosition2Variance;
0097 
0098     friend class Spring;
0099 };
0100 
0101 
0102 /** \ingroup forces
0103  *  \brief Massless spring
0104  *
0105  *  Massless spring is the force between two selected bodies which equals:
0106  *  \f[
0107  *      \overrightarrow{f} = k (\overrightarrow{r} - \overrightarrow{r_0})
0108  *  \f]
0109  *  where:\n
0110  *  \f$k\f$ is Spring::stiffness\n
0111  *  \f$\overrightarrow{r}\f$ is difference of Particle::position
0112  *  of the first and second body\n
0113  *  \f$\overrightarrow{r_0}\f$ is Spring::restLength
0114  *  
0115  *  \todo how to move setBody1() and setBody2() to PairForce ?
0116  */
0117 class Spring : public Force
0118 {
0119     STEPCORE_OBJECT(Spring)
0120 
0121 public:
0122     /** Constructs Spring */
0123     explicit Spring(double restLength = 0, double stiffness = 1, double damping = 0,
0124                 Item* body1 = nullptr, Item* body2 = nullptr);
0125 
0126     void calcForce(bool calcVariances) override;
0127 
0128     /** Get rest length of the spring */
0129     double restLength() const { return _restLength; }
0130     /** Set rest length of the spring */
0131     void   setRestLength(double restLength) { _restLength = restLength; }
0132 
0133     /** Get current length of the spring */
0134     double length() const { return (position2()-position1()).norm(); }
0135 
0136     /** Get stiffness of the spring */
0137     double stiffness() const { return _stiffness; }
0138     /** Set stiffness of the spring */
0139     void   setStiffness(double stiffness) { _stiffness = stiffness; }
0140 
0141     /** Get damping of the spring */
0142     double damping() const { return _damping; }
0143     /** Set damping of the spring */
0144     void setDamping(double damping) { _damping = damping; }
0145 
0146     /** Get pointer to the first body */
0147     Object* body1() const { return _body1; }
0148     /** Set pointer to the first connected body */
0149     void setBody1(Object* body1);
0150 
0151     /** Get pointer to the second body */
0152     Object* body2() const { return _body2; }
0153     /** Set pointer to the second connected body */
0154     void setBody2(Object* body2);
0155 
0156     /** Local position of the first end of the spring on the body
0157      *  or in the world (if the end is not connected) */
0158     Vector2d localPosition1() const { return _localPosition1; }
0159     /** Set local position of the first end of the spring on the body
0160      *  or in the world (if the end is not connected) */
0161     void setLocalPosition1(const Vector2d& localPosition1) { _localPosition1 = localPosition1; }
0162 
0163     /** Local position of the second end of the spring on the body
0164      *  or in the world (if the end is not connected) */
0165     Vector2d localPosition2() const { return _localPosition2; }
0166     /** Set local position of the second end of the spring on the body
0167      *  or in the world (if the end is not connected) */
0168     void setLocalPosition2(const Vector2d& localPosition2) { _localPosition2 = localPosition2; }
0169 
0170     /** Position of the first end of the spring */
0171     Vector2d position1() const;
0172     /** Set position of the first end of the spring (will be ignored the end is connected) */
0173     //void setPosition1(const Vector2d& position1) { if(!_body1) _position1 = position1; }
0174 
0175     /** Position of the second end of the spring */
0176     Vector2d position2() const;
0177     /** Set position of the second end of the spring (will be ignored the end is connected) */
0178     //void setPosition2(const Vector2d& position2) { if(!_body2) _position2 = position2; }
0179     
0180     /** Velocity of the first end of the spring */
0181     Vector2d velocity1() const;
0182 
0183     /** Velocity of the second end of the spring */
0184     Vector2d velocity2() const;
0185 
0186     /** Tension force */
0187     double force() const;
0188 
0189     /** Get first connected Particle */
0190     Particle* particle1() const { return _p1; }
0191     /** Get second connected Particle */
0192     Particle* particle2() const { return _p2; }
0193     /** Get first connected RigidBody */
0194     RigidBody* rigidBody1() const { return _r1; }
0195     /** Get second connected RigidBody */
0196     RigidBody* rigidBody2() const { return _r2; }
0197 
0198     //void worldItemRemoved(Item* item);
0199     //void setWorld(World* world);
0200 
0201     /** Get (and possibly create) SpringErrors object */
0202     SpringErrors* springErrors() { return static_cast<SpringErrors*>(objectErrors()); }
0203 
0204 protected:
0205     ObjectErrors* createObjectErrors() override { return new SpringErrors(this); }
0206 
0207     Object* _body1;
0208     Object* _body2;
0209     double _restLength;
0210     double _stiffness;
0211     double _damping;
0212     Vector2d _localPosition1;
0213     Vector2d _localPosition2;
0214 
0215     Particle*  _p1;
0216     Particle*  _p2;
0217     RigidBody* _r1;
0218     RigidBody* _r2;
0219 
0220     friend class SpringErrors;
0221 };
0222 
0223 } // namespace StepCore
0224 
0225 #endif
0226