CRUD
This commit is contained in:
@@ -45,7 +45,6 @@ public:
|
|||||||
color(color), size(size), light(light), emittance(emittance), refraction(refraction),
|
color(color), size(size), light(light), emittance(emittance), refraction(refraction),
|
||||||
reflection(reflection) {}
|
reflection(reflection) {}
|
||||||
|
|
||||||
// Default constructor for serialization
|
|
||||||
NodeData() : active(false), visible(false), size(0.0f), light(false),
|
NodeData() : active(false), visible(false), size(0.0f), light(false),
|
||||||
emittance(0.0f), refraction(0.0f), reflection(0.0f) {}
|
emittance(0.0f), refraction(0.0f), reflection(0.0f) {}
|
||||||
};
|
};
|
||||||
@@ -433,7 +432,6 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Octree from binary file
|
|
||||||
bool load(const std::string& filename) {
|
bool load(const std::string& filename) {
|
||||||
std::ifstream in(filename, std::ios::binary);
|
std::ifstream in(filename, std::ios::binary);
|
||||||
if (!in) return false;
|
if (!in) return false;
|
||||||
@@ -460,6 +458,222 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<NodeData> find(const PointType& pos, float tolerance = 0.0001f) {
|
||||||
|
std::function<std::shared_ptr<NodeData>(OctreeNode*)> searchNode = [&](OctreeNode* node) -> std::shared_ptr<NodeData> {
|
||||||
|
if (!node->contains(pos)) return nullptr;
|
||||||
|
|
||||||
|
if (node->isLeaf) {
|
||||||
|
for (const auto& pointData : node->points) {
|
||||||
|
if (!pointData->active) continue;
|
||||||
|
|
||||||
|
float distSq = (pointData->position - pos).squaredNorm();
|
||||||
|
if (distSq <= tolerance * tolerance) {
|
||||||
|
return pointData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
int octant = getOctant(pos, node->center);
|
||||||
|
if (node->children[octant]) {
|
||||||
|
return searchNode(node->children[octant].get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
return searchNode(root_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(const PointType& pos, float tolerance = 0.0001f) {
|
||||||
|
bool found = false;
|
||||||
|
std::function<bool(OctreeNode*)> removeNode = [&](OctreeNode* node) -> bool {
|
||||||
|
if (!node->contains(pos)) return false;
|
||||||
|
|
||||||
|
if (node->isLeaf) {
|
||||||
|
auto it = std::remove_if(node->points.begin(), node->points.end(),
|
||||||
|
[&](const std::shared_ptr<NodeData>& pointData) {
|
||||||
|
if (!pointData->active) return false;
|
||||||
|
|
||||||
|
float distSq = (pointData->position - pos).squaredNorm();
|
||||||
|
if (distSq <= tolerance * tolerance) {
|
||||||
|
found = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
node->points.erase(it, node->points.end());
|
||||||
|
size--; // Decrement size counter
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int octant = getOctant(pos, node->center);
|
||||||
|
if (node->children[octant]) {
|
||||||
|
return removeNode(node->children[octant].get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return removeNode(root_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<NodeData>> findInRadius(const PointType& center, float radius) {
|
||||||
|
std::vector<std::shared_ptr<NodeData>> results;
|
||||||
|
if (!root_) return results;
|
||||||
|
|
||||||
|
float radiusSq = radius * radius;
|
||||||
|
|
||||||
|
std::function<void(OctreeNode*)> searchNode = [&](OctreeNode* node) {
|
||||||
|
// Check if node's bounding box intersects with search sphere
|
||||||
|
PointType boxCenter = (node->bounds.first + node->bounds.second) * 0.5f;
|
||||||
|
PointType boxHalfSize = (node->bounds.second - node->bounds.first) * 0.5f;
|
||||||
|
|
||||||
|
PointType closestPoint;
|
||||||
|
for (int i = 0; i < Dim; ++i) {
|
||||||
|
closestPoint[i] = std::max(node->bounds.first[i],
|
||||||
|
std::min(center[i], node->bounds.second[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
float distSq = (closestPoint - center).squaredNorm();
|
||||||
|
if (distSq > (radius + boxHalfSize.norm()) * (radius + boxHalfSize.norm())) {
|
||||||
|
return; // No intersection
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->isLeaf) {
|
||||||
|
for (const auto& pointData : node->points) {
|
||||||
|
if (!pointData->active) continue;
|
||||||
|
|
||||||
|
float pointDistSq = (pointData->position - center).squaredNorm();
|
||||||
|
if (pointDistSq <= radiusSq) {
|
||||||
|
results.emplace_back(pointData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const auto& child : node->children) {
|
||||||
|
if (child) {
|
||||||
|
searchNode(child.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
searchNode(root_.get());
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update(const PointType& oldPos, const PointType& newPos, const T& newData = T(), bool newVisible = true,
|
||||||
|
Eigen::Vector3f newColor = Eigen::Vector3f(1.0f, 1.0f, 1.0f), float newSize = 0.01f, bool newActive = true,
|
||||||
|
bool newLight = false, float newEmittance = 0.0f, float newRefraction = 0.0f, float newReflection = 0.0f,
|
||||||
|
float tolerance = 0.0001f) {
|
||||||
|
|
||||||
|
// Find the existing point
|
||||||
|
auto pointData = find(oldPos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
// If position changed, we need to remove and reinsert
|
||||||
|
float moveDistSq = (newPos - oldPos).squaredNorm();
|
||||||
|
if (moveDistSq > tolerance * tolerance) {
|
||||||
|
// Save the data
|
||||||
|
T dataCopy = pointData->data;
|
||||||
|
bool activeCopy = pointData->active;
|
||||||
|
bool visibleCopy = pointData->visible;
|
||||||
|
Eigen::Vector3f colorCopy = pointData->color;
|
||||||
|
float sizeCopy = pointData->size;
|
||||||
|
bool lightCopy = pointData->light;
|
||||||
|
float emittanceCopy = pointData->emittance;
|
||||||
|
float refractionCopy = pointData->refraction;
|
||||||
|
float reflectionCopy = pointData->reflection;
|
||||||
|
|
||||||
|
// Remove the old point
|
||||||
|
if (!remove(oldPos, tolerance)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert at new position with updated properties
|
||||||
|
return set(newData != T() ? newData : dataCopy, newPos,
|
||||||
|
newVisible ? newVisible : visibleCopy,
|
||||||
|
newColor != Eigen::Vector3f(1.0f, 1.0f, 1.0f) ? newColor : colorCopy,
|
||||||
|
newSize > 0 ? newSize : sizeCopy,
|
||||||
|
newActive ? newActive : activeCopy,
|
||||||
|
newLight ? newLight : lightCopy,
|
||||||
|
newEmittance > 0 ? newEmittance : emittanceCopy,
|
||||||
|
newRefraction >= 0 ? newRefraction : refractionCopy,
|
||||||
|
newReflection >= 0 ? newReflection : reflectionCopy);
|
||||||
|
} else {
|
||||||
|
// Just update properties in place
|
||||||
|
pointData->data = newData;
|
||||||
|
pointData->position = newPos; // Minor adjustment within tolerance
|
||||||
|
pointData->visible = newVisible;
|
||||||
|
pointData->color = newColor;
|
||||||
|
pointData->size = newSize;
|
||||||
|
pointData->active = newActive;
|
||||||
|
pointData->light = newLight;
|
||||||
|
pointData->emittance = newEmittance;
|
||||||
|
pointData->refraction = newRefraction;
|
||||||
|
pointData->reflection = newReflection;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateData(const PointType& pos, const T& newData, float tolerance = 0.0001f) {
|
||||||
|
auto pointData = find(pos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
pointData->data = newData;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setActive(const PointType& pos, bool active, float tolerance = 0.0001f) {
|
||||||
|
auto pointData = find(pos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
pointData->active = active;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setVisible(const PointType& pos, bool visible, float tolerance = 0.0001f) {
|
||||||
|
auto pointData = find(pos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
pointData->visible = visible;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setLight(const PointType& pos, bool light, float tolerance = 0.0001f) {
|
||||||
|
auto pointData = find(pos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
pointData->light = light;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setColor(const PointType& pos, Eigen::Vector3f color, float tolerance = 0.0001f) {
|
||||||
|
auto pointData = find(pos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
pointData->color = color;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setReflection(const PointType& pos, float reflection, float tolerance = 0.0001f) {
|
||||||
|
auto pointData = find(pos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
pointData->reflection = reflection;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setEmittance(const PointType& pos, float emittance, float tolerance = 0.0001f) {
|
||||||
|
auto pointData = find(pos, tolerance);
|
||||||
|
if (!pointData) return false;
|
||||||
|
|
||||||
|
pointData->emittance = emittance;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<NodeData>> voxelTraverse(const PointType& origin, const PointType& direction,
|
std::vector<std::shared_ptr<NodeData>> voxelTraverse(const PointType& origin, const PointType& direction,
|
||||||
float maxDist, bool stopAtFirstHit) {
|
float maxDist, bool stopAtFirstHit) {
|
||||||
std::vector<std::shared_ptr<NodeData>> hits;
|
std::vector<std::shared_ptr<NodeData>> hits;
|
||||||
|
|||||||
Reference in New Issue
Block a user