mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 11:24:19 +00:00
ifcviewer: cache CoordinateOperation in sidecar (v10 -> v11)
Previously, applyCoordinateOperationToViewport — which pushes both
CoordinateOperation and ModelTransformation — was only called on
paths that required the IFC source to be loaded
(onLoadedFromStream and onDataSourceReady). Sidecar-only loads
(loadDataSource off, or no .ifc/.rdb sibling) silently lost both
stages.
Cache the per-model georef + unit scales in the sidecar itself so
the IFC source isn't needed to apply them:
SidecarData gains
coordinate_operation_meters[16] // column-major
project_length_to_meters
map_unit_to_meters
has_coordinate_operation
148 B fixed block written/read between instances and elements.
SIDECAR_VERSION 10 -> 11; existing sidecars rebuild on next load.
MainWindow::writeSidecarForModel populates the block from
loader_->modelGeoref(mid) before writeSidecar.
SceneLoader::applySidecarData restores it into the model's
ModelGeoref + sets has_georef = true, so subsequent
loader_->modelGeoref(mid) calls return the cached data without
needing the IFC.
MainWindow::onLoadedFromSidecar now calls
applyCoordinateOperationToViewport(mid) directly — both
CoordinateOperation and ModelTransformation land at sidecar-load
time, no longer waiting on a possibly-never-arriving data source.
Edits to the IFC's IfcMapConversion don't invalidate the cache —
delete the .ifcview manually if the source's georef changes. This
matches the existing cache-invalidation contract.
Tests: round-trip the new fields through the existing sidecar
fixture; assert SIDECAR_VERSION == 11.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -594,12 +594,18 @@ void MainWindow::applyFederatedFalseOriginToViewport() {
|
||||
viewport_->setFederatedFalseOrigin(M);
|
||||
}
|
||||
|
||||
void MainWindow::onLoadedFromSidecar(uint32_t /*mid*/, qint64 elapsed_ms) {
|
||||
void MainWindow::onLoadedFromSidecar(uint32_t mid, qint64 elapsed_ms) {
|
||||
progress_bar_->setVisible(false);
|
||||
status_label_->setText(QString("%1 elements across %2 model(s) — loaded from cache in %3")
|
||||
.arg(element_map_.size())
|
||||
.arg(loader_->modelCount())
|
||||
.arg(formatElapsed(elapsed_ms)));
|
||||
|
||||
// Sidecar v11+ caches the CoordinateOperation, so SceneLoader has
|
||||
// already populated modelGeoref by now — push CoordinateOperation +
|
||||
// ModelTransformation immediately rather than waiting for the
|
||||
// (possibly never-arriving) data-source load.
|
||||
applyCoordinateOperationToViewport(mid);
|
||||
}
|
||||
|
||||
void MainWindow::onStreamedElementsReady(uint32_t /*mid*/, std::vector<ElementInfo> elements) {
|
||||
@@ -615,6 +621,16 @@ void MainWindow::writeSidecarForModel(uint32_t mid) {
|
||||
SidecarData sd;
|
||||
if (!viewport_->snapshotModel(mid, sd)) return;
|
||||
|
||||
// Cache the model's CoordinateOperation alongside the geometry so a
|
||||
// sidecar load doesn't need the IFC source just to apply georef.
|
||||
if (const ModelGeoref* gr = loader_->modelGeoref(mid)) {
|
||||
sd.has_coordinate_operation = gr->has_coordinate_operation ? 1 : 0;
|
||||
Eigen::Map<Eigen::Matrix<double, 4, 4, Eigen::ColMajor>>(
|
||||
sd.coordinate_operation_meters) = gr->coordinate_operation_meters;
|
||||
sd.project_length_to_meters = gr->units.project_length_to_meters;
|
||||
sd.map_unit_to_meters = gr->units.map_unit_to_meters;
|
||||
}
|
||||
|
||||
for (const auto& [oid, info] : element_map_) {
|
||||
if (info.model_id != mid) continue;
|
||||
PackedElementInfo pe;
|
||||
|
||||
Reference in New Issue
Block a user