Search code examples
pdfchartsgoogle-visualizationdata-visualizationpostscript

How can I programatically generate venn diagram images with labels on top of the image?


I'm trying to generate Venn diagrams for a pdf report, with text on top of the distinct regions.

We're using htmldoc to generate pdfs, which precludes text on top of background images.

We use the google charts api for other images, but their Venn diagrams don't support text on top of the diagram (from what I can tell).

The easiest path would be some way to generate an image of the venn on our server using a 3rd party library, and then link the image into the document, I just don't know any software packages that would support our use case.

Any links/pointers would be appreciated.


Solution

  • Here's some example code. This seems like a decent tutorial:

    http://paulbourke.net/dataformats/postscript/

    If you're on Linux, you can use the gv command to view it. There are various utilities to convert it to PDF too; ps2pdf on Linux, and I think Acrobat Distiller on Windows.

    %!PS-Adobe-3.0 EPSF-3.0
    %%BoundingBox: 0 0 144 144
    
    % CenterText - paint text centered on x with baseline on y
    % x y s CenterText
    /CenterText
    {
       << >> begin
       /s exch def /y exch def /x exch def
       newpath x s stringwidth pop 2 div sub y moveto s show
       end
    } bind def
    
    2 setlinewidth
    54 72 36 0 360 arc stroke
    90 72 36 0 360 arc stroke
    
    /Helvetica 10 selectfont
    36 72 (A) CenterText
    108 72 (B) CenterText
    72 72 (A^B) CenterText
    

    Here's the three-circle one. It works but I don't vouch for the quality of the coding, I haven't done any serious PS code in years.

    %!PS-Adobe-3.0 EPSF-3.0
    %%BoundingBox: 0 0 216 216
    
    % CenterText - paint text centered on x with baseline on y
    % x y s CenterText
    /CenterText
    {
       << >> begin
       /s exch def /y exch def /x exch def
       newpath x s stringwidth pop 2 div sub y moveto s show
       end
    } bind def
    
    % Set center of bounding box at 0,0 and rotate 90 degrees cw
    108 108 translate
    gsave
    180 rotate
    
    % Draw 3 circles at 120-degree intervals
    /ct 3 def
    /offset 36 def
    /radius 60 def
    0 1 ct 1 sub   % for
    {
        gsave
        360 mul ct div rotate
        0 offset translate
        0 0 radius 0 360 arc stroke
        grestore
    } for
    
    grestore
    
    /Helvetica 10 selectfont
    -54 36 (A) CenterText
    54 36 (B) CenterText
    0 -72 (C) CenterText
    
    0 36 (A^B) CenterText
    -36 -24 (A^C) CenterText
    36 -24 (B^C) CenterText
    
    0 -6 (A^B^C) CenterText