- 1. itransform
- 1.1. Syntax
- 1.2. Stack Effects
- 1.3. Description
- 1.4. PostScript Level
- 1.5. Examples
- 1.6. Common Use Cases
- 1.7. Common Pitfalls
- 1.8. Error Conditions
- 1.9. Implementation Notes
- 1.10. Transformation Formula
- 1.11. Relationship to Other Operators
- 1.12. Use in Interactive Applications
- 1.13. Performance Considerations
- 1.14. See Also
1. itransform
Transforms coordinates from device space to user space (inverse transform).
1.2. Stack Effects
| Level | Object |
|---|---|
1 |
|
0 |
|
| Level | Object |
|---|---|
1 |
|
0 |
|
1.3. Description
With no matrix operand, itransform (inverse transform) transforms the device space coordinate (x', y') by the inverse of the current transformation matrix (CTM) to produce the corresponding user space coordinate (x, y).
If the matrix operand is supplied, itransform transforms (x', y') by the inverse of matrix rather than by the inverse of CTM.
This is the inverse operation of transform. It converts device coordinates (pixel positions) back to user coordinates (the coordinate system used for drawing).
1.5. Examples
100 100 translate
2 2 scale
% Forward transformation
50 50 transform
% → 200.0 200.0
% Inverse transformation
200 200 itransform
% → 50.0 50.0 (back to original)
/m [2 0 0 2 100 100] def
200 200 m itransform
% → 50.0 50.0
% Inverse of (x-100)/2, (y-100)/2
% Convert device coordinates (pixels) to user coordinates
/deviceX 300 def
/deviceY 400 def
deviceX deviceY itransform
% → user space coordinates
1.6. Common Use Cases
1.6.1. Hit Testing
% Check if device point is inside user space rectangle
/deviceClick { % deviceX deviceY -> bool
itransform % Convert to user space
% Check bounds in user space
dup 0 ge exch 100 le and
exch dup 0 ge exch 100 le and
and
} def
250 300 deviceClick % Check if click is in rectangle
1.6.2. Event Handling
% Convert mouse events to drawing coordinates
/handleMouseDown { % deviceX deviceY
gsave
% Current transformations in effect
itransform
/userY exch def
/userX exch def
% Process in user coordinates
userX userY processClick
grestore
} def
1.7. Common Pitfalls
Includes Translation - itransform uses the full inverse transformation including translation. Use idtransform for distance vectors.
|
100 100 translate
% For points:
150 200 itransform % → 50 100 (correct)
% For distances:
100 100 itransform % → 0 0 (wrong - includes translation)
100 100 idtransform % → 100 100 (correct - distance)
Singular Matrices - If CTM or matrix is singular (determinant = 0), itransform fails.
|
0 0 scale % Creates singular matrix (determinant = 0)
100 100 itransform % Error: undefinedresult
| Precision Loss - Very large transformations may cause precision loss in the inverse. |
1000000 1000000 scale
1 1 itransform
% May not return exactly 0.000001 0.000001
% due to floating-point precision
| Use for Interactive Graphics - Essential for converting mouse/touch coordinates: |
% In drawing application
/handleClick { % deviceX deviceY
gsave
% Apply all user transformations
panX panY translate
zoom zoom scale
rotation rotate
% Convert click to drawing coordinates
itransform
/drawY exch def
/drawX exch def
% Process click in drawing coordinates
drawX drawY addPoint
grestore
} def
| Verify Round-Trip - Test that transform/itransform are inverses: |
/testTransform {
% userX userY
2 copy transform itransform
% Should return original values
3 -1 roll sub abs 0.001 lt
3 1 roll exch sub abs 0.001 lt and
{ (OK) } { (Error!) } ifelse print
} def
100 200 testTransform
1.8. Error Conditions
| Error | Condition |
|---|---|
[ |
Matrix operand does not have exactly 6 elements |
[ |
Fewer than 2 operands on stack (first form) or fewer than 3 (second form) |
[ |
Operands are not numbers, or matrix operand is not an array |
[ |
CTM or matrix is singular (determinant = 0) and cannot be inverted |
1.9. Implementation Notes
-
Requires computing the matrix inverse
-
More expensive than
transform(forward transformation) -
The inverse CTM is not cached; computed each time
-
Precision depends on CTM condition number
-
Used automatically by many interactive operators
1.10. Transformation Formula
For CTM = [a b c d tx ty], the inverse transformation is:
det = a×d - b×c x = (d×(x' - tx) - c×(y' - ty)) / det y = (a×(y' - ty) - b×(x' - tx)) / det
Example with CTM = [2 0 0 2 100 100]:
det = 2×2 - 0×0 = 4 (200, 200) inverse transforms to: x = (2×(200-100) - 0×(200-100)) / 4 = 200/4 = 50 y = (2×(200-100) - 0×(200-100)) / 4 = 200/4 = 50 → (50, 50)
1.11. Relationship to Other Operators
% Forward and inverse are opposites:
userX userY transform itransform
% → userX userY (round-trip)
deviceX deviceY itransform transform
% → deviceX deviceY (round-trip)
% Using explicit matrix:
x y m transform m itransform
% → x y
% Equivalent to using inverse matrix:
m matrix invertmatrix % Get inverse
x y transform % Transform by inverse
1.12. Use in Interactive Applications
% Typical pattern for interactive graphics
/processInput { % deviceX deviceY eventType
/event exch def
itransform % Convert to user space
event (mousedown) eq {
handleMouseDown
} if
event (mousemove) eq {
handleMouseMove
} if
} def
1.13. Performance Considerations
-
Slightly slower than
transform(requires matrix inversion) -
Still very fast for occasional use
-
If called frequently with same matrix, consider precomputing inverse:
% Inefficient:
{
deviceX deviceY itransform
% ... process ...
} repeat
% Efficient:
matrix currentmatrix matrix invertmatrix
/inverseMatrix exch def
{
deviceX deviceY inverseMatrix transform
% ... process ...
} repeat
1.14. See Also
-
transform- Transform user to device coordinates -
dtransform- Transform distance vector -
idtransform- Inverse transform distance vector -
invertmatrix- Invert transformation matrix -
currentmatrix- Get current CTM