pub struct Transform {
pub basis: [[f64; 3]; 3],
pub origin: [f64; 3],
}Expand description
An affine transform: a 3x3 linear part plus a translation.
Column-major: basis[i] is the image of basis vector i.
Fields§
§basis: [[f64; 3]; 3]Images of the X, Y, Z basis vectors.
origin: [f64; 3]Translation applied after the linear part.
Implementations§
Source§impl Transform
impl Transform
Sourcepub const fn translation(origin: [f64; 3]) -> Self
pub const fn translation(origin: [f64; 3]) -> Self
A pure translation.
Sourcepub fn from_axes(
origin: [f64; 3],
axis: Option<[f64; 3]>,
ref_direction: Option<[f64; 3]>,
) -> Option<Self>
pub fn from_axes( origin: [f64; 3], axis: Option<[f64; 3]>, ref_direction: Option<[f64; 3]>, ) -> Option<Self>
Build from an origin and axis directions, Gram-Schmidt orthonormalized.
IFC gives Axis (local Z) and RefDirection (approximate local X) and
explicitly allows them to be non-perpendicular: the spec derives X by
projecting RefDirection onto the plane normal to Axis. Skipping
that projection produces a sheared transform that looks almost right,
which is worse than looking obviously wrong.
Returns None if the axes are degenerate (zero-length or parallel).
This is the schema’s IfcBuildAxes; the two derived axes come from
IfcFirstProjAxis and IfcSecondProjAxis, marked inline below.
Sourcepub fn from_axes_or_identity(
origin: [f64; 3],
axis: Option<[f64; 3]>,
ref_direction: Option<[f64; 3]>,
) -> Self
pub fn from_axes_or_identity( origin: [f64; 3], axis: Option<[f64; 3]>, ref_direction: Option<[f64; 3]>, ) -> Self
Self::from_axes, falling back to the identity transform when the
axes are absent or degenerate.
IFC’s Axis/RefDirection are both optional and, per spec, default to
the standard basis when omitted — the common case, so most call sites
that use from_axes immediately follow it with
.unwrap_or_else(Transform::identity). This collapses that
boilerplate. Reach for from_axes directly when a degenerate axis
pair should be a reportable error instead of a silent identity.
Sourcepub fn determinant(&self) -> f64
pub fn determinant(&self) -> f64
The determinant of the linear part: the signed volume scale.
Negative when the transform mirrors (reverses handedness), positive
when it preserves it; its magnitude is the volume scale factor. Zero or
non-finite only for a degenerate basis, which an IFC placement or a
cartesian transformation operator cannot state validly (Scale is
positive and the axes are independent).
Sourcepub fn apply_direction(&self, v: [f64; 3]) -> [f64; 3]
pub fn apply_direction(&self, v: [f64; 3]) -> [f64; 3]
Apply the linear part only, without translating.
Correct for vectors and tangents. Surface normals under non-uniform scale
must use apply_unit_normal instead.
Sourcepub fn to_geom_frame(self, entity: EntityId) -> GeometryResult<Frame3>
pub fn to_geom_frame(self, entity: EntityId) -> GeometryResult<Frame3>
Convert to a neutral orthonormal frame at the IFC boundary.
axiolid_core::Frame3 is structurally public and cannot enforce unit,
orthogonal, right-handed axes itself. This method is therefore the one
executable IFC-to-Axiolid frame contract. It rejects non-finite origins,
scaled or sheared axes, and mirrored frames before neutral construction.
IFC placements reach this method after Axis/RefDirection have been
normalized and Gram-Schmidt orthogonalized; mapped-item scale stays on
an Instance transform and must never leak into a surface frame.
Sourcepub fn to_geom(self) -> Transform3
pub fn to_geom(self) -> Transform3
Convert to the format-neutral geometry transform at the IFC boundary.
Sourcepub fn compose(&self, inner: &Transform) -> Transform
pub fn compose(&self, inner: &Transform) -> Transform
Compose: self applied after inner.
This is the operation a placement chain folds with. Order matters and
getting it backwards places every child relative to the wrong parent,
so the convention is stated here once: parent.compose(&child) yields
the child’s world transform.
Sourcepub fn scaled(&self, factor: f64) -> Transform
pub fn scaled(&self, factor: f64) -> Transform
Scale the linear part uniformly, e.g. for a transformation operator.
Sourcepub fn scaled_nonuniform(&self, factors: [f64; 3]) -> Transform
pub fn scaled_nonuniform(&self, factors: [f64; 3]) -> Transform
Scale each axis independently, for the non-uniform operator.
Sourcepub fn to_metres(self, units: &UnitScale) -> Transform
pub fn to_metres(self, units: &UnitScale) -> Transform
Convert the translation to metres, leaving the basis dimensionless.
IFC coordinates carry the file’s length unit; direction ratios and scale factors do not. Scaling the basis as well would compound the unit into every rotation and silently resize geometry, so only the origin is converted. Apply this exactly once, at the boundary where a source frame becomes project space.
Sourcepub fn is_identity(&self, tolerance: f64) -> bool
pub fn is_identity(&self, tolerance: f64) -> bool
Is this within tolerance of the identity?