transforms.ps - Some useful transforms in PostScript
(/home/wherever/ps/lib/transforms.ps) run % to send it to a printer see include_run . . . /rect { 4 dict begin [ /h /w /y /x ] { exch def } forall x y moveto w 0 rlineto 0 h rlineto 0 w sub 0 rlineto closepath end } def % like rectfill, except it just constructs the path /HelveticaBold 310 selectfont % the vanishing-point will be 300,400 % left of the vanishing-point, we start printing text at x0 /x0 20 def x0 375 moveto (MHXWENZE) true charpath [ 300 400 x0 ] /perspective_xy2uv c_transform fill % but right of the VP, we start the text at x0-stringwidth /x0 570 def /x_start_of_string x0 (MHXWENZE) stringwidth pop sub def x_start_of_string 375 moveto (MHXWENZE) true charpath % [ x0 theta ] % at x0, the text is at theta degrees to the viewer [ 300 400 x0 20 ] /perspective_xy2uv c_transform fill /y0 20 def 70 y0 24 5000 rect 490 y0 24 5000 rect 0.5 setgray [ 300 400 y0 20 ] /perspective_flat_xy2uv c_transform fill showpage 18 36 575 { /x exch def 18 36 808 { /y exch def x y 20 20 rect } for } for % construct a path 0.8 setgray % [x_amplitud y_wavelen y_phase y_amplitud x_wavelen x_phase] [9 300 0 6 200 90] /sine_xy2uv c_transform fill showpage 18 30 575 { /x exch def 18 30 808 { /y exch def x y 16 16 rect } for } for % construct a path % [ x y r magnification ] [ 120 700 80 1.8 ] /softlens_xy2uv c_transform [ 120 450 80 1.8 ] /hardlens_xy2uv c_transform % [ x y r angle ] [ 350 200 70 60 ] /twist_xy2uv c_transform % [ x y r range ] [ 400 600 70 90 ] /collapse_xy2uv c_transform fill
This module implements in PostScript some useful transforms.
It is mostly useful for non-linear transforms,
since the linear transforms are more easily done with
translate, scale and concat.
It can only transform paths, so to transform text
the path must be generated by using charpath,
then transfomed, and finally made visible by fill (or stroke).
This means that only text in Type-1 fonts can be transformed.
For example, the custom fonts
Bitfont5x7, FatSimple and FatSimpleItalic
in fonts.ps are not Type-1 fonts.
The procedures here transform the current path. Unlike the built-ins translate, scale and concat, they do not transform the coordinate-system and so do not have to be protected between a gsave and grestore. Anything already stroked or filled onto the page is of course not moved.
For some simple examples, see test_transforms.pdf, a pdf version of the test-file. (The PostScript source is on github.)
Just as a handy reference:
the PostScript matrix as used by concat is the array:
[ a b c d tx ty ]
where the transformation x,y
to x',y'
is:
x' = a.x + c.y + tx
y' = b.x + d.y + ty
ctransform c_transform collapse_xy2uv perspective_xy2uv perspective_flat_xy2uv sine_xy2uv softlens_xy2uv hardlens_xy2uv twist_xy2uv
This procedure comes straight from chapter 8 of
Mathematical Illustrations: A Manual of Geometry and Postscript by
Bill Casselman
and makes possible all kinds of non-linear translations of the current path.
It takes one argument, which is a named procedure to transform the
coordinates x and y into the resulting u and v
Note that a single long line such as
10 145 moveto 580 145 lineto
remains a long straight line;
it's in the nature of pathforall
that only the join-points get moved.
So you probably want something like:
10 145 moveto 15 5 580 { 145 lineto } for
which expresses the line in many smaller segments.
c_transform is extended from ctransform to allow the specification of an array of parameters for the _xy2uv routine.
It takes two arguments. Second-to-top of the stack is an array containing the parameters which will be used by the xy2uv_proc. Top of the stack is a named procedure to transform the coordinates x and y into the resulting u and v
There now follow various such named procedures, implementing some useful transformations . . .
collapse_xy2uv implements a "collapse" transform (think Black Hole, or Macular Degeneration) in which everything within a given circle collapses down to the center, and things outside that circle (within a given range of it) stretch inward to fill the gap.
perspective_xy2uv implements a perspective-transformation
in which parallel lines converge toward a vanishing-point
at xvp
,yvp
.
The lines are assumed to lie in a vertical surface,
such as a building-facade, or a wall, or a billboard.
perspective_xy2uv
looks at four parameters :
xvp
,yvp
which are the vanishing-point,
x0
which is the x at which the heights are to scale 1:1,
and theta
which is the angle at which the viewer sees the x0
point.
So if theta=90
the viewer is face-on to the x=u=x0
point.
In practice, theta
is typically between 20 and 60 degrees.
theta
is currently implemented in a cheap kludge
in which the obliqueness is constant all the way to the horizon,
whereas in reality the obliqueness becomes more extreme
as the vanising-point is approached . . .
If theta
is missing, the text is displayed at full width
(as if viewed face-on), may be good for legibility but is less realistic,
since in reality it would be seen from a more oblique angle.
perspective_flat_xy2uv is like
perspective_xy2uv
in that parallel lines converge toward a vanishing-point
at xvp
,yvp
,
except that the parallel lines are assumed to lie on a horizontal surface,
for example the ground.
xvp
,yvp
specify the vanishing-point.
y0
is the y at which the widths are to scale 1:1,
which for surfaces below eye-level will be less than yvp
.
theta
which is the angle at which the viewer sees the y0
point.
sine_xy2uv implements a sine-waviness in the coordinate grid.
The vertical lines get a horizontal waviness
with a wavelength in the y coordinate,
and conversely the horizontal lines get a waviness in the y direction
with a wavelength in the x coordinate.
An array of six parameters is needed. In order:
x_amplitude
,
y_wavelength
and
y_phase
for the waviness in the vertical lines, and
y_amplitude
,
x_wavelength
and
x_phase
for the waviness in the horizontal lines.
softlens_xy2uv implements a soft-edged magnifying-glass
over the coordinate grid.
An array of four parameters is needed. In order:
x
,
y
,
radius
and
magnification
.
hardlens_xy2uv implements a hard-edged magnifying-glass
over the coordinate grid.
An array of four parameters is needed. In order:
x
,
y
,
radius
and
magnification
.
twist_xy2uv implements a twist in the coordinate grid.
An array of four parameters is needed. In order:
x
,
y
,
radius
and
angle
.
The degrees-of-twist decay exponentially with the radial distance
from the centre.
grand_xy2uv moves each point by gaussian-random distance,
and the standard-deviation in the x and y coordinates
is specified separately.
So an array of two parameters is needed, namely:
stdev_x
and
stdev_y
If you use this, you will need to run the
random.ps library.
For example:
(/home/wherever/ps/lib/random.ps) run
/Times-Roman 110 selectfont
20 700 moveto ( Gaussian) true charpath
20 600 moveto (SCDOGJPQ) true charpath
20 500 moveto (QSCDOGJP) true charpath
20 400 moveto (PQSCDOGJ) true charpath
20 300 moveto (JPQSCDOG) true charpath
20 200 moveto (GJPQSCDO) true charpath
20 100 moveto (OGJPQSCD) true charpath
[3 7] /grand_xy2uv c_transform
gsave 1 0 0 setrgbcolor fill grestore
0 0 0 setrgbcolor 3 setlinewidth stroke
To install: go to
www.pjb.com.au/comp/free/transforms.ps.txt
and save the file to your local disc.
Rename it to transforms.ps and move it into some appropriate
directory such as ~/ps/lib
. . .
Or, first change directory to where you keep your PostScript libraries:
cd /home/wherever/ps/lib/
(or wherever) and then either:
wget -O transforms.ps http://www.pjb.com.au/comp/free/transforms.ps.txt
or:
curl http://www.pjb.com.au/comp/free/transforms.ps.txt -o transforms.ps
Or, get it from github:
git clone
https://github.com/peterbillam/postscriptlib
Peter J Billam www.pjb.com.au/comp/contact.html
20170510 added grand_xy2uv 20160723 perspective and perspective_flat get a [xvp yvp x0 theta] syntax 20160722 added collapse, perspective_flat, sine, softlens, hardlens, twist 20160717 first release
Back to P J B Computing or to www.pjb.com.au . . .