mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-18 19:30:25 +00:00
ifcviewer: rename stage1/2/3/4 to their proper IFC-mapped names
Replace the placeholder "stage1/2/3/4" terminology with names that
mirror the IFC concepts each step represents:
stage 1 -> PlacementTransformation
(per-instance, derived from IfcObjectPlacement)
stage 2 -> CoordinateOperation
(per-model, IfcCoordinateOperation / IfcMapConversion)
stage 3 -> FederatedFalseOrigin
(federation-wide, user-nominated)
stage 4 -> ModelTransformation
(per-model, user-authored within the federation)
API renames:
FederationOrigin -> FederatedFalseOrigin
ModelTransform -> ModelTransformation
composeFederationOrigin -> composeFederatedFalseOrigin
composeModelTransform -> composeModelTransformation
Federation::setOrigin -> Federation::setFederatedFalseOrigin
Federation::setModelTransform -> Federation::setModelTransformation
Federation::origin() -> Federation::federatedFalseOrigin()
Federation::Model::transform_intent -> ::model_transformation
ModelGeoref::stage2_meters -> ::coordinate_operation_meters
ModelGeoref::has_stage2 -> ::has_coordinate_operation
JSON keys in .ifcfed renamed in lockstep:
origin -> federated_false_origin
transform_intent -> model_transformation
The streamer's per-mesh "stage 1 vertex rebasing" comment is reframed:
the rebase isn't its own stage — it's a precision optimisation applied
inside the PlacementTransformation step.
All 36 ctest cases pass under the new names.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -84,8 +84,8 @@ double federationUnitToMeters(const FederationConfig& cfg) {
|
||||
return convert(1.0, cfg.unit_prefix, cfg.unit_name, "", "METRE");
|
||||
}
|
||||
|
||||
Eigen::Matrix4d composeFederationOrigin(const FederationOrigin& origin,
|
||||
const FederationConfig& cfg) {
|
||||
Eigen::Matrix4d composeFederatedFalseOrigin(const FederatedFalseOrigin& origin,
|
||||
const FederationConfig& cfg) {
|
||||
const double u = federationUnitToMeters(cfg);
|
||||
const Eigen::Vector3d xyz_m = origin.xyz * u;
|
||||
const double rz_rad = origin.rz_deg * kDegToRad;
|
||||
@@ -127,32 +127,34 @@ ModelGeoref computeModelGeoref(ifcopenshell::file* ifc_file) {
|
||||
wcs_m(0, 3) *= out.units.project_length_to_meters;
|
||||
wcs_m(1, 3) *= out.units.project_length_to_meters;
|
||||
wcs_m(2, 3) *= out.units.project_length_to_meters;
|
||||
out.stage2_meters = helmert * wcs_m.inverse();
|
||||
out.coordinate_operation_meters = helmert * wcs_m.inverse();
|
||||
} else {
|
||||
out.stage2_meters = helmert;
|
||||
out.coordinate_operation_meters = helmert;
|
||||
}
|
||||
out.has_stage2 = true;
|
||||
out.has_coordinate_operation = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
Eigen::Matrix4d composeModelTransform(const ModelTransform& xf,
|
||||
const FederationConfig& fed_cfg,
|
||||
const ModelUnits& model_units,
|
||||
const Eigen::Matrix4d& stage2_meters) {
|
||||
Eigen::Matrix4d composeModelTransformation(const ModelTransformation& xf,
|
||||
const FederationConfig& fed_cfg,
|
||||
const ModelUnits& model_units,
|
||||
const Eigen::Matrix4d& coordinate_operation_meters) {
|
||||
const double u_fed = federationUnitToMeters(fed_cfg);
|
||||
|
||||
Eigen::Vector3d A_m;
|
||||
if (xf.a_frame == AFrame::ModelLocal) {
|
||||
// a is in the model's project length unit, expressed in the
|
||||
// pre-stage2 frame. Convert to metres, then lift through stage 2.
|
||||
// pre-CoordinateOperation frame. Convert to metres, then lift
|
||||
// through the CoordinateOperation.
|
||||
const Eigen::Vector4d a_h(
|
||||
xf.a.x() * model_units.project_length_to_meters,
|
||||
xf.a.y() * model_units.project_length_to_meters,
|
||||
xf.a.z() * model_units.project_length_to_meters,
|
||||
1.0);
|
||||
A_m = (stage2_meters * a_h).head<3>();
|
||||
A_m = (coordinate_operation_meters * a_h).head<3>();
|
||||
} else {
|
||||
// a is in the model's map unit, expressed in the post-stage2 frame.
|
||||
// a is in the model's map unit, expressed in the
|
||||
// post-CoordinateOperation frame.
|
||||
A_m = xf.a * model_units.map_unit_to_meters;
|
||||
}
|
||||
|
||||
@@ -188,8 +190,8 @@ void Federation::clear() {
|
||||
created_ = QDateTime();
|
||||
modified_ = QDateTime();
|
||||
models_.clear();
|
||||
config_ = FederationConfig{};
|
||||
origin_ = FederationOrigin{};
|
||||
config_ = FederationConfig{};
|
||||
federated_false_origin_ = FederatedFalseOrigin{};
|
||||
has_home_view_ = false;
|
||||
home_view_ = HomeView{};
|
||||
setDirty(false);
|
||||
@@ -202,17 +204,18 @@ void Federation::setConfig(const FederationConfig& c) {
|
||||
setDirty(true);
|
||||
}
|
||||
|
||||
void Federation::setOrigin(const FederationOrigin& o) {
|
||||
if (origin_.xyz == o.xyz && origin_.rz_deg == o.rz_deg) return;
|
||||
origin_ = o;
|
||||
void Federation::setFederatedFalseOrigin(const FederatedFalseOrigin& o) {
|
||||
if (federated_false_origin_.xyz == o.xyz &&
|
||||
federated_false_origin_.rz_deg == o.rz_deg) return;
|
||||
federated_false_origin_ = o;
|
||||
setDirty(true);
|
||||
}
|
||||
|
||||
void Federation::setModelTransform(const QString& fed_id,
|
||||
const ModelTransform& xf) {
|
||||
void Federation::setModelTransformation(const QString& fed_id,
|
||||
const ModelTransformation& xf) {
|
||||
for (auto& m : models_) {
|
||||
if (m.id != fed_id) continue;
|
||||
m.transform_intent = xf;
|
||||
m.model_transformation = xf;
|
||||
setDirty(true);
|
||||
return;
|
||||
}
|
||||
@@ -315,14 +318,14 @@ bool Federation::load(const QString& path,
|
||||
config_.unit_prefix = uo.value("prefix").toString("").toStdString();
|
||||
}
|
||||
|
||||
if (QJsonValue ov = root.value("origin"); ov.isObject()) {
|
||||
if (QJsonValue ov = root.value("federated_false_origin"); ov.isObject()) {
|
||||
QJsonObject oo = ov.toObject();
|
||||
QJsonArray xyz = oo.value("xyz").toArray();
|
||||
if (xyz.size() == 3) {
|
||||
origin_.xyz = Eigen::Vector3d(
|
||||
federated_false_origin_.xyz = Eigen::Vector3d(
|
||||
xyz[0].toDouble(), xyz[1].toDouble(), xyz[2].toDouble());
|
||||
}
|
||||
origin_.rz_deg = oo.value("rz_deg").toDouble(0.0);
|
||||
federated_false_origin_.rz_deg = oo.value("rz_deg").toDouble(0.0);
|
||||
}
|
||||
|
||||
QJsonArray arr = root.value("models").toArray();
|
||||
@@ -360,20 +363,20 @@ bool Federation::load(const QString& path,
|
||||
if (m.display_name.isEmpty())
|
||||
m.display_name = QFileInfo(m.source_path).fileName();
|
||||
|
||||
if (QJsonValue tv = mo.value("transform_intent"); tv.isObject()) {
|
||||
if (QJsonValue tv = mo.value("model_transformation"); tv.isObject()) {
|
||||
QJsonObject to = tv.toObject();
|
||||
const QString af = to.value("a_frame").toString("ModelGlobal");
|
||||
m.transform_intent.a_frame =
|
||||
m.model_transformation.a_frame =
|
||||
(af == "ModelLocal") ? AFrame::ModelLocal : AFrame::ModelGlobal;
|
||||
auto readVec3 = [](QJsonArray ja) {
|
||||
if (ja.size() != 3) return Eigen::Vector3d::Zero().eval();
|
||||
return Eigen::Vector3d(
|
||||
ja[0].toDouble(), ja[1].toDouble(), ja[2].toDouble());
|
||||
};
|
||||
m.transform_intent.a = readVec3(to.value("a").toArray());
|
||||
m.transform_intent.b = readVec3(to.value("b").toArray());
|
||||
m.transform_intent.rxyz_deg = readVec3(to.value("rxyz_deg").toArray());
|
||||
m.transform_intent.pivot = readVec3(to.value("pivot").toArray());
|
||||
m.model_transformation.a = readVec3(to.value("a").toArray());
|
||||
m.model_transformation.b = readVec3(to.value("b").toArray());
|
||||
m.model_transformation.rxyz_deg = readVec3(to.value("rxyz_deg").toArray());
|
||||
m.model_transformation.pivot = readVec3(to.value("pivot").toArray());
|
||||
}
|
||||
|
||||
QJsonValue vv = mo.value("visible");
|
||||
@@ -426,12 +429,12 @@ bool Federation::save(const QString& path, QString* err) {
|
||||
{
|
||||
QJsonObject oo;
|
||||
QJsonArray xyz;
|
||||
xyz.append(origin_.xyz.x());
|
||||
xyz.append(origin_.xyz.y());
|
||||
xyz.append(origin_.xyz.z());
|
||||
xyz.append(federated_false_origin_.xyz.x());
|
||||
xyz.append(federated_false_origin_.xyz.y());
|
||||
xyz.append(federated_false_origin_.xyz.z());
|
||||
oo["xyz"] = xyz;
|
||||
oo["rz_deg"] = origin_.rz_deg;
|
||||
root["origin"] = oo;
|
||||
oo["rz_deg"] = federated_false_origin_.rz_deg;
|
||||
root["federated_false_origin"] = oo;
|
||||
}
|
||||
|
||||
QJsonArray arr;
|
||||
@@ -450,9 +453,9 @@ bool Federation::save(const QString& path, QString* err) {
|
||||
}
|
||||
mo["source"] = so;
|
||||
|
||||
// Skip transform_intent when it's at defaults (identity placement).
|
||||
const ModelTransform def;
|
||||
const ModelTransform& xf = m.transform_intent;
|
||||
// Skip model_transformation when it's at defaults (identity placement).
|
||||
const ModelTransformation def;
|
||||
const ModelTransformation& xf = m.model_transformation;
|
||||
const bool xf_is_default =
|
||||
xf.a_frame == def.a_frame && xf.a == def.a && xf.b == def.b &&
|
||||
xf.rxyz_deg == def.rxyz_deg && xf.pivot == def.pivot;
|
||||
@@ -469,7 +472,7 @@ bool Federation::save(const QString& path, QString* err) {
|
||||
to["b"] = writeVec3(xf.b);
|
||||
to["rxyz_deg"] = writeVec3(xf.rxyz_deg);
|
||||
to["pivot"] = writeVec3(xf.pivot);
|
||||
mo["transform_intent"] = to;
|
||||
mo["model_transformation"] = to;
|
||||
}
|
||||
|
||||
if (!m.visible) mo["visible"] = false;
|
||||
|
||||
Reference in New Issue
Block a user