refactoring grid2 to make it cleaner and smaller.
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
const float EPSILON = 0.0000000000000000000000001;
|
const float EPSILON = 0.0000000000000000000000001;
|
||||||
|
|
||||||
class reverselookupassistantclasscausecppisdumb {
|
class reverselookupassistant {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<size_t, Vec2> Positions;
|
std::unordered_map<size_t, Vec2> Positions;
|
||||||
std::unordered_map<Vec2, size_t, Vec2::Hash> ƨnoiƚiƨoꟼ;
|
std::unordered_map<Vec2, size_t, Vec2::Hash> ƨnoiƚiƨoꟼ;
|
||||||
@@ -193,14 +193,40 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GenericPixel {
|
||||||
|
protected:
|
||||||
|
size_t id;
|
||||||
|
Vec4 color;
|
||||||
|
Vec2 pos;
|
||||||
|
public:
|
||||||
|
//constructors
|
||||||
|
GenericPixel(size_t id, Vec4 color, Vec2 pos) : id(id), color(color), pos(pos) {};
|
||||||
|
|
||||||
|
//getters
|
||||||
|
Vec4 getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
//setters
|
||||||
|
void setColor(Vec4 newColor) {
|
||||||
|
color = newColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(Vec2 newPos) {
|
||||||
|
pos = newPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recolor(Vec4 newColor) {
|
||||||
|
color.recolor(newColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Grid2 {
|
class Grid2 {
|
||||||
protected:
|
protected:
|
||||||
//all positions
|
//all positions
|
||||||
reverselookupassistantclasscausecppisdumb Positions;
|
reverselookupassistant Positions;
|
||||||
//all colors
|
std::unordered_map<size_t /*id*/, GenericPixel> Pixels;
|
||||||
std::unordered_map<size_t, Vec4> Colors;
|
|
||||||
//all sizes
|
|
||||||
std::unordered_map<size_t, float> Sizes;
|
|
||||||
|
|
||||||
std::vector<size_t> unassignedIDs;
|
std::vector<size_t> unassignedIDs;
|
||||||
|
|
||||||
@@ -297,12 +323,8 @@ public:
|
|||||||
//add pixel (default color and default size provided)
|
//add pixel (default color and default size provided)
|
||||||
size_t addObject(const Vec2& pos, const Vec4& color, float size = 1.0f) {
|
size_t addObject(const Vec2& pos, const Vec4& color, float size = 1.0f) {
|
||||||
size_t id = Positions.set(pos);
|
size_t id = Positions.set(pos);
|
||||||
Colors[id] = color;
|
Pixels.insert({id, GenericPixel(id, color, pos)});
|
||||||
Sizes[id] = size;
|
|
||||||
|
|
||||||
// Add to spatial grid
|
|
||||||
spatialGrid.insert(id, pos);
|
spatialGrid.insert(id, pos);
|
||||||
// updateNeighborForID(id);
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,78 +338,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setMaterialProperties(size_t id, double conductivity, double specific_heat, double density = 1.0) {
|
void setMaterialProperties(size_t id, double conductivity, double specific_heat, double density = 1.0) {
|
||||||
auto it = tempMap.find(id);
|
auto it = tempMap.at(id);
|
||||||
if (it != tempMap.end()) {
|
it.conductivity = conductivity;
|
||||||
it->second.conductivity = conductivity;
|
it.specific_heat = specific_heat;
|
||||||
it->second.specific_heat = specific_heat;
|
it.diffusivity = conductivity / (density * specific_heat);
|
||||||
it->second.diffusivity = conductivity / (density * specific_heat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMaterialProperties(const Vec2& pos, double conductivity, double specific_heat, double density = 1.0) {
|
|
||||||
size_t id = getOrCreatePositionVec(pos, 0.0f, true);
|
|
||||||
setMaterialProperties(id, conductivity, specific_heat, density);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//set position by id
|
//set position by id
|
||||||
void setPosition(size_t id, const Vec2& newPosition) {
|
void setPosition(size_t id, const Vec2& newPosition) {
|
||||||
Vec2 oldPosition = Positions.at(id);
|
Vec2 oldPosition = Positions.at(id);
|
||||||
|
Pixels.at(id).move(newPosition);
|
||||||
spatialGrid.update(id, oldPosition, newPosition);
|
spatialGrid.update(id, oldPosition, newPosition);
|
||||||
Positions.at(id).move(newPosition);
|
Positions.at(id).move(newPosition);
|
||||||
// updateNeighborForID(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPosition(size_t id, float x, float y) {
|
|
||||||
Vec2 newPos = Vec2(x,y);
|
|
||||||
Vec2 oldPos = Positions.at(id);
|
|
||||||
|
|
||||||
spatialGrid.update(id, oldPos, newPos);
|
|
||||||
Positions.at(id).move(newPos);
|
|
||||||
// updateNeighborForID(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//set color by id (by pos same as get color)
|
//set color by id (by pos same as get color)
|
||||||
void setColor(size_t id, const Vec4 color) {
|
void setColor(size_t id, const Vec4 color) {
|
||||||
Colors.at(id).recolor(color);
|
Pixels.at(id).recolor(color);
|
||||||
}
|
|
||||||
|
|
||||||
void setColor(size_t id, float r, float g, float b, float a=1.0f) {
|
|
||||||
Colors.at(id).recolor(Vec4(r,g,b,a));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColor(float x, float y, const Vec4 color) {
|
|
||||||
size_t id = getPositionVec(Vec2(x,y));
|
|
||||||
Colors.at(id).recolor(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColor(float x, float y, float r, float g, float b, float a=1.0f) {
|
|
||||||
size_t id = getPositionVec(Vec2(x,y));
|
|
||||||
Colors.at(id).recolor(Vec4(r,g,b,a));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColor(const Vec2& pos, const Vec4 color) {
|
|
||||||
size_t id = getPositionVec(pos);
|
|
||||||
Colors.at(id).recolor(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColor(const Vec2& pos, float r, float g, float b, float a=1.0f) {
|
|
||||||
size_t id = getPositionVec(pos);
|
|
||||||
Colors.at(id).recolor(Vec4(r,g,b,a));
|
|
||||||
}
|
|
||||||
|
|
||||||
//set size by id (by pos same as get size)
|
|
||||||
void setSize(size_t id, float size) {
|
|
||||||
Sizes.at(id) = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSize(float x, float y, float size) {
|
|
||||||
size_t id = getPositionVec(Vec2(x,y));
|
|
||||||
Sizes.at(id) = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSize(const Vec2& pos, float size) {
|
|
||||||
size_t id = getPositionVec(pos);
|
|
||||||
Sizes.at(id) = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set neighbor search radius
|
// Set neighbor search radius
|
||||||
@@ -397,7 +364,6 @@ public:
|
|||||||
optimizeSpatialGrid();
|
optimizeSpatialGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
//temp stuff
|
|
||||||
void setTemp(const Vec2 pos, double temp) {
|
void setTemp(const Vec2 pos, double temp) {
|
||||||
size_t id = getOrCreatePositionVec(pos, 0.0, true);
|
size_t id = getOrCreatePositionVec(pos, 0.0, true);
|
||||||
setTemp(id, temp);
|
setTemp(id, temp);
|
||||||
@@ -419,7 +385,6 @@ public:
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get id from position (optional radius, picks first found. radius of 0 becomes epsilon if none are found)
|
|
||||||
size_t getPositionVec(const Vec2& pos, float radius = 0.0f) const {
|
size_t getPositionVec(const Vec2& pos, float radius = 0.0f) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
if (radius == 0.0f) {
|
if (radius == 0.0f) {
|
||||||
@@ -472,10 +437,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getPositionVec(float x, float y, float radius = 0.0f) const {
|
|
||||||
return getPositionVec(Vec2(x,y), radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
//get all id in region
|
//get all id in region
|
||||||
std::vector<size_t> getPositionVecRegion(const Vec2& pos, float radius = 1.0f) const {
|
std::vector<size_t> getPositionVecRegion(const Vec2& pos, float radius = 1.0f) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
@@ -502,23 +463,6 @@ public:
|
|||||||
return Colors.at(id);
|
return Colors.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get color from position (use get id from position and then get color from id)
|
|
||||||
Vec4 getColor(float x, float y) {
|
|
||||||
size_t id = getPositionVec(Vec2(x,y),0.0);
|
|
||||||
return getColor(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//get size from id
|
|
||||||
size_t getSize(size_t id) {
|
|
||||||
return Sizes.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//get size from position (use get id from position and then get size from id)
|
|
||||||
size_t getSize(float x, float y) {
|
|
||||||
size_t id = getPositionVec(Vec2(x,y),0.0);
|
|
||||||
return getSize(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
double getTemp(size_t id) {
|
double getTemp(size_t id) {
|
||||||
if (tempMap.find(id) != tempMap.end()) {
|
if (tempMap.find(id) != tempMap.end()) {
|
||||||
Temp temp = Temp(getPositionID(id), getTemps());
|
Temp temp = Temp(getPositionID(id), getTemps());
|
||||||
@@ -552,17 +496,6 @@ public:
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getTemp(const Vec2 pos) {
|
|
||||||
size_t id = getOrCreatePositionVec(pos, 0.01f, true);
|
|
||||||
if (tempMap.find(id) == tempMap.end()) {
|
|
||||||
//std::cout << "missing a temp at: " << pos << std::endl;
|
|
||||||
double dtemp = Temp::calTempIDW(pos, getTemps(id));
|
|
||||||
setTemp(id, dtemp);
|
|
||||||
return dtemp;
|
|
||||||
}
|
|
||||||
else return tempMap.at(id).temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get bounding box
|
//get bounding box
|
||||||
void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) const {
|
void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
@@ -594,20 +527,81 @@ public:
|
|||||||
maxCorner.y += margin;
|
maxCorner.y += margin;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<size_t> getAllIDs() {
|
frame getGridRegionAsFrame(const Vec2& minCorner, const Vec2& maxCorner,
|
||||||
|
Vec2& res, frame::colormap outChannels = frame::colormap::RGB) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
std::vector<size_t> ids;
|
// Calculate dimensions
|
||||||
ids.reserve(Positions.size());
|
size_t width = static_cast<int>(maxCorner.x - minCorner.x);
|
||||||
|
size_t height = static_cast<int>(maxCorner.y - minCorner.y);
|
||||||
|
frame outframe = frame();
|
||||||
|
outframe.colorFormat = outChannels;
|
||||||
|
|
||||||
for (const auto& pair : Positions) {
|
if (width <= 0 || height <= 0) {
|
||||||
ids.push_back(pair.first);
|
width = height = 0;
|
||||||
|
return outframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ids;
|
std::vector<Vec4> colorBuffer(width * height, Vec4(0,0,0,0));
|
||||||
|
|
||||||
|
for (const auto& [id, pos] : Positions) {
|
||||||
|
if (maxCorner.x > pos.x > minCorner.x && maxCorner.y pos.y > mincorner.y) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no return because it passes back a 1d vector of ints between 0 and 255 with a width and height
|
// Calculate pixel coordinates
|
||||||
//get region as rgb
|
int pixelXm = static_cast<int>(pos.x/2 - minCorner.x);
|
||||||
|
int pixelXM = static_cast<int>(pos.x/2 - minCorner.x);
|
||||||
|
int pixelYm = static_cast<int>(pos.y/2 - minCorner.y);
|
||||||
|
int pixelYM = static_cast<int>(pos.y/2 - minCorner.y);
|
||||||
|
|
||||||
|
pixelXm = std::max(0, pixelXm);
|
||||||
|
pixelXM = std::min(width - 1, pixelXM);
|
||||||
|
pixelYm = std::max(0, pixelYm);
|
||||||
|
pixelYM = std::min(height - 1, pixelYM);
|
||||||
|
|
||||||
|
// Ensure within bounds
|
||||||
|
if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) {
|
||||||
|
const Vec4& color = Colors.at(id);
|
||||||
|
float srcAlpha = color.a;
|
||||||
|
float invSrcAlpha = 1.0f - srcAlpha;
|
||||||
|
for (int py = pixelYm; py <= pixelYM; ++py){
|
||||||
|
for (int px = pixelXm; px <= pixelXM; ++px){
|
||||||
|
int index = (py * width + px);
|
||||||
|
Vec4 dest = colorBuffer[index];
|
||||||
|
|
||||||
|
// Alpha blending: new_color = src * src_alpha + dest * (1 - src_alpha)
|
||||||
|
dest.r = color.r * srcAlpha + dest.r * invSrcAlpha;
|
||||||
|
dest.g = color.g * srcAlpha + dest.g * invSrcAlpha;
|
||||||
|
dest.b = color.b * srcAlpha + dest.b * invSrcAlpha;
|
||||||
|
dest.a = srcAlpha + dest.a * invSrcAlpha;
|
||||||
|
colorBuffer[index] = dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to RGB bytes
|
||||||
|
rgbData.resize(colorBuffer.size() * 3);
|
||||||
|
for (int i = 0; i < colorBuffer.size(); ++i) {
|
||||||
|
Vec4& color = colorBuffer[i];
|
||||||
|
int rgbIndex = i * 3;
|
||||||
|
float alpha = color.a;
|
||||||
|
|
||||||
|
if (alpha < 1.0) {
|
||||||
|
float invalpha = 1.0 - alpha;
|
||||||
|
color.r = defaultBackgroundColor.r * alpha + color.r * invalpha;
|
||||||
|
color.g = defaultBackgroundColor.g * alpha + color.g * invalpha;
|
||||||
|
color.b = defaultBackgroundColor.b * alpha + color.b * invalpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from [0,1] to [0,255] and store as RGB
|
||||||
|
rgbData[rgbIndex + 0] = static_cast<unsigned char>(color.r * 255);
|
||||||
|
rgbData[rgbIndex + 1] = static_cast<unsigned char>(color.g * 255);
|
||||||
|
rgbData[rgbIndex + 2] = static_cast<unsigned char>(color.b * 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void getGridRegionAsRGB(const Vec2& minCorner, const Vec2& maxCorner,
|
void getGridRegionAsRGB(const Vec2& minCorner, const Vec2& maxCorner,
|
||||||
int& width, int& height, std::vector<uint8_t>& rgbData) const {
|
int& width, int& height, std::vector<uint8_t>& rgbData) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
@@ -1040,32 +1034,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<size_t> bulkAddObjects(const std::vector<std::tuple<Vec2, Vec4, float>>& objects) {
|
|
||||||
TIME_FUNCTION;
|
|
||||||
std::vector<size_t> ids;
|
|
||||||
ids.reserve(objects.size());
|
|
||||||
|
|
||||||
// Reserve space in maps to avoid rehashing
|
|
||||||
Positions.reserve(Positions.size() + objects.size());
|
|
||||||
Colors.reserve(Colors.size() + objects.size());
|
|
||||||
Sizes.reserve(Sizes.size() + objects.size());
|
|
||||||
|
|
||||||
// Batch insertion
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (size_t i = 0; i < objects.size(); ++i) {
|
|
||||||
const auto& [pos, color, size] = objects[i];
|
|
||||||
size_t id = Positions.set(pos);
|
|
||||||
|
|
||||||
Colors[id] = color;
|
|
||||||
Sizes[id] = size;
|
|
||||||
//spatialGrid.insert(id,pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
shrinkIfNeeded();
|
|
||||||
// updateNeighborMap();
|
|
||||||
return getAllIDs(); // Or generate ID range
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<size_t> bulkAddObjects(const std::vector<Vec2> poses, std::vector<Vec4> colors, std::vector<float>& sizes) {
|
std::vector<size_t> bulkAddObjects(const std::vector<Vec2> poses, std::vector<Vec4> colors, std::vector<float>& sizes) {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
std::vector<size_t> ids;
|
std::vector<size_t> ids;
|
||||||
@@ -1146,7 +1114,6 @@ public:
|
|||||||
|
|
||||||
void optimizeSpatialGrid() {
|
void optimizeSpatialGrid() {
|
||||||
//std::cout << "optimizeSpatialGrid()" << std::endl;
|
//std::cout << "optimizeSpatialGrid()" << std::endl;
|
||||||
neighborRadius = 1.0;
|
|
||||||
spatialCellSize = neighborRadius * neighborRadius;
|
spatialCellSize = neighborRadius * neighborRadius;
|
||||||
spatialGrid = SpatialGrid(spatialCellSize);
|
spatialGrid = SpatialGrid(spatialCellSize);
|
||||||
|
|
||||||
@@ -1326,9 +1293,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void diffuseTemps(uint timestep) {
|
void diffuseTemps(int timestep) {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
if (tempMap.empty() || timestep == 0) return;
|
if (tempMap.empty() || timestep < 1) return;
|
||||||
std::unordered_map<size_t, float> cTemps;
|
std::unordered_map<size_t, float> cTemps;
|
||||||
cTemps.reserve(tempMap.size());
|
cTemps.reserve(tempMap.size());
|
||||||
for (const auto& [id, temp] : tempMap) {
|
for (const auto& [id, temp] : tempMap) {
|
||||||
|
|||||||
Reference in New Issue
Block a user