1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
/*
SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
/** \file spring.h
* \brief Spring class
*/
#ifndef STEPCORE_SPRING_H
#define STEPCORE_SPRING_H
#include "force.h"
#include "object.h"
#include "particle.h"
#include "rigidbody.h"
#include "vector.h"
#include <QString>
#include <cmath>
namespace StepCore
{
class Spring;
/** \ingroup errors
* \brief Errors object for Spring
*/
class SpringErrors: public ObjectErrors
{
STEPCORE_OBJECT(SpringErrors)
public:
/** Constructs SpringErrors */
explicit SpringErrors(Item* owner = nullptr)
: ObjectErrors(owner), _restLengthVariance(0), _stiffnessVariance(0),
_dampingVariance(0), _localPosition1Variance(0,0), _localPosition2Variance(0,0) {}
/** Get owner as String */
Spring* spring() const;
/** Get restLength variance */
double restLengthVariance() const { return _restLengthVariance; }
/** Set restLength variance */
void setRestLengthVariance(double restLengthVariance) {
_restLengthVariance = restLengthVariance; }
/** Get current length of the spring */
double lengthVariance() const;
/** Get stiffness variance */
double stiffnessVariance() const { return _stiffnessVariance; }
/** Set stiffness variance */
void setStiffnessVariance(double stiffnessVariance) {
_stiffnessVariance = stiffnessVariance; }
/** Get damping variance */
double dampingVariance() const { return _dampingVariance; }
/** Set damping variance */
void setDampingVariance(double dampingVariance) {
_dampingVariance = dampingVariance; }
/** Get localPosition1 variance */
Vector2d localPosition1Variance() const { return _localPosition1Variance; }
/** Set localPosition1 variance */
void setLocalPosition1Variance(const Vector2d& localPosition1Variance) {
_localPosition1Variance = localPosition1Variance; }
/** Get localPosition2 variance */
Vector2d localPosition2Variance() const { return _localPosition2Variance; }
/** Set localPosition2 variance */
void setLocalPosition2Variance(const Vector2d& localPosition2Variance) {
_localPosition2Variance = localPosition2Variance; }
/** Get position1 variance */
Vector2d position1Variance() const;
/** Get position2 variance */
Vector2d position2Variance() const;
/** Get velocity1 variance */
Vector2d velocity1Variance() const;
/** Get velocity2 variance */
Vector2d velocity2Variance() const;
/** Get force variance */
double forceVariance() const;
protected:
double _restLengthVariance;
double _stiffnessVariance;
double _dampingVariance;
StepCore::Vector2d _localPosition1Variance;
StepCore::Vector2d _localPosition2Variance;
friend class Spring;
};
/** \ingroup forces
* \brief Massless spring
*
* Massless spring is the force between two selected bodies which equals:
* \f[
* \overrightarrow{f} = k (\overrightarrow{r} - \overrightarrow{r_0})
* \f]
* where:\n
* \f$k\f$ is Spring::stiffness\n
* \f$\overrightarrow{r}\f$ is difference of Particle::position
* of the first and second body\n
* \f$\overrightarrow{r_0}\f$ is Spring::restLength
*
* \todo how to move setBody1() and setBody2() to PairForce ?
*/
class Spring : public Force
{
STEPCORE_OBJECT(Spring)
public:
/** Constructs Spring */
explicit Spring(double restLength = 0, double stiffness = 1, double damping = 0,
Item* body1 = nullptr, Item* body2 = nullptr);
void calcForce(bool calcVariances) override;
/** Get rest length of the spring */
double restLength() const { return _restLength; }
/** Set rest length of the spring */
void setRestLength(double restLength) { _restLength = restLength; }
/** Get current length of the spring */
double length() const { return (position2()-position1()).norm(); }
/** Get stiffness of the spring */
double stiffness() const { return _stiffness; }
/** Set stiffness of the spring */
void setStiffness(double stiffness) { _stiffness = stiffness; }
/** Get damping of the spring */
double damping() const { return _damping; }
/** Set damping of the spring */
void setDamping(double damping) { _damping = damping; }
/** Get pointer to the first body */
Object* body1() const { return _body1; }
/** Set pointer to the first connected body */
void setBody1(Object* body1);
/** Get pointer to the second body */
Object* body2() const { return _body2; }
/** Set pointer to the second connected body */
void setBody2(Object* body2);
/** Local position of the first end of the spring on the body
* or in the world (if the end is not connected) */
Vector2d localPosition1() const { return _localPosition1; }
/** Set local position of the first end of the spring on the body
* or in the world (if the end is not connected) */
void setLocalPosition1(const Vector2d& localPosition1) { _localPosition1 = localPosition1; }
/** Local position of the second end of the spring on the body
* or in the world (if the end is not connected) */
Vector2d localPosition2() const { return _localPosition2; }
/** Set local position of the second end of the spring on the body
* or in the world (if the end is not connected) */
void setLocalPosition2(const Vector2d& localPosition2) { _localPosition2 = localPosition2; }
/** Position of the first end of the spring */
Vector2d position1() const;
/** Set position of the first end of the spring (will be ignored the end is connected) */
//void setPosition1(const Vector2d& position1) { if(!_body1) _position1 = position1; }
/** Position of the second end of the spring */
Vector2d position2() const;
/** Set position of the second end of the spring (will be ignored the end is connected) */
//void setPosition2(const Vector2d& position2) { if(!_body2) _position2 = position2; }
/** Velocity of the first end of the spring */
Vector2d velocity1() const;
/** Velocity of the second end of the spring */
Vector2d velocity2() const;
/** Tension force */
double force() const;
/** Get first connected Particle */
Particle* particle1() const { return _p1; }
/** Get second connected Particle */
Particle* particle2() const { return _p2; }
/** Get first connected RigidBody */
RigidBody* rigidBody1() const { return _r1; }
/** Get second connected RigidBody */
RigidBody* rigidBody2() const { return _r2; }
//void worldItemRemoved(Item* item);
//void setWorld(World* world);
/** Get (and possibly create) SpringErrors object */
SpringErrors* springErrors() { return static_cast<SpringErrors*>(objectErrors()); }
protected:
ObjectErrors* createObjectErrors() override { return new SpringErrors(this); }
Object* _body1;
Object* _body2;
double _restLength;
double _stiffness;
double _damping;
Vector2d _localPosition1;
Vector2d _localPosition2;
Particle* _p1;
Particle* _p2;
RigidBody* _r1;
RigidBody* _r2;
friend class SpringErrors;
};
} // namespace StepCore
#endif
|