diff --git a/util/grid/grid2.hpp b/util/grid/grid2.hpp index 4d82048..8c5e067 100644 --- a/util/grid/grid2.hpp +++ b/util/grid/grid2.hpp @@ -15,7 +15,7 @@ const float EPSILON = 0.0000000000000000000000001; -class reverselookupassistantclasscausecppisdumb { +class reverselookupassistant { private: std::unordered_map Positions; std::unordered_map ƨnoiƚiƨoꟼ; @@ -193,15 +193,41 @@ 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 { protected: //all positions - reverselookupassistantclasscausecppisdumb Positions; - //all colors - std::unordered_map Colors; - //all sizes - std::unordered_map Sizes; - + reverselookupassistant Positions; + std::unordered_map Pixels; + std::vector unassignedIDs; //grid min @@ -297,12 +323,8 @@ public: //add pixel (default color and default size provided) size_t addObject(const Vec2& pos, const Vec4& color, float size = 1.0f) { size_t id = Positions.set(pos); - Colors[id] = color; - Sizes[id] = size; - - // Add to spatial grid + Pixels.insert({id, GenericPixel(id, color, pos)}); spatialGrid.insert(id, pos); - // updateNeighborForID(id); return id; } @@ -316,80 +338,25 @@ public: } void setMaterialProperties(size_t id, double conductivity, double specific_heat, double density = 1.0) { - auto it = tempMap.find(id); - if (it != tempMap.end()) { - it->second.conductivity = conductivity; - it->second.specific_heat = 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); + auto it = tempMap.at(id); + it.conductivity = conductivity; + it.specific_heat = specific_heat; + it.diffusivity = conductivity / (density * specific_heat); } //set position by id void setPosition(size_t id, const Vec2& newPosition) { Vec2 oldPosition = Positions.at(id); + Pixels.at(id).move(newPosition); spatialGrid.update(id, oldPosition, 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) 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 void setNeighborRadius(float radius) { neighborRadius = radius; @@ -397,7 +364,6 @@ public: optimizeSpatialGrid(); } - //temp stuff void setTemp(const Vec2 pos, double temp) { size_t id = getOrCreatePositionVec(pos, 0.0, true); setTemp(id, temp); @@ -419,7 +385,6 @@ public: 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 { TIME_FUNCTION; 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 std::vector getPositionVecRegion(const Vec2& pos, float radius = 1.0f) const { TIME_FUNCTION; @@ -502,23 +463,6 @@ public: 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) { if (tempMap.find(id) != tempMap.end()) { Temp temp = Temp(getPositionID(id), getTemps()); @@ -552,17 +496,6 @@ public: 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 void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) const { TIME_FUNCTION; @@ -594,20 +527,81 @@ public: maxCorner.y += margin; } - std::vector getAllIDs() { + frame getGridRegionAsFrame(const Vec2& minCorner, const Vec2& maxCorner, + Vec2& res, frame::colormap outChannels = frame::colormap::RGB) const { TIME_FUNCTION; - std::vector ids; - ids.reserve(Positions.size()); - - for (const auto& pair : Positions) { - ids.push_back(pair.first); + // Calculate dimensions + size_t width = static_cast(maxCorner.x - minCorner.x); + size_t height = static_cast(maxCorner.y - minCorner.y); + frame outframe = frame(); + outframe.colorFormat = outChannels; + + if (width <= 0 || height <= 0) { + width = height = 0; + return outframe; } - return ids; + std::vector 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) { + + } + + // Calculate pixel coordinates + int pixelXm = static_cast(pos.x/2 - minCorner.x); + int pixelXM = static_cast(pos.x/2 - minCorner.x); + int pixelYm = static_cast(pos.y/2 - minCorner.y); + int pixelYM = static_cast(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(color.r * 255); + rgbData[rgbIndex + 1] = static_cast(color.g * 255); + rgbData[rgbIndex + 2] = static_cast(color.b * 255); + } } - // no return because it passes back a 1d vector of ints between 0 and 255 with a width and height - //get region as rgb + void getGridRegionAsRGB(const Vec2& minCorner, const Vec2& maxCorner, int& width, int& height, std::vector& rgbData) const { TIME_FUNCTION; @@ -1040,32 +1034,6 @@ public: } } - std::vector bulkAddObjects(const std::vector>& objects) { - TIME_FUNCTION; - std::vector 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 bulkAddObjects(const std::vector poses, std::vector colors, std::vector& sizes) { TIME_FUNCTION; std::vector ids; @@ -1146,7 +1114,6 @@ public: void optimizeSpatialGrid() { //std::cout << "optimizeSpatialGrid()" << std::endl; - neighborRadius = 1.0; spatialCellSize = neighborRadius * neighborRadius; spatialGrid = SpatialGrid(spatialCellSize); @@ -1326,9 +1293,9 @@ public: } } - void diffuseTemps(uint timestep) { + void diffuseTemps(int timestep) { TIME_FUNCTION; - if (tempMap.empty() || timestep == 0) return; + if (tempMap.empty() || timestep < 1) return; std::unordered_map cTemps; cTemps.reserve(tempMap.size()); for (const auto& [id, temp] : tempMap) {