The local X axis an IfcAxis2Placement3D has when its RefDirection is
absent ($), as ifc-lite's renderer computes it (#5922).
This is the single TypeScript definition. It mirrors build_axis2_matrix
in rust/geometry/src/transform.rs, which the renderer's object and
shape-placement parsers (parse_axis2_placement_3d and its siblings) feed:
each passes world X (1,0,0) for a $ RefDirection, and
build_axis2_matrix projects it onto the plane normal to the normalised
Axis. (Conic surface parametrisation in advanced_face/conics.rs picks its
own reference direction; that is a different concern, not this fill.) That
is the schema's IfcFirstProjAxis(Axis, $) everywhere except next to the
X axis:
when the projection is no longer than 1e-6 (Axis within about 1e-6 rad
of +X or -X), the renderer takes (0,0,1) x Axis instead. For exactly
+X that is (0,1,0), the schema's own switch to world Y. For exactly
-X, where the schema's projection of X vanishes and it gives no
answer, it is (0,-1,0).
an Axis near +X but inside that tolerance with a positive Y or Z offset
gets about (0,+1,0), where the schema's projection points about
(0,-1,0). That is the renderer's behaviour and it is copied here on
purpose: a reader that fills $ differently from the viewer turns the
frame 180 degrees about its Axis relative to what is drawn.
rust/geometry/tests/absent_ref_direction_fill.rs pins the same vectors on
the Rust side; change both together.
A zero-length Axis is read as (0,0,1), as build_axis2_matrix does, and
gives (1,0,0). The result is unit length and perpendicular to the Axis.
The local X axis an
IfcAxis2Placement3Dhas when itsRefDirectionis absent ($), as ifc-lite's renderer computes it (#5922).This is the single TypeScript definition. It mirrors
build_axis2_matrixinrust/geometry/src/transform.rs, which the renderer's object and shape-placement parsers (parse_axis2_placement_3dand its siblings) feed: each passes world X(1,0,0)for a$RefDirection, andbuild_axis2_matrixprojects it onto the plane normal to the normalised Axis. (Conic surface parametrisation inadvanced_face/conics.rspicks its own reference direction; that is a different concern, not this fill.) That is the schema'sIfcFirstProjAxis(Axis, $)everywhere except next to the X axis:(0,0,1) x Axisinstead. For exactly+Xthat is(0,1,0), the schema's own switch to world Y. For exactly-X, where the schema's projection of X vanishes and it gives no answer, it is(0,-1,0).(0,+1,0), where the schema's projection points about(0,-1,0). That is the renderer's behaviour and it is copied here on purpose: a reader that fills$differently from the viewer turns the frame 180 degrees about its Axis relative to what is drawn.rust/geometry/tests/absent_ref_direction_fill.rspins the same vectors on the Rust side; change both together.A zero-length Axis is read as
(0,0,1), asbuild_axis2_matrixdoes, and gives(1,0,0). The result is unit length and perpendicular to the Axis.