mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
ifcviewer: move volume readout helpers into ViewportCore (#84-j)
Tiny followup to #84-i — move the const-lookup volume helpers used by
bonsai's measurement HUD:
double volumeOfObjects(const std::vector<uint32_t>&) const
vector<pair<uint32_t, double>> volumesPerObject(
const std::vector<uint32_t>&) const
The det3OfPlacement static helper moves with them into ViewportCore.cpp's
anonymous namespace (the original kept its mirror in
ViewportWindow.cpp; ViewportWindow's own internal callers are gone now
since these methods moved).
Pure read of models_gpu_ + mesh_local_volumes — all in core already.
Trivial transplant.
Builds: desktop / bonsai / web all green. Tests 100/100.
This commit is contained in:
@@ -489,3 +489,57 @@ bool ViewportCore::computeObjectAabb(uint32_t object_id,
|
||||
mx = Eigen::Vector3f(fmax[0], fmax[1], fmax[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// |det| of the 3×3 linear part of a column-major double[16] placement
|
||||
// matrix. Picks up uniform scale + mirror so a 2× clone of a 1m³ mesh
|
||||
// reports 8m³. Used by the volume readout below.
|
||||
namespace {
|
||||
double det3OfPlacement(const double M[16]) {
|
||||
const double m00 = M[0], m10 = M[1], m20 = M[2];
|
||||
const double m01 = M[4], m11 = M[5], m21 = M[6];
|
||||
const double m02 = M[8], m12 = M[9], m22 = M[10];
|
||||
return m00 * (m11 * m22 - m12 * m21)
|
||||
- m01 * (m10 * m22 - m12 * m20)
|
||||
+ m02 * (m10 * m21 - m11 * m20);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
double ViewportCore::volumeOfObjects(
|
||||
const std::vector<uint32_t>& object_ids) const {
|
||||
if (object_ids.empty()) return 0.0;
|
||||
double total = 0.0;
|
||||
for (uint32_t oid : object_ids) {
|
||||
for (const auto& [mid, m] : models_gpu_) {
|
||||
auto it = m.object_id_to_instance.find(oid);
|
||||
if (it == m.object_id_to_instance.end()) continue;
|
||||
const InstanceCpu& inst = m.instances[it->second];
|
||||
if (inst.mesh_id >= m.mesh_local_volumes.size()) break;
|
||||
const double v_local = m.mesh_local_volumes[inst.mesh_id];
|
||||
const double det = std::abs(det3OfPlacement(inst.placement_transformation));
|
||||
total += v_local * det;
|
||||
break; // object_id is globally unique → at most one hit
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, double>>
|
||||
ViewportCore::volumesPerObject(
|
||||
const std::vector<uint32_t>& object_ids) const {
|
||||
std::vector<std::pair<uint32_t, double>> out;
|
||||
if (object_ids.empty()) return out;
|
||||
out.reserve(object_ids.size());
|
||||
for (uint32_t oid : object_ids) {
|
||||
for (const auto& [mid, m] : models_gpu_) {
|
||||
auto it = m.object_id_to_instance.find(oid);
|
||||
if (it == m.object_id_to_instance.end()) continue;
|
||||
const InstanceCpu& inst = m.instances[it->second];
|
||||
if (inst.mesh_id >= m.mesh_local_volumes.size()) break;
|
||||
const double v_local = m.mesh_local_volumes[inst.mesh_id];
|
||||
const double det = std::abs(det3OfPlacement(inst.placement_transformation));
|
||||
out.emplace_back(oid, v_local * det);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "BufferPool.h"
|
||||
#include "InstanceCompose.h"
|
||||
@@ -158,6 +160,17 @@ public:
|
||||
bool computeObjectAabb(uint32_t object_id,
|
||||
Eigen::Vector3f& mn, Eigen::Vector3f& mx) const;
|
||||
|
||||
// Sum of mesh-local volumes (m³) of every instance whose object_id
|
||||
// is in `object_ids`. Each instance is scaled by |det(placement_3x3)|
|
||||
// to pick up mapped-item scale/mirror; signed-tetrahedra absolute
|
||||
// value means winding is ignored. Volumes are precomputed at
|
||||
// applyCachedModel — this call is just lookups + multiplies.
|
||||
double volumeOfObjects(const std::vector<uint32_t>& object_ids) const;
|
||||
// Per-object variant. Used by the Volume tool to drive both the
|
||||
// total HUD and the per-object overlay labels at AABB centres.
|
||||
std::vector<std::pair<uint32_t, double>>
|
||||
volumesPerObject(const std::vector<uint32_t>& object_ids) const;
|
||||
|
||||
// Friend access for ViewportWindow's reference proxies. As each
|
||||
// render method moves into ViewportCore it stops needing these
|
||||
// (it touches the fields directly); once everything has migrated
|
||||
|
||||
@@ -3547,44 +3547,15 @@ void ViewportWindow::setToolMode(ToolMode m) {
|
||||
if (isExposed()) requestUpdate();
|
||||
}
|
||||
|
||||
// volumeOfObjects / volumesPerObject moved to ViewportCore (#84-j).
|
||||
double ViewportWindow::volumeOfObjects(
|
||||
const std::vector<uint32_t>& object_ids) const {
|
||||
if (object_ids.empty()) return 0.0;
|
||||
double total = 0.0;
|
||||
for (uint32_t oid : object_ids) {
|
||||
for (const auto& [mid, m] : models_gpu_) {
|
||||
auto it = m.object_id_to_instance.find(oid);
|
||||
if (it == m.object_id_to_instance.end()) continue;
|
||||
const InstanceCpu& inst = m.instances[it->second];
|
||||
if (inst.mesh_id >= m.mesh_local_volumes.size()) break;
|
||||
const double v_local = m.mesh_local_volumes[inst.mesh_id];
|
||||
const double det = std::abs(det3OfPlacement(inst.placement_transformation));
|
||||
total += v_local * det;
|
||||
break; // object_id is globally unique → at most one hit
|
||||
}
|
||||
}
|
||||
return total;
|
||||
return core_.volumeOfObjects(object_ids);
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, double>>
|
||||
ViewportWindow::volumesPerObject(
|
||||
const std::vector<uint32_t>& object_ids) const {
|
||||
std::vector<std::pair<uint32_t, double>> out;
|
||||
if (object_ids.empty()) return out;
|
||||
out.reserve(object_ids.size());
|
||||
for (uint32_t oid : object_ids) {
|
||||
for (const auto& [mid, m] : models_gpu_) {
|
||||
auto it = m.object_id_to_instance.find(oid);
|
||||
if (it == m.object_id_to_instance.end()) continue;
|
||||
const InstanceCpu& inst = m.instances[it->second];
|
||||
if (inst.mesh_id >= m.mesh_local_volumes.size()) break;
|
||||
const double v_local = m.mesh_local_volumes[inst.mesh_id];
|
||||
const double det = std::abs(det3OfPlacement(inst.placement_transformation));
|
||||
out.emplace_back(oid, v_local * det);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
return core_.volumesPerObject(object_ids);
|
||||
}
|
||||
|
||||
void ViewportWindow::updateVolumeReadout() {
|
||||
|
||||
Reference in New Issue
Block a user