CellModules
PhysicsConstraints.hpp
Go to the documentation of this file.
1#ifndef PHYSICSCONSTRAINTS_HPP
2#define PHYSICSCONSTRAINTS_HPP
3
4#include <vector>
5#include <math.h>
6#include <mecacell/mecacell.h>
7#include <functional>
8
14private:
19 class Plane {
20 public:
23 bool sticky;
32 Plane(MecaCell::Vec _n = MecaCell::Vec(0, 1, 0), MecaCell::Vec _p = MecaCell::Vec(0, 0, 0), bool _sticky = false) {
33 n = _n;
34 n.normalize();
35 p = _p;
36 sticky = _sticky;
37 }
38
46 if (n.x() * c.x() + n.y() * c.y() + n.z() * c.z() + (-n.x() * p.x() - n.y() * p.y() - n.z() * p.z()) < 0)
47 return -(MecaCell::Vec::getProjectionOnPlane(p, n, c) - c).length();
48 else
49 return (MecaCell::Vec::getProjectionOnPlane(p, n, c) - c).length();
50 }
51 };
53
58 class SymAxis {
59 public:
62 double length;
64 bool fitShape;
66 std::function<double(double, MecaCell::Vec, MecaCell::Vec)> radiusFunction;
79 SymAxis(MecaCell::Vec a, MecaCell::Vec o, double l, double mef, bool fs, double av, std::function<double(double, MecaCell::Vec, MecaCell::Vec)> rf)
81 };
83
85 double ratioPoisson2OnYoung = 0.0000000000001;
87 double radiusBox = -1;
88
89public:
90 double overlapAdhesion = 0.2;
91
96
104 void addPlane(MecaCell::Vec _n = MecaCell::Vec(0, 1, 0), MecaCell::Vec _p = MecaCell::Vec(0, 0, 0), bool _sticky = false) {
105 planes.push_back(Plane(_n, _p, _sticky));
106 }
107
119 void addSymAxis(std::function<double(double, MecaCell::Vec, MecaCell::Vec)> _radiusFunction, MecaCell::Vec _axis = MecaCell::Vec(0., 1., 0.), MecaCell::Vec _origin = MecaCell::Vec(0., 0., 0.), double _length = 100, double _maxEffectRadius = 100, bool _fitShape = true, double _velocity_attraction = 0.001) {
120 symAxes.push_back(SymAxis(_axis, _origin, _length, _maxEffectRadius, _fitShape, _velocity_attraction, _radiusFunction));
121 }
122
129 velocities.push_back(_v);
130 }
131
139 template<typename cell_t>
142 for (auto symAxis : symAxes) {
143 double distOnAxis = symAxis.axis.normalized().dot((c->getBody().getPosition() - symAxis.origin));
144 // proj dist to origin
145 if (distOnAxis > 0 && distOnAxis < symAxis.length) {
146 // dist to axis
147 MecaCell::Vec dir = (c->getBody().getPosition() - (symAxis.axis.normalized() * distOnAxis + symAxis.origin));
148 double sqDistToAxis = dir.sqlength();
149 if (sqDistToAxis > 0) dir.normalize();
150
151 if (sqDistToAxis < symAxis.maxEffectRadius * symAxis.maxEffectRadius) {
152 double targetRadius = symAxis.radiusFunction(distOnAxis / symAxis.length, symAxis.origin, symAxis.axis.normalized() * symAxis.length);
153 double sqDistToRadius = targetRadius * targetRadius - sqDistToAxis;
154 if ((sqDistToRadius > 0 && symAxis.fitShape) || sqDistToRadius < 0) {
155 // push cell to radius
156 ret = dir * (sqDistToRadius > 0 ? 1 : -1) * symAxis.attraction_velocity;
157 }
158 }
159 }
160 }
161 return ret;
162 }
163
171 template<typename cell_t>
173 // force pushing cells to center
174 double distToCenter = c->getBody().getPosition().length();
175 MecaCell::Vec ret = (radiusBox == -1 || distToCenter <= radiusBox)
177 : -c->getBody().getPosition().normalized() * std::pow(distToCenter - radiusBox, 2.0) * velocity_center_attraction;
178 // constraints velocities
179 for (auto v : velocities)
180 ret += v;
181 // shape constraints
183 return ret;
184 }
185
193 void setCurvedBox(double radiusBoxPlane, double curvedDistToMaxSpeed, double maxSpeed) {
194 radiusBox = radiusBoxPlane;
195 velocity_center_attraction = maxSpeed / std::pow(curvedDistToMaxSpeed, 2.0);
196 }
197
204 void setPoissonAndYoungOfPlane(double poisson, double young) {
205 ratioPoisson2OnYoung = (1.0 - poisson * poisson) / young;
206 }
207
214 template<typename cell_t>
215 void applyPlaneConstraints(cell_t* c) {
216 double dist, delta, R, E, Frep, adhesion, Fadh;
217 for (auto plane : planes) {
218 if (plane.sticky) {
219 dist = std::abs(plane.distanceToPoint(c->getBody().getPosition()));
220 if (dist <= c->getBody().getBoundingBoxRadius()) {
221 delta = c->getBody().getBoundingBoxRadius() - dist;
222 R = 1.0 / (1.0 / c->getBody().getBoundingBoxRadius() + 1.0 / c->getBody().getBoundingBoxRadius());
223 E = 1.0 /
224 ((1.0 - c->getBody().getPoissonNumber() * c->getBody().getPoissonNumber()) / c->getBody().getYoungModulus() +
226
227 Frep = 4.0 / 3.0 * E * sqrt(R) * pow(delta, 3.0 / 2.0);
228 adhesion = (4.0 * sqrt(overlapAdhesion * c->getBody().getBoundingBoxRadius()) * E * sqrt(R)) / (3.0 * M_PI * M_PI * R * R);
229 Fadh = -M_PI * M_PI * R * R * adhesion * delta;
230
231 c->getBody().receiveForce(plane.n * (Frep + Fadh));
232 }
233 }
234 }
235 }
236
243 template<typename cell_t>
244 void snapCellsToPlane(cell_t* c) {
245 double dist;
246 for (auto plane : planes) {
247 dist = plane.distanceToPoint(c->getBody().getPosition()) - (c->getBody().getBoundingBoxRadius() - c->getBody().getBoundingBoxRadius() * overlapAdhesion);
248 if (dist < 0) c->getBody().setPosition(c->getBody().getPosition() - plane.n * dist);
249 }
250 }
251};
252
253#endif // PHYSICSCONSTRAINTS_HPP
double getBoundingBoxRadius() const
Definition: CellBody.hpp:65
general purpose 3D vector/point class.
Definition: vector3D.h:20
double x() const
Definition: vector3D.h:94
static Vector3D getProjectionOnPlane(const Vector3D &o, const Vector3D &n, const Vector3D &p)
project a point on a plane
Definition: vector3D.h:362
double y() const
Definition: vector3D.h:100
double length() const
compute the length of the vector
Definition: vector3D.h:257
double sqlength() const
compute the square length of the current vector (faster than length)
Definition: vector3D.h:265
static Vector3D zero()
constructs a zero vector
Definition: vector3D.h:170
double z() const
Definition: vector3D.h:106
void normalize()
normalizes the vector
Definition: vector3D.h:445
Vector3D normalized() const
returns a normalized copy of the current vector
Definition: vector3D.h:452
Represents a plane constraint.
double distanceToPoint(MecaCell::Vec c)
Computes the distance from a point to the plane.
Plane(MecaCell::Vec _n=MecaCell::Vec(0, 1, 0), MecaCell::Vec _p=MecaCell::Vec(0, 0, 0), bool _sticky=false)
Constructor for Plane.
Represents a symmetrical axis constraint.
std::function< double(double, MecaCell::Vec, MecaCell::Vec)> radiusFunction
SymAxis(MecaCell::Vec a, MecaCell::Vec o, double l, double mef, bool fs, double av, std::function< double(double, MecaCell::Vec, MecaCell::Vec)> rf)
Constructor for SymAxis.
Class for managing physical constraints in a simulation.
PhysicsConstraints()
Default constructor.
std::vector< Plane > planes
void setPoissonAndYoungOfPlane(double poisson, double young)
Sets the Poisson's ratio and Young's modulus for the plane.
std::vector< MecaCell::Vec > velocities
void addPlane(MecaCell::Vec _n=MecaCell::Vec(0, 1, 0), MecaCell::Vec _p=MecaCell::Vec(0, 0, 0), bool _sticky=false)
Adds a plane constraint.
void applyPlaneConstraints(cell_t *c)
Applies plane constraints to a cell.
MecaCell::Vec getSymAxesConstraintsVelocity(cell_t *c)
Computes the symmetrical axis constraints velocity for a cell.
std::vector< SymAxis > symAxes
MecaCell::Vec getConstraintVelocity(cell_t *c)
Computes the constraint velocity for a cell.
void snapCellsToPlane(cell_t *c)
Snaps cells to the plane.
void addSymAxis(std::function< double(double, MecaCell::Vec, MecaCell::Vec)> _radiusFunction, MecaCell::Vec _axis=MecaCell::Vec(0., 1., 0.), MecaCell::Vec _origin=MecaCell::Vec(0., 0., 0.), double _length=100, double _maxEffectRadius=100, bool _fitShape=true, double _velocity_attraction=0.001)
Adds a symmetrical axis constraint.
void addVelocity(MecaCell::Vec _v=MecaCell::Vec(0, 1, 0))
Adds a velocity constraint.
void setCurvedBox(double radiusBoxPlane, double curvedDistToMaxSpeed, double maxSpeed)
Sets the curved box parameters.
A simple vector class template.
Definition: std.hpp:290
int abs(int x)
Computes the absolute value of an integer.
Definition: std.hpp:83
double sqrt(double x)
Computes the square root of a number.
Definition: std.hpp:32
double pow(double base, double exponent)
Computes the power of a number.
Definition: std.hpp:43