Class TransformationUtil
Utilities for the ProgramToMcTransform chain.
Each entry is {Source, Kind, Mat4d}; entries are composed in order
with pure matrix multiplication (GetComposedTransform(JsonObject)).
KindKey partitions the entries by contour validity:
- KindStatic — the matrix is valid across the whole block, applicable to any interpolated point along the contour.
- KindDynamic — the matrix is a block-endpoint snapshot of a rotary-state-dependent transform (RTCP rotary-dynamic). Composing it produces a correct endpoint MC, but interpolated points along the contour must be derived per-step by motion semantics (ClLinearMcMotionSemantic); do not apply it to interpolated ProgramXyz.
public static class TransformationUtil
- Inheritance
-
TransformationUtil
- Inherited Members
Fields
KindDynamic
The entry's Mat4d is a block-endpoint snapshot only; intermediate contour points must be resolved by per-step IK in motion semantics.
public const string KindDynamic = "Dynamic"
Field Value
KindKey
JSON key for the entry's contour-validity classification. Value must be KindStatic or KindDynamic.
public const string KindKey = "Kind"
Field Value
KindStatic
The entry's Mat4d is valid for any point along the contour.
public const string KindStatic = "Static"
Field Value
Mat4dKey
JSON key for the Mat4d snapshot inside each chain entry.
public const string Mat4dKey = "Mat4d"
Field Value
PivotTransformSource
Canonical source name for the RTCP pivot transform — the kinematic transform from Pn (post-G54, post-G68.2) to MC at the block's endpoint ABC. Contributed by PivotTransformationSyntax. Must be the last entry written into the chain so that all Pn-frame operations (tilt, tool-height, coord-offset) are accumulated before the final kinematic IK; this ordering is enforced by the syntax- chain registration order, not by the writer API.
public const string PivotTransformSource = "PivotTransform"
Field Value
SourceKey
JSON key for the transform origin label inside each chain entry.
public const string SourceKey = "Source"
Field Value
ToolHeightCompensationSource
Canonical source name for the tool-height-compensation entry
(tool-normal · offset_mm along the current tool axis). Matches the
ToolHeightCompensation section key read for
Offset_mm.
public const string ToolHeightCompensationSource = "ToolHeightCompensation"
Field Value
Methods
AddOrReplaceTransform(JsonObject, string, string, Mat4d)
Adds or replaces a named transformation entry in the chain.
If an entry with the same source already exists, it is replaced in-place.
Otherwise the new entry is appended.
kind must be KindStatic or KindDynamic.
public static void AddOrReplaceTransform(JsonObject json, string source, string kind, Mat4d mat)
Parameters
jsonJsonObjectsourcestringkindstringmatMat4d
GetComposedTransform(JsonObject)
Composes all entries in the chain into a single block-endpoint Mat4d (left-to-right multiplication). Pure multiplication — no special cases, no kinematic lookup. The returned matrix is valid only for the block's endpoint state; see ProgramToMcTransform for the endpoint-semantic contract.
public static Mat4d GetComposedTransform(JsonObject json)
Parameters
jsonJsonObject
Returns
GetComposedTransformAtAbc(JsonObject, Vec3d, Vec3d, IMachineKinematics, double)
Composes the chain into the Mat4d valid at an INTERPOLATED contour
point whose rotary state is stepAbc_rad, by
rebuilding every KindDynamic entry at that rotary state
while keeping every KindStatic entry's stored snapshot.
The per-step dual of GetComposedTransform(JsonObject), which is
endpoint-only when the chain carries a Dynamic entry.
public static Mat4d GetComposedTransformAtAbc(JsonObject json, Vec3d stepAbc_rad, Vec3d endpointAbc_rad, IMachineKinematics kinematics, double toolHeightOffset_mm)
Parameters
jsonJsonObjectThe block's JSON sections carrying the chain.
stepAbc_radVec3dThe interpolated point's MC rotary state in radians (NaN axes are treated as 0, mirroring ResolveEndpointAbc(LazyLinkedListNode<SyntaxPiece>, IMachineAxisConfig)).
endpointAbc_radVec3dThe block-endpoint MC rotary state in radians — the state the stored Dynamic snapshots were built at.
kinematicsIMachineKinematicsThe machine kinematics; null keeps every stored snapshot.
toolHeightOffset_mmdoubleThe block's ToolHeightCompensation offset in mm (the value its Dynamic height entry was built with).
Returns
Remarks
Rebuild rules, per Dynamic entry source:
- ToolHeightCompensationSource — rebuilt with
MakeToolHeightMat(IMachineKinematics, Vec3d, double) at
stepAbc_radandtoolHeightOffset_mm: the same construction every writer uses (G43p4RtcpSyntax, SiemensTraoriSyntax), so atstepAbc_radequal to the block-endpoint ABC the rebuilt matrix is bit-identical to the stored snapshot. - PivotTransformSource — rebuilt
anchor-agnostically as
stored · K(endpointAbc) · K(stepAbc)⁻¹, recovering the writer's pre-pivot anchor (preFrameToPn = stored · K(endpointAbc), see MakePivotTransformMat(IMachineKinematics, Vec3d, Mat4d)) from the snapshot itself instead of assuming the NC pipeline's machine-zero anchor — the CLSF pivot (ClToMcTransformSyntax) folds a fixture-topology anchor into the same entry and stays correct here. - Any other Dynamic source — kept as stored (no rebuild recipe; no shipped writer produces one).
null kinematics every entry keeps its
stored snapshot, collapsing to GetComposedTransform(JsonObject) —
correct for the only kinematics-less Dynamic corner (the
G43p4RtcpSyntax UnitZ height fallback,
whose matrix does not depend on ABC).
GetTransformBySource(JsonObject, string)
Gets a specific entry's Mat4d by source name. Returns identity if not found.
public static Mat4d GetTransformBySource(JsonObject json, string source)
Parameters
jsonJsonObjectsourcestring
Returns
HasDynamicEntry(JsonObject)
Returns true if any entry in the chain carries
KindDynamic. Used by motion-form selection
(LinearMotionSyntax) and ProgramXyz
strategy dispatch (ProgramXyzUtil) to
detect RTCP-rotary-dynamic state without consulting a flag on a
sibling section. Throws if any entry lacks KindKey.
public static bool HasDynamicEntry(JsonObject json)
Parameters
jsonJsonObject
Returns
MakePivotTransformMat(IMachineKinematics, Vec3d)
Builds the PivotTransformSource Mat4d — an
empirically-constructed Pn→MC rigid-affine transform at the block's
endpoint ABC. Equivalent to
kinematics.PnToMc(pn_input, normal).Point when applied to
a Pn-frame point, but expressed as a reusable Mat4d so the chain
stays a pure matrix product (no per-point IK call inside
GetComposedTransform(JsonObject)).
The pre-pivot anchor is the machine-zero attacher point
McToPn(0).Point as a pure translation — the same
origin anchor HardNc keeps in
HardNcEnv.AttacherAtMcZeroOnTableCoordinate. Program-frame
vectors already point along the Pn (table-buckle) axes, so only
K(0)'s translation may enter the anchor. Folding the full
K(0) (its linear part encodes per-axis motion sense — a
workpiece-side linear axis contributes a negated row)
would flip those axes' program components before the IK; on a
machine whose Z rides the table (e.g. the B-x7000 WAC chain,
table branch Base→Z→B→W) that mirrored every program Z
and, at B≈180°, threw the resolved MC off by twice the
pivot-to-attacher distance (~3.5 m).
Requiring machine files to be modelled the other way instead —
workpiece-side axes negative, which makes K(0)'s linear part
the identity and the two constructions equivalent — was evaluated as
an alternative to this fix and deliberately rejected.
IMachineKinematics resolves either axis direction, so a
file that positions correctly through
PnToMc(DVec3d, out DVec3d) has to position correctly
through this transform as well; a precondition enforced here and
nowhere else would only make one consumer diverge from the kinematics
on files every other consumer accepts. The modelling convention
governs how MC values read against the machine panel, and belongs to
a check on the data when it loads — never to this matrix.
Constructed by probing McToPn(DVec3d) at
the four standard basis points (origin + XYZ unit vectors) at the
target ABC to derive K(abc); returns
T(McToPn(0).Point) · K(abc).GetInverse(). Topology-
agnostic — works for any affine kinematic chain regardless of axis
order. Legacy PnToMc(DVec3d, out DVec3d) remains the
reference oracle.
public static Mat4d MakePivotTransformMat(IMachineKinematics kinematics, Vec3d abc_rad)
Parameters
kinematicsIMachineKinematicsabc_radVec3d
Returns
MakePivotTransformMat(IMachineKinematics, Vec3d, Mat4d)
Variant anchored to an arbitrary pre-pivot frame: builds the
PivotTransformSource Mat4d
preFrameToPn · K(abc)⁻¹ that maps a point of the chain's
accumulated pre-pivot frame directly to MC at the block's endpoint
ABC. The two-parameter overload is this variant specialised to the
NC pipeline's machine-zero program frame
(preFrameToPn = T(McToPn(0).Point), translation only — see
its remarks for why K(0)'s linear part must stay out); the
CLSF pipeline passes its workpiece→Pn fixture-topology matrix
instead, so the pivot entry absorbs the workpiece placement
together with the kinematics.
public static Mat4d MakePivotTransformMat(IMachineKinematics kinematics, Vec3d abc_rad, Mat4d preFrameToPn)
Parameters
kinematicsIMachineKinematicsabc_radVec3dpreFrameToPnMat4d
Returns
MakeToolHeightMat(IMachineKinematics, Vec3d, double)
Builds the tool-height-compensation Mat4d for a given rotary state:
translate by (tool-normal at abc_rad) · height_mm.
Pure translation (no rotation component); combines with the
downstream PivotTransformSource to form the full
Pn→MC IK.
public static Mat4d MakeToolHeightMat(IMachineKinematics kinematics, Vec3d abc_rad, double height_mm)
Parameters
kinematicsIMachineKinematicsabc_radVec3dheight_mmdouble