Line data Source code
1 : #ifndef F674C74F_4648_4098_89DD_4A99F7F0CB5C_HPP 2 : #define F674C74F_4648_4098_89DD_4A99F7F0CB5C_HPP 3 : 4 : #include "Disc.hpp" 5 : #include "Membrane.hpp" 6 : #include "Types.hpp" 7 : #include "Vector2d.hpp" 8 : 9 : #include <optional> 10 : #include <set> 11 : #include <vector> 12 : 13 : namespace cell 14 : { 15 : 16 : class CollisionDetector 17 : { 18 : public: 19 : struct Params 20 : { 21 : std::vector<Disc>* discs = nullptr; 22 : std::vector<Membrane>* membranes = nullptr; 23 : std::vector<Disc*>* intrudingDiscs = nullptr; 24 : Membrane* containingMembrane = nullptr; 25 : }; 26 : 27 : enum class EntryType 28 : { 29 : Disc, 30 : Membrane, 31 : IntrudingDisc 32 : }; 33 : 34 : enum class CollisionType 35 : { 36 : DiscDisc, 37 : DiscContainingMembrane, 38 : DiscChildMembrane, 39 : None 40 : }; 41 : 42 : struct Entry 43 : { 44 : std::size_t index = 0; 45 : double radius = 0; 46 : Vector2d position; 47 : double minX = 0, maxX = 0; 48 : EntryType type = EntryType::Disc; 49 : }; 50 : 51 : struct Collision 52 : { 53 : Disc* disc = nullptr; 54 : Disc* otherDisc = nullptr; 55 : Membrane* membrane = nullptr; 56 : CollisionType type = CollisionType::None; 57 : bool allowedToPass = false; // Set in case of membrane collisions depending on permeability 58 : 59 22 : bool invalidatedByDestroyedDiscs() const 60 : { 61 22 : return disc->isMarkedDestroyed() || (otherDisc && otherDisc->isMarkedDestroyed()); 62 : } 63 : }; 64 : 65 : private: 66 : struct EntryComparator 67 : { 68 37 : bool operator()(const Entry& e1, const Entry& e2) const 69 : { 70 37 : return e1.minX < e2.minX; 71 : } 72 : } entryComparator_; 73 : 74 : public: 75 : CollisionDetector(const DiscTypeRegistry& discTypeRegistry, const MembraneTypeRegistry& membraneTypeRegistry); 76 : void setParams(Params params); 77 : void buildMembraneIndex(); 78 : void buildDiscIndex(); 79 : void addIntrudingDiscsToIndex(); 80 : 81 : std::vector<Collision> detectDiscMembraneCollisions(); 82 : std::vector<Collision> detectDiscDiscCollisions(); 83 : 84 : static DiscTypeMap<int> getAndResetCollisionCounts(); 85 : 86 : private: 87 : template <typename ElementType, typename RegistryType> 88 : Entry createEntry(const ElementType& element, const RegistryType& registry, std::size_t index, 89 : EntryType entryType) const; 90 : 91 : bool discIsContainedByMembrane(const Entry& entry); 92 : bool canGoThrough(Disc* disc, Membrane* membrane, CollisionDetector::CollisionType collisionType) const; 93 : 94 : private: 95 : static DiscTypeMap<int> collisionCounts_; 96 : 97 : const DiscTypeRegistry& discTypeRegistry_; 98 : const MembraneTypeRegistry& membraneTypeRegistry_; 99 : 100 : std::vector<Entry> membraneEntries_; 101 : std::vector<Entry> discEntries_; 102 : Params params_; 103 : }; 104 : 105 : template <typename ElementType, typename RegistryType> 106 43 : inline CollisionDetector::Entry CollisionDetector::createEntry(const ElementType& element, const RegistryType& registry, 107 : std::size_t index, EntryType entryType) const 108 : { 109 43 : const double r = registry.getByID(element.getTypeID()).getRadius(); 110 43 : const auto& p = element.getPosition(); 111 : 112 43 : return Entry{.index = index, .radius = r, .position = p, .minX = p.x - r, .maxX = p.x + r, .type = entryType}; 113 : } 114 : 115 : } // namespace cell 116 : 117 : #endif /* F674C74F_4648_4098_89DD_4A99F7F0CB5C_HPP */