Files
IfcOpenShell/src/interface/modules/viewport/Controller.cpp
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

191 lines
8.3 KiB
C++
Raw Normal View History

2026-05-07 14:45:23 +10:00
// This file was generated with the assistance of an AI coding tool.
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "Controller.h"
2026-05-11 09:17:45 +10:00
#include "../../InterfaceSettings.h"
2026-05-07 17:10:04 +10:00
#include "../../SessionState.h"
2026-05-07 14:45:23 +10:00
#include "../../../ifcviewer/AppSettings.h"
#include "../../../ifcviewer/Federation.h"
#include "../../../ifcviewer/SceneLoader.h"
#include "../../../ifcviewer/ViewportWindow.h"
#include <Eigen/Dense>
2026-05-09 19:43:26 +10:00
namespace ifcinterface::modules::viewport {
2026-05-07 14:45:23 +10:00
2026-05-07 17:10:04 +10:00
ViewportController::ViewportController(ifcinterface::SessionState* session_state,
2026-05-07 14:45:23 +10:00
ViewportWindow* viewport,
QObject* parent)
: QObject(parent)
2026-05-07 17:10:04 +10:00
, session_state_(session_state)
2026-05-07 14:45:23 +10:00
, viewport_(viewport)
{
2026-05-07 17:10:04 +10:00
Federation* federation = session_state_->federation();
SceneLoader* loader = session_state_->loader();
2026-05-11 09:17:45 +10:00
connect(&ifcinterface::InterfaceSettings::instance(),
&ifcinterface::InterfaceSettings::themeChanged,
this, [this]() {
viewport_->setBackgroundColor(QColor(ifcinterface::InterfaceSettings::instance().color("viewport_background")));
});
viewport_->setBackgroundColor(QColor(ifcinterface::InterfaceSettings::instance().color("viewport_background")));
2026-05-07 17:10:04 +10:00
connect(federation, &Federation::federatedFalseOriginChanged,
2026-05-07 14:45:23 +10:00
this, &ViewportController::applyFederatedFalseOrigin);
2026-05-07 17:10:04 +10:00
connect(federation, &Federation::configChanged, this, [this]() {
2026-05-07 14:45:23 +10:00
applyFederatedFalseOrigin();
2026-05-07 17:10:04 +10:00
for (uint32_t mid : session_state_->modelIds()) {
applyModelTransformation(mid);
2026-05-07 14:45:23 +10:00
}
});
2026-05-07 17:10:04 +10:00
connect(federation, &Federation::modelTransformationChanged,
2026-05-07 14:45:23 +10:00
this, [this](const QString& fed_id) {
2026-05-07 17:10:04 +10:00
const uint32_t mid = session_state_->modelIdForFedId(fed_id);
if (mid != 0) applyModelTransformation(mid);
});
connect(federation, &Federation::modelVisibilityChanged,
this, [this](const QString& fed_id, bool /*visible*/) {
const uint32_t mid = session_state_->modelIdForFedId(fed_id);
if (mid != 0) applyModelVisibility(mid);
});
connect(federation, &Federation::modelGroupChanged,
this, [this](const QString& fed_id, const QString& /*group_id*/) {
const uint32_t mid = session_state_->modelIdForFedId(fed_id);
if (mid != 0) applyModelVisibility(mid);
});
connect(federation, &Federation::groupVisibilityChanged,
this, [this](const QString&, bool /*visible*/) {
for (uint32_t mid : session_state_->modelIds()) {
applyModelVisibility(mid);
2026-05-07 14:45:23 +10:00
}
});
2026-05-07 17:10:04 +10:00
connect(loader, &SceneLoader::loadedFromSidecar, this,
2026-05-07 14:45:23 +10:00
[this](uint32_t mid, qint64 /*elapsed_ms*/) {
applyCoordinateOperation(mid);
2026-05-07 17:10:04 +10:00
applyModelVisibility(mid);
2026-05-07 14:45:23 +10:00
maybeGuessFederatedFalseOrigin(mid);
});
2026-05-07 17:10:04 +10:00
connect(loader, &SceneLoader::dataSourceReady, this,
2026-05-07 14:45:23 +10:00
[this](uint32_t mid) {
applyCoordinateOperation(mid);
});
2026-05-07 17:10:04 +10:00
connect(loader, &SceneLoader::loadedFromStream, this,
2026-05-07 14:45:23 +10:00
[this](uint32_t mid, qint64 /*elapsed_ms*/) {
applyCoordinateOperation(mid);
2026-05-07 17:10:04 +10:00
applyModelVisibility(mid);
2026-05-07 14:45:23 +10:00
maybeGuessFederatedFalseOrigin(mid);
});
}
void ViewportController::applyCoordinateOperation(uint32_t mid) {
2026-05-07 17:10:04 +10:00
SceneLoader* loader = session_state_->loader();
2026-05-07 14:45:23 +10:00
Eigen::Matrix4d matrix = Eigen::Matrix4d::Identity();
if (const ModelGeoref* georef = loader->modelGeoref(mid)) {
if (georef->has_coordinate_operation) {
matrix = georef->coordinate_operation_meters;
2026-05-07 14:45:23 +10:00
}
}
viewport_->setModelCoordinateOperation(mid, matrix);
applyModelTransformation(mid);
}
void ViewportController::applyModelTransformation(uint32_t mid) {
2026-05-07 17:10:04 +10:00
Federation* federation = session_state_->federation();
SceneLoader* loader = session_state_->loader();
2026-05-07 14:45:23 +10:00
Eigen::Matrix4d matrix = Eigen::Matrix4d::Identity();
2026-05-07 17:10:04 +10:00
const QString fed_id = session_state_->fedIdForModelId(mid);
if (!fed_id.isEmpty()) {
if (const Federation::Model* model = federation->findById(fed_id)) {
2026-05-07 14:45:23 +10:00
ModelUnits units;
Eigen::Matrix4d coordinate_operation = Eigen::Matrix4d::Identity();
2026-05-07 17:10:04 +10:00
if (const ModelGeoref* georef = loader->modelGeoref(mid)) {
2026-05-07 14:45:23 +10:00
units = georef->units;
if (georef->has_coordinate_operation) {
2026-05-07 14:45:23 +10:00
coordinate_operation = georef->coordinate_operation_meters;
}
}
matrix = composeModelTransformation(
2026-05-07 17:10:04 +10:00
model->model_transformation, federation->config(), units, coordinate_operation);
2026-05-07 14:45:23 +10:00
}
}
viewport_->setModelTransformation(mid, matrix);
}
2026-05-07 17:10:04 +10:00
void ViewportController::applyModelVisibility(uint32_t mid) {
Federation* federation = session_state_->federation();
const QString fed_id = session_state_->fedIdForModelId(mid);
if (fed_id.isEmpty()) return;
if (federation->isModelEffectivelyVisible(fed_id)) {
viewport_->showModel(mid);
} else {
viewport_->hideModel(mid);
}
}
2026-05-07 14:45:23 +10:00
void ViewportController::applyFederatedFalseOrigin() {
2026-05-07 17:10:04 +10:00
Federation* federation = session_state_->federation();
2026-05-07 14:45:23 +10:00
viewport_->setFederatedFalseOrigin(
2026-05-07 17:10:04 +10:00
composeFederatedFalseOrigin(federation->federatedFalseOrigin(), federation->config()));
2026-05-07 14:45:23 +10:00
}
2026-05-09 07:11:58 +10:00
void ViewportController::setHomeView() {
auto camera = viewport_->cameraState();
Federation::HomeView home_view;
home_view.target = camera.target;
home_view.distance = camera.distance;
home_view.yaw = camera.yaw;
home_view.pitch = camera.pitch;
session_state_->federation()->setHomeView(home_view);
session_state_->setStatusMessage("Camera", "Home view updated");
}
void ViewportController::goHomeView() {
Federation* federation = session_state_->federation();
if (!federation->hasHomeView()) {
session_state_->setStatusMessage("Camera", "No home view set for this project");
return;
}
const auto& home_view = federation->homeView();
viewport_->setCamera(
home_view.target.x(), home_view.target.y(), home_view.target.z(),
home_view.distance, home_view.yaw, home_view.pitch);
session_state_->setStatusMessage("Camera", "Home view restored");
}
2026-05-07 14:45:23 +10:00
void ViewportController::maybeGuessFederatedFalseOrigin(uint32_t mid) {
2026-05-07 17:10:04 +10:00
Federation* federation = session_state_->federation();
SceneLoader* loader = session_state_->loader();
if (!federation->filePath().isEmpty()) return;
2026-05-07 14:45:23 +10:00
2026-05-07 17:10:04 +10:00
const FederatedFalseOrigin& current = federation->federatedFalseOrigin();
2026-05-07 14:45:23 +10:00
const FederatedFalseOrigin defaults;
if (current.xyz != defaults.xyz || current.rz_deg != defaults.rz_deg) return;
2026-05-07 17:10:04 +10:00
const Eigen::Matrix4d* placement = loader->firstPlacement(mid);
const ModelGeoref* georef = loader->modelGeoref(mid);
2026-05-07 14:45:23 +10:00
if (placement == nullptr || georef == nullptr) return;
2026-05-07 17:10:04 +10:00
federation->setFederatedFalseOrigin(guessFederatedFalseOrigin(
*placement, *georef, federation->config()));
2026-05-07 14:45:23 +10:00
}
2026-05-09 19:43:26 +10:00
} // namespace ifcinterface::modules::viewport