placementTransform function
Transform2
placementTransform({})
translation(at) · rotation · scale(mirrored ? -1 : 1, 1) · translation(-basePoint): the definition's base point lands on at
(spec F-2), and a mirror flips the local x axis whatever the
rotation.
The rotation is given one of two ways, never both (an ArgumentError, in release builds too):
quarterTurnscounter-clockwise, taken modulo 4 (negative allowed), with exact cosine and sine from a table (0 and ±1, never6e-17);rotation, a unit vector(cos, sin)used exactly as given (spec 09c D5: a wall face'st).
Neither is no turn. The quarter-turn form is the rotation form at its
table entry, so the two give the same bytes. No stored component is
-0.0 in either form, so a placement stores clean numbers in a file.
Implementation
Transform2 placementTransform({
required Vector2 at,
required Vector2 basePoint,
int? quarterTurns,
(double, double)? rotation,
bool mirrored = false,
}) {
if (quarterTurns != null && rotation != null) {
throw ArgumentError(
'placementTransform takes quarterTurns or rotation, not both');
}
final (cos, sin) = rotation ?? _quarterTurn(quarterTurns ?? 0);
final m = Transform2.translation(at.x, at.y)
.multiply(Transform2(cos, sin, -sin, cos, 0, 0))
.multiply(Transform2.scale(mirrored ? -1 : 1, 1))
.multiply(Transform2.translation(-basePoint.x, -basePoint.y));
double clean(double v) => v == 0 ? 0.0 : v;
return Transform2(
clean(m.a), clean(m.b), clean(m.c), clean(m.d), clean(m.e), clean(m.f));
}