mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 17:57:02 +00:00
Updates IfcAxis2PlacementLinear and matrix4::init per @aothms suggestions
This commit is contained in:
@@ -29,34 +29,26 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcAxis2PlacementLinear* inst)
|
|||||||
Logger::Error(std::runtime_error("Location must be IfcPointByDistanceExpression for IfcAxis2PlacementLinear"));
|
Logger::Error(std::runtime_error("Location must be IfcPointByDistanceExpression for IfcAxis2PlacementLinear"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Eigen::Vector3d o, axis(0, 0, 1), refDirection;
|
|
||||||
|
|
||||||
taxonomy::matrix4::ptr m = taxonomy::cast<taxonomy::matrix4>(map(inst->Location()));
|
taxonomy::matrix4::ptr m = taxonomy::cast<taxonomy::matrix4>(map(inst->Location()));
|
||||||
o = m->components().col(3).head<3>();
|
Eigen::Vector3d o = m->components().col(3).head<3>();
|
||||||
|
|
||||||
// From 8.9.3.4 IfcAxis2PlacementLinear there are 4 cases that need to be considered
|
// From 8.9.3.4 IfcAxis2PlacementLinear there are 4 cases that need to be considered
|
||||||
// 1) Axis is given but not RefDirection
|
// 1) Axis is given but not RefDirection
|
||||||
// 2) RefDirection is given but not Axis
|
// 2) RefDirection is given but not Axis
|
||||||
// 3) Neither Axis or RefDirection are provided
|
// 3) Neither Axis or RefDirection are provided
|
||||||
// 4) Both Axis and RefDirection are provided
|
// 4) Both Axis and RefDirection are provided
|
||||||
|
// When Axis or RefDirection are not provided explicitly in the IfcAxis2PlacementLinear,
|
||||||
|
// they are taken from the context of curve by evaluating the Location, which is an IfcPointByDistanceExpression on a curve.
|
||||||
|
// The curve tangent is used as RefDirection and the curve normal is used as Axis.
|
||||||
|
|
||||||
const bool hasAxis = inst->Axis() != nullptr;
|
const bool hasAxis = inst->Axis() != nullptr;
|
||||||
const bool hasRef = inst->RefDirection() != nullptr;
|
const bool hasRef = inst->RefDirection() != nullptr;
|
||||||
|
|
||||||
/*
|
Eigen::Vector3d axis, refDirection;
|
||||||
if (hasAxis != hasRef) {
|
|
||||||
Logger::Warning("Axis and RefDirection should be specified together", inst);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (hasAxis && !hasRef) {
|
if (hasAxis && !hasRef) {
|
||||||
taxonomy::direction3::ptr a = taxonomy::cast<taxonomy::direction3>(map(inst->Axis()));
|
taxonomy::direction3::ptr a = taxonomy::cast<taxonomy::direction3>(map(inst->Axis()));
|
||||||
axis = *a->components_;
|
axis = *a->components_;
|
||||||
|
|
||||||
refDirection = m->components().col(0).head<3>(); // RefDirection is the curve tangent when omitted
|
refDirection = m->components().col(0).head<3>(); // RefDirection is the curve tangent when omitted
|
||||||
// refDirection is not necessarily orthogonal to axis.
|
|
||||||
// axis.cross(refDirection) gives y. y.cross(axis) gives x=refDirection
|
|
||||||
refDirection = axis.cross(refDirection).cross(axis);
|
|
||||||
} else if (!hasAxis && hasRef) {
|
} else if (!hasAxis && hasRef) {
|
||||||
taxonomy::direction3::ptr r = taxonomy::cast<taxonomy::direction3>(map(inst->RefDirection()));
|
taxonomy::direction3::ptr r = taxonomy::cast<taxonomy::direction3>(map(inst->RefDirection()));
|
||||||
refDirection = *r->components_;
|
refDirection = *r->components_;
|
||||||
@@ -67,13 +59,10 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcAxis2PlacementLinear* inst)
|
|||||||
} else {
|
} else {
|
||||||
taxonomy::direction3::ptr a = taxonomy::cast<taxonomy::direction3>(map(inst->Axis()));
|
taxonomy::direction3::ptr a = taxonomy::cast<taxonomy::direction3>(map(inst->Axis()));
|
||||||
axis = *a->components_;
|
axis = *a->components_;
|
||||||
|
|
||||||
taxonomy::direction3::ptr r = taxonomy::cast<taxonomy::direction3>(map(inst->RefDirection()));
|
taxonomy::direction3::ptr r = taxonomy::cast<taxonomy::direction3>(map(inst->RefDirection()));
|
||||||
refDirection = *r->components_;
|
refDirection = *r->components_;
|
||||||
refDirection = axis.cross(refDirection).cross(axis); // refDirection needs to be orthogonal to axis
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// axis and refDirection need to be orthogonal
|
|
||||||
return taxonomy::make<taxonomy::matrix4>(o, axis, refDirection);
|
return taxonomy::make<taxonomy::matrix4>(o, axis, refDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-14
@@ -277,20 +277,40 @@ typedef item const* ptr;
|
|||||||
struct IFC_GEOM_API matrix4 : public item, public eigen_base<Eigen::Matrix4d> {
|
struct IFC_GEOM_API matrix4 : public item, public eigen_base<Eigen::Matrix4d> {
|
||||||
private:
|
private:
|
||||||
void init(const Eigen::Vector3d& o, const Eigen::Vector3d& z, const Eigen::Vector3d& x) {
|
void init(const Eigen::Vector3d& o, const Eigen::Vector3d& z, const Eigen::Vector3d& x) {
|
||||||
auto Z = z.normalized();
|
auto valid_and_non_zero_extent = [](const Eigen::Vector3d&v,double eps = 1.e-9) {
|
||||||
auto Y = Z.cross(x).normalized();
|
return v.allFinite() && v.squaredNorm() > eps*eps;
|
||||||
auto X = Y.cross(Z);
|
};
|
||||||
components_ = new Eigen::Matrix4d;
|
|
||||||
(*components_) <<
|
// check z and x are valid vectors
|
||||||
X(0), Y(0), Z(0), o(0),
|
if (!valid_and_non_zero_extent(z) || !valid_and_non_zero_extent(x)) {
|
||||||
X(1), Y(1), Z(1), o(1),
|
throw std::runtime_error("Invalid during for matrix4 construction");
|
||||||
X(2), Y(2), Z(2), o(2),
|
}
|
||||||
0, 0, 0, 1.;
|
|
||||||
if (is_identity()) {
|
auto Z = z.normalized(); // ensure Z is a unit vector
|
||||||
// @todo detect this earlier to save us the heapalloc.
|
auto Y = Z.cross(x); // Y is orthogonal to x and Z
|
||||||
delete components_;
|
|
||||||
components_ = nullptr;
|
// make sure Y is a valid vector
|
||||||
tag = IDENTITY;
|
if (!valid_and_non_zero_extent(Y)) {
|
||||||
|
throw std::runtime_error("Parallel or degenerate matrix4 construction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Y.normalize(); // ensure Y is a unit vector
|
||||||
|
auto X = Y.cross(Z); // X is orthogonal to Y and Z, and a unit vector
|
||||||
|
|
||||||
|
// check if this is going to be an identity matrix
|
||||||
|
double eps = 1.e-9;
|
||||||
|
if (X.isApprox(Eigen::Vector3d(1., 0., 0.), eps) &&
|
||||||
|
Y.isApprox(Eigen::Vector3d(0., 1., 0.), eps) &&
|
||||||
|
Z.isApprox(Eigen::Vector3d(0., 0., 1.), eps) &&
|
||||||
|
o.isApprox(Eigen::Vector3d(0., 0., 0.), eps)) // in the full 4x4 matrix, this will be (0,0,0,1)
|
||||||
|
{
|
||||||
|
tag = IDENTITY;
|
||||||
|
} else {
|
||||||
|
components_ = new Eigen::Matrix4d;
|
||||||
|
(*components_) << X(0), Y(0), Z(0), o(0),
|
||||||
|
X(1), Y(1), Z(1), o(1),
|
||||||
|
X(2), Y(2), Z(2), o(2),
|
||||||
|
0, 0, 0, 1.;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user