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
|
/*************************************************************************
* Copyright (C) 2008 by Sergei Dorofeenko *
* sega@users.berlios.de *
* *
* This program is free software; it is licensed under the terms of the *
* GNU General Public License v2 or later. See file LICENSE for details. *
*************************************************************************/
#include "SpatialQuickSortCollider.hpp"
#include <core/BodyContainer.hpp>
#include <core/Scene.hpp>
#include <algorithm>
namespace yade { // Cannot have #include directive inside.
YADE_PLUGIN((SpatialQuickSortCollider));
void SpatialQuickSortCollider::action()
{
if (scene->isPeriodic) { throw runtime_error("SpatialQuickSortCollider doesn't handle periodic boundaries."); }
// update bounds
boundDispatcher->scene = scene;
boundDispatcher->action();
const shared_ptr<BodyContainer>& bodies = scene->bodies;
// This collider traverses all interactions at every step, therefore all interactions
// that were requested for erase might be erased here and will be recreated if necessary.
scene->interactions->eraseNonReal();
size_t nbElements = bodies->size();
if (nbElements != rank.size()) {
size_t n = rank.size();
rank.resize(nbElements);
for (; n < nbElements; ++n)
rank[n] = shared_ptr<AABBBound>(new AABBBound);
}
Vector3r min, max;
int n = 0;
for (const auto& b : *bodies) {
if (!b->bound) continue;
min = b->bound->min;
max = b->bound->max;
rank[n]->id = b->getId();
rank[n]->min = min;
rank[n]->max = max;
n++;
}
const shared_ptr<InteractionContainer>& interactions = scene->interactions;
scene->interactions->iterColliderLastRun = scene->iter;
sort(rank.begin(), rank.end(), xBoundComparator()); // sorting along X
int id, id2;
size_t j;
shared_ptr<Interaction> interaction;
for (int i = 0, e = nbElements - 1; i < e; ++i) {
id = rank[i]->id;
min = rank[i]->min;
max = rank[i]->max;
j = i;
while (++j < nbElements) {
if (rank[j]->min[0] > max[0]) break; // skip all others, because it's sorted along X
id2 = rank[j]->id;
#ifdef YADE_MPI
if (not Collider::mayCollide(Body::byId(id, scene).get(), Body::byId(id2, scene).get(), scene->subdomain))
#else
if (not Collider::mayCollide(Body::byId(id, scene).get(), Body::byId(id2, scene).get()))
#endif
continue; // skip this pair id ↔ id2, because it cannot collide for whatever reasons, e.g. a groupMask
if (rank[j]->min[1] < max[1] && rank[j]->max[1] > min[1] && rank[j]->min[2] < max[2] && rank[j]->max[2] > min[2]) {
if ((interaction = interactions->find(Body::id_t(id), Body::id_t(id2))) == 0) {
interaction = shared_ptr<Interaction>(new Interaction(id, id2));
interactions->insert(interaction);
}
interaction->iterLastSeen = scene->iter;
}
}
}
}
} // namespace yade
|