added more retentive stuff

This commit is contained in:
Lauchmelder 2021-12-16 16:35:37 +01:00
parent 75df9ad96d
commit b947b0b263
8 changed files with 117 additions and 107 deletions

View file

@ -1,7 +1,7 @@
add_library(nm_utils STATIC
"Window.cpp"
"RetentiveArray.hpp" "RetentiveObject.hpp" "RetentiveEntity.hpp")
"RetentiveArray.hpp" "RetentiveObject.hpp" "RetentiveEntity.hpp" "VectorField.hpp" "VectorField.cpp")
target_include_directories(nm_utils PUBLIC ${SDL2_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(nm_utils PUBLIC ${SDL2_LIBRARIES})

View file

@ -3,6 +3,76 @@
#include <vector>
#include <array>
#include <functional>
#include <memory>
template<
typename Type,
unsigned int AttentionSpan,
bool IsPointerType>
class _RetentiveEntityBase;
template<
typename Type,
unsigned int AttentionSpan>
class _RetentiveEntityBase<Type, AttentionSpan, false>
{
public:
/**
* @brief Get the entity from `index` generations ago
*
* @param index Amount of generations to go backwards in time
* @return The entity from before `index` generations
*/
Type& operator[](size_t index)
{
return data[index];
}
/**
* @brief Get the most up-to-date entity
*
* @return The entity with generation 0
*/
Type& Current()
{
return data[0];
}
protected:
std::array<Type, AttentionSpan + 1> data;
};
template<
typename Type,
unsigned int AttentionSpan>
class _RetentiveEntityBase<Type, AttentionSpan, true>
{
public:
/**
* @brief Get the entity from `index` generations ago
*
* @param index Amount of generations to go backwards in time
* @return The entity from before `index` generations
*/
Type& operator[](size_t index)
{
return *(data[index]);
}
/**
* @brief Get the most up-to-date entity
*
* @return The entity with generation 0
*/
Type& Current()
{
return *(data[0]);
}
protected:
std::array<std::shared_ptr<Type>, AttentionSpan + 1> data; // Shared for move semantics
};
/**
* @brief Abstract base type for all retentive things
@ -13,8 +83,8 @@
template<
typename Type,
unsigned int AttentionSpan,
typename std::enable_if_t<(AttentionSpan > 0), bool> = true>
class RetentiveEntity
bool IsPointerType = false>
class RetentiveEntity : public _RetentiveEntityBase<Type, AttentionSpan, IsPointerType>
{
public:
RetentiveEntity() {}
@ -23,27 +93,6 @@ public:
RetentiveEntity<Type, AttentionSpan>& operator=(const RetentiveEntity<Type, AttentionSpan>& other) = delete;
RetentiveEntity<Type, AttentionSpan>& operator=(RetentiveEntity<Type, AttentionSpan>&& other) = delete;
/**
* @brief Get the entity from `index` generations ago
*
* @param index Amount of generations to go backwards in time
* @return The entity from before `index` generations
*/
virtual Type& operator[](size_t index)
{
return data[index];
}
/**
* @brief Get the most up-to-date entity
*
* @return The entity with generation 0
*/
virtual Type& Current()
{
return data[0];
}
/**
* @brief Evolve the data in the entity
*
@ -92,8 +141,4 @@ protected:
* @brief Swaps the objects in the array
*/
virtual void CycleGenerations() = 0;
protected:
std::array<Type, AttentionSpan + 1> data;
std::function<void(void)> rule = std::bind([]() {}); // Do nothing by default
};

View file

@ -21,9 +21,8 @@
*/
template<
typename Type,
unsigned int AttentionSpan,
typename std::enable_if_t<(AttentionSpan > 0), bool> = true>
class RetentiveObject : public RetentiveEntity<Type*, AttentionSpan>
unsigned int AttentionSpan>
class RetentiveObject : public RetentiveEntity<Type, AttentionSpan, true>
{
public:
/**
@ -34,7 +33,7 @@ public:
// Create new vectors for every generation that needs to be remembered
for (int n = 0; n <= AttentionSpan; n++)
{
data[n] = new Type();
data[n] = std::make_shared<Type>();
}
}
@ -45,10 +44,10 @@ public:
*/
RetentiveObject(const Type& initVal)
{
// Create new vectors for every generation that needs to be remembered
// Create new objects for every generation that needs to be remembered
for (int n = 0; n <= AttentionSpan; n++)
{
data[n] = new Type(initVal);
data[n] = std::make_shared<Type>(initVal);
}
}
@ -77,7 +76,6 @@ public:
for (int n = 0; n <= AttentionSpan; n++)
{
data[n] = other.data[n];
other.data[n] = nullptr;
}
return *this;
@ -103,36 +101,6 @@ public:
*this = other;
}
~RetentiveObject()
{
for (int n = 0; n <= AttentionSpan; n++)
{
if (data[n] != nullptr)
delete data[n];
}
}
/**
* @brief Get the object from `index` generations ago
*
* @param index Amount of generations to go backwards in time
* @return The object from before `index` generations
*/
Type& operator[](size_t index) override
{
return *(data[index]);
}
/**
* @brief Get the most up-to-date object
*
* @return The object with generation 0
*/
Type& Current() override
{
return *(data[0]);
}
private:
/**
* @brief Swaps the objects in the array

76
lib/VectorField.cpp Normal file
View file

@ -0,0 +1,76 @@
#include "VectorField.hpp"
#include <chrono>
#include <iostream>
#include <SDL.h>
VectorField::VectorField() :
width(0), height(0), biggestMagnitude(1.0)
{
}
VectorField::VectorField(int width, int height) :
width(width), height(height)
{
horizontal = std::vector<double>(width * height, 0.0);
vertical = std::vector<double>(width * height, 0.0);
biggestMagnitude = 1.0f;
}
VectorField::VectorField(int width, int height, const std::vector<double>& hori, const std::vector<double>& vert) :
width(width), height(height)
{
horizontal = hori;
vertical = vert;
RecalculateMagnitude();
}
void VectorField::Draw(SDL_Renderer* renderer, const SDL_Rect& targetRect)
{
double cellWidth = (double)(targetRect.w - targetRect.x) / (double)width;
double cellHeight = (double)(targetRect.h - targetRect.y) / (double)height;
SDL_FRect vectorCenterSquare;
vectorCenterSquare.w = cellWidth / 5.0;
vectorCenterSquare.h = cellHeight / 5.0;
SDL_SetRenderDrawColor(renderer, 200, 20, 20, 100);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
vectorCenterSquare.x = (double)targetRect.x + cellWidth * (x + 0.4); // cellWidth * x + cellWidth / 2 - cellWidth / 10
vectorCenterSquare.y = (double)targetRect.y + cellHeight * (y + 0.4);
SDL_RenderFillRectF(renderer, &vectorCenterSquare);
SDL_RenderDrawLineF(renderer,
(double)targetRect.x + cellWidth * (x + 0.5),
(double)targetRect.y + cellHeight * (y + 0.5),
(double)targetRect.x + cellWidth * (x + 0.5) + horizontal[y * width + x] / biggestMagnitude * cellWidth * 2.5,
(double)targetRect.y + cellHeight * (y + 0.5) + vertical[y * width + x] / biggestMagnitude * cellHeight * 2.5
);
}
}
}
void VectorField::RecalculateMagnitude()
{
for (int y = 0; y < this->height; y++)
{
for (int x = 0; x < this->width; x++)
{
double u = horizontal[y * this->width + x];
double v = vertical[y * this->width + x];
double magnitude = u * u + v * v;
biggestMagnitude = std::max(biggestMagnitude, magnitude);
}
}
if (biggestMagnitude == 0.0) // should use an epsilon probably
biggestMagnitude = 1.0;
biggestMagnitude = sqrt(biggestMagnitude);
biggestMagnitude = 0.5f;
}

26
lib/VectorField.hpp Normal file
View file

@ -0,0 +1,26 @@
#pragma once
#include <vector>
struct SDL_Rect;
struct SDL_Renderer;
class VectorField
{
public:
VectorField();
VectorField(int width, int height);
VectorField(int width, int height, const std::vector<double>& hori, const std::vector<double>& vert);
void Draw(SDL_Renderer* renderer, const SDL_Rect& targetRect);
void RecalculateMagnitude();
public:
std::vector<double> horizontal;
std::vector<double> vertical;
private:
int width, height;
double biggestMagnitude = 0.0;
};