An example of dmmlib

This is a simple example of how I create diagrams in postscript. It makes heavy use of dmmlib, my personal postscript library, as well as some ad-hoc functions. A certain amount of existing postscript knowledge is helpful to understand it but if you know that it's a stack-based language for drawing text and images on a page, and that % is the comment marker and that { } creates a block, you can probably make sense of it.

The image is meaningless, created when "doodling" in ps for fun.

%!
(dmmlib/base.ps) run
(dmmlib/lines.ps) run
%
% I have defined "circle" and "spcircle" as taking the arguments x y rad.
% This takes that plus one argument, so that tcircle and hcircle below
% can provide n and then match the signature of circle.
%
% arg = exch def. Handy way to pull arguments off the stack.
% I've started tucking the arguments to functions and for-loops here.
/ncircle { /n arg /rad arg /y arg /x arg
    % My spcircle has thick points at 0 and 180.  For the orientation and 
    % symmetry of this design, I wanted a thick point at 90 and 3 or 6
    % points total.
    x y translate
    % n block circrepeat = repeat with a 360/n rotate after each block.
    % Everything happens in the current reference frame and rotates back
    % around, so I can add to the current path and then closepath to make
    % symmetrical shapes and such.
    n {
        % sparc is a drop-in replacement for arc that does its own spline
        % calculation, which matters when using cstroke.
        % The built-in arc makes a new spline every 90 degrees.
        0 0 rad 90 dup 360 n div add sparc
    } circrepeat
    closepath
    x neg y neg translate
} def
/tcircle { 3 ncircle } def
/hcircle { 6 ncircle } def
%
% cstroke is a changeable alias to brushystroke, defined in lines.ps.
% brushystroke is thick along the path where a new spline or line
% starts or ends.
% I'm defining hstroke here as a tiny replacement for cstroke to set
% a hue based on an angle to make it easier to see what each section does.
/hstroke {
    360 div 1 0.7 sethsbcolor cstroke 0 setgray
} def
/HexaSomething {
    gsave
        % I like using powers of 2 for line thickness and 0.03125 is a pain.
        32 recip setlinewidth
0 0 0.5 tcircle 0 hstroke
0 0 1 tcircle 30 hstroke
% Using circrepeat provides automatic triangular rotational symmetry. 3 { gsave
0 -1 translate 0 0 1 hcircle 60 hstroke
% hmirror - run the block with and without a horizontal flip. % hmirror _does_ act inside a gsave block. % there is also a vmirror defined. { 0.5 -0.5 goto 0.5 -1.25 goto 90 hstroke } hmirror
grestore } circrepeat
% I actually intended to make this a rounded hexagon but got % the rotation direction wrong (-3 {foo} circrepeat would have worked) % and I liked this accident better. 3 { 0 -1 1.5 -60 -120 arcn } circrepeat closepath 120 hstroke
3 {
0 1 1.5 60 120 arc 0 1 goto closepath 150 hstroke
0 2 0.5 tcircle 180 hstroke
} circrepeat
6 { 0 2 goto } circrepeat closepath 210 hstroke
% % dot is just a filled circle that's 3 times as thick as the current % line width, which I've found to harmonize well.
6 { 2.250 0 dot } circrepeat
6 { 0 2.5 goto 0 2.75 goto 240 hstroke } circrepeat
0 0 2.75 hcircle 270 hstroke
0 0 3 hcircle 300 hstroke
grestore } def %%EndProlog % I've defined "softscale" to scale by the given number in both dimensions, % and to divide the current line width by the same amount. % I usually work at one unit per inch, and start in the center of the page. 72 softscale 4.25 5.5 translate % for the printed version I want this to fill up more of the page. 1.25 softscale HexaSomething showpage

hexasomething.ps
hexasomething.pdf


This page and these graphics by Denis Moskowitz. Last modified Tuesday December 6, 2022.


More postscript stuff