1#ifndef MECACELL_GENERICCONNECTIONPLUGIN_HPP
2#define MECACELL_GENERICCONNECTIONPLUGIN_HPP
18template <
typename Cell,
template <
class>
class GenericConnection>
25 std::unique_ptr<GenericConnection<Cell>>>
35 [](GenericConnection<Cell> *) {};
52 w->threadpool.autoChunks(w->cells, 100, 5,
53 [dt = w->getDt()](
auto &c) { c->body.updateInternals(dt); });
54 w->threadpool.waitUntilLast();
58 unsigned int nbIterations = 2;
63 savedForces.
reserve(w->cells.size());
64 for (
auto &c : w->cells) {
66 std::make_pair<Vec, Vec>(c->getBody().getForce(), c->getBody().getTorque()));
67 c->getBody().resetForce();
68 c->getBody().resetTorque();
72 double subdt = w->getDt() /
static_cast<double>(nbIterations);
73 for (
unsigned int i = 0; i < nbIterations; ++i) {
76 [subdt](
auto &c) { c.second->update(subdt); });
77 w->threadpool.waitUntilLast();
78 for (
size_t j = 0; j < w->cells.size(); ++j) {
79 auto &c = w->cells[j];
80 c->body.receiveForce(savedForces[j].first);
81 c->body.receiveTorque(savedForces[j].second);
83 w->allForcesHaveBeenAppliedToCells();
84 for (
auto &c : w->cells) {
85 c->body.updatePositionsAndOrientations(subdt);
87 c->body.resetTorque();
99 auto ptr = std::make_unique<GenericConnection<Cell>>(cells);
100 auto *newConnection =
ptr.get();
104 cells.
first->body.cellConnections.push_back(newConnection);
105 cells.
second->body.cellConnections.push_back(newConnection);
136 const double NEW_CONNECTION_THRESHOLD = 1.0 - 1e-10;
139 for (
const auto &c : world.cells) grid.
insert(c);
140 int minCellPerBatch = 0;
141 if (world.threadpool.getNbThreads() > 0)
142 minCellPerBatch = world.cells.size() / (10 * 8.0);
144 for (
auto &color : gridCells) {
146 newConnectionsFutures;
147 newConnectionsFutures.
reserve(color.size());
148 for (
auto &batch : color)
149 if (batch.size() > 1)
150 newConnectionsFutures.
push_back(world.threadpool.enqueueWithFuture([&] {
151 std::vector<ordered_pair<Cell *>> newConns;
152 for (size_t i = 0; i < batch.size(); ++i) {
153 for (size_t j = i + 1; j < batch.size(); ++j) {
154 auto op = make_ordered_cell_pair(batch[i], batch[j]);
155 Vec AB = op.second->getPosition() - op.first->getPosition();
156 double sqDistance = AB.sqlength();
157 if (sqDistance < std::pow(op.first->body.getBoundingBoxRadius() +
158 op.second->body.getBoundingBoxRadius(),
160 if (!op.first->isConnectedTo(op.second) && op.first != op.second) {
161 double dist = sqrt(sqDistance);
163 auto d0 = op.first->body.getPreciseMembraneDistance(dir);
164 auto d1 = op.second->body.getPreciseMembraneDistance(-dir);
165 if (dist < NEW_CONNECTION_THRESHOLD * (d0 + d1))
166 newConns.push_back(op);
171 return std::move(newConns);
173 for (
auto &ncf : newConnectionsFutures)
177 auto &batch = world.cells;
178 for (
size_t i = 0; i < batch.size(); ++i) {
179 for (
size_t j = i + 1; j < batch.size(); ++j) {
181 Vec AB = op.second->getPosition() - op.first->getPosition();
183 if (sqDistance <
std::pow(op.first->body.getBoundingBoxRadius() +
184 op.second->body.getBoundingBoxRadius(),
186 if (!op.first->isConnectedTo(op.second) && op.first != op.second) {
187 double dist =
sqrt(sqDistance);
189 auto d0 = op.first->body.getPreciseMembraneDistance(dir);
190 auto d1 = op.second->body.getPreciseMembraneDistance(-dir);
208 for (
auto &con : connections) {
209 if (!con.second->unbreakable) {
210 if (con.second->area <= 0) {
211 toDisconnect.
push_back(std::make_pair(con.first, con.second.get()));
212 }
else if (con.first.first->getBody().getConnectedCell(con.second->direction) !=
214 con.first.second->getBody().getConnectedCell(-con.second->direction) !=
216 toDisconnect.
push_back(std::make_pair(con.first, con.second.get()));
220 for (
auto &c : toDisconnect) disconnect(c.first, c.second);
224 for (
auto &c : w->cells) {
226 auto cctmp(c->body.cellConnections);
227 for (
auto &connection : cctmp) {
228 auto *c0 = connection->cells.first;
229 auto *c1 = connection->cells.second;
232 c0->connectedCells.erase(c1);
233 c1->connectedCells.erase(c0);
234 assert(c0->id != c1->id);
235 connections.erase(connection->cells);
Infinite grid of fixed cell size for space partitioning.
std::array< vector< vector< O > >, 8 > getThreadSafeGrid() const
void insert(V &&k, const O &o)
general purpose 3D vector/point class.
double sqlength() const
compute the square length of the current vector (faster than length)
A simple vector class template.
void reserve(size_t newCapacity)
Reserves storage for the specified number of elements.
void push_back(const T &value)
Adds an element to the end of the vector.
this file contains various miscellanious utility functions & helpers *
ordered_pair< T * > make_ordered_cell_pair(T *a, T *b)
T * ptr(T &obj)
returns a pointer (transforms reference into pointer)
void eraseFromVector(const T &elem, std::deque< T > &vec)
static double GRIDSIZE
Embedded plugin that will handle the collision detection routines. Parallel code.
double sqrt(double x)
Computes the square root of a number.
double pow(double base, double exponent)
Computes the power of a number.
std::mutex connectionMutex
connections. The ordered_hash_map is to enforce determinism.
void updateCellCellConnections(W &)
updates (compute forces) the connections and delete the resolved ones (when cells are not in contact ...
std::function< void(GenericConnection< Cell > *)> newConnectionCallback
void preBehaviorUpdate(W *w)
void deleteImpossibleConnections()
void preDeleteDeadCellsUpdate(W *w)
void checkForCellCellConnections(W &world)
we check for any cell cell collision or adhesion
void setNewConnectionCallback(std::function< void(GenericConnection< Cell > *)> f)
Sets a callback function to be called at each connection creation. Can be used to override the defaul...
void disconnect(const ordered_pair< Cell * > &cells, GenericConnection< Cell > *conn)
Disconnect two cells.
void createConnection(const ordered_pair< Cell * > &cells)
create and register a contact surface connection between twoe cells
const size_t AVG_TASKS_PER_THREAD
ordered_hash_map< ordered_pair< Cell * >, std::unique_ptr< GenericConnection< Cell > > > connections
const size_t MIN_CHUNK_SIZE