Pdf 如何以编程方式生成维恩图图像,并在图像顶部添加标签?

Pdf 如何以编程方式生成维恩图图像,并在图像顶部添加标签?,pdf,charts,google-visualization,data-visualization,postscript,Pdf,Charts,Google Visualization,Data Visualization,Postscript,我试图为pdf报告生成维恩图,文本位于不同区域的顶部 我们正在使用htmldoc生成PDF,它排除了背景图像顶部的文本 我们对其他图像使用谷歌图表api,但他们的维恩图表不支持图表顶部的文本(据我所知) 最简单的方法是使用第三方库在我们的服务器上生成venn的映像,然后将映像链接到文档中,我只是不知道有任何软件包支持我们的用例 任何链接/指针都将不胜感激。以下是一些示例代码。这似乎是一个不错的教程: 如果您在Linux上,可以使用gv命令查看它。还有各种各样的实用程序可以将其转换为PDF格式;

我试图为pdf报告生成维恩图,文本位于不同区域的顶部

我们正在使用htmldoc生成PDF,它排除了背景图像顶部的文本

我们对其他图像使用谷歌图表api,但他们的维恩图表不支持图表顶部的文本(据我所知)

最简单的方法是使用第三方库在我们的服务器上生成venn的映像,然后将映像链接到文档中,我只是不知道有任何软件包支持我们的用例


任何链接/指针都将不胜感激。

以下是一些示例代码。这似乎是一个不错的教程:

如果您在Linux上,可以使用
gv
命令查看它。还有各种各样的实用程序可以将其转换为PDF格式;Linux上的ps2pdf,我认为Windows上的Acrobat蒸馏器

%!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
%!PS-Adobe-3.0 EPSF-3.0
%%边界框:0 0 144 144
%CenterText-绘制以x为中心且基线位于y的文本
%x y s中心文本
/中心文本
{
>开始
/s exch def/y exch def/x exch def
新路径x s stringwidth pop 2 div sub y移动到显示
结束
}绑定def
2设置线宽
54 72 36 0 360弧冲程
90 72 36 0 360弧冲程
/Helvetica 10选择字体
36 72(A)中心文本
108 72(B)中心文本
72(A^B)中心文本
这是三圈一号。它可以工作,但我不能保证编码的质量,我已经多年没有做过任何严肃的PS代码了

%!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
%!PS-Adobe-3.0 EPSF-3.0
%%边界框:0 0 216 216
%CenterText-绘制以x为中心且基线位于y的文本
%x y s中心文本
/中心文本
{
>开始
/s exch def/y exch def/x exch def
新路径x s stringwidth pop 2 div sub y移动到显示
结束
}绑定def
%将边界框的中心设置为0,0,并顺时针旋转90度
108翻译
gsave
180转
%以120度的间隔画3个圆
/ct 3 def
/偏移量36 def
/半径60 def
0 1 ct 1次%
{
gsave
360多个ct分区旋转
0偏移平移
0 0半径0 360圆弧笔划
格雷斯托
}为了
格雷斯托
/Helvetica 10选择字体
-54 36(A)中心文本
54 36(B)中心文本
0-72(C)中心文本
0 36(A^B)中心文本
-36-24(A^C)中心文本
36-24(B^C)中心文本
0-6(A^B^C)中心文本

这是一张图中的两个电池的示意图。我发现省略号比圆圈更容易把文字压缩成圆圈

.PS
ellipse
"A" at 1st ellipse - (.2, 0)
ellipse with .w at 1st ellipse.e - (.4, 0)
"B" at 2nd ellipse + (.2, 0)
"A^B" at 1st ellipse.e - (.2, 0)
.PE
和一个三单元图:

.PS
ellipsewid = 1
ellipseht = .75
ellipse
ellipse at 1st ellipse + (.5, 0)
ellipse at 1st ellipse + (.25, .35)
"A" at 1st ellipse - (.2, .1)
"B" at 2nd ellipse + (.2, -.1)
"C" at 3rd ellipse + (0, .1)
"A^B" at 3rd ellipse - (0, .5)
"A^C" at 3rd ellipse - (.3, .1)
"B^C" at 3rd ellipse + (.3, -.1)
"A^B^C" at 3rd ellipse - (0, .25)
.PE
转换为ps:
groff-p ven.pic>ven.ps

我还没有找到一个制作.eps的好方法。敬请期待!编辑:
sudo apt get install ps2eps

编辑:

在一个中央不可见的盒子上,相对于指南针点构造所有东西要容易得多

两个单元:

.PS
box invis "A^B"
ellipse wid 1st box.wid*1.5 at 1st box.w + (.1, 0)
ellipse wid 1st box.wid*1.5 at 1st box.e - (.1, 0)
"A  " at 2nd ellipse.w rjust
"  B" at 1st ellipse.e ljust
.PE
三个单元:

.PS
box invis "A^B^C" below wid .5 ht .3
ellipse at 1st box.sw
ellipse at 1st box.se
ellipse at 1st box.n
"A  " at 2st ellipse.w rjust below
"  B" at 1nd ellipse.e ljust below
"C" "" "" at 3rd ellipse above
"A^B" at 3rd ellipse.s below
"A^C   " at 2nd ellipse.nw rjust
"   B^C" at 1nd ellipse.ne ljust
.PE
不过,仍然需要调整。但数量要少得多!长方体的宽度和高度定义用于放置椭圆中心的等腰三角形

编辑:

最后一个想法提出了一种制作四单元图的方法。我不得不缩小楔形字体

.PS
box invis "A^B^C^D" wid .65 ht .5
ellipsewid = 2
ellipseht = 1.25
ellipse at 1st box.ne
ellipse at 1st box.se
ellipse at 1st box.sw
ellipse at 1st box.nw
"A" at 1st box.ne + (.4,  .4)
"B" at 1st box.se + (.4, -.4)
"C" at 1st box.sw - (.4,  .4)
"D" at 1st box.nw - (.4, -.4)
"A^B" at 1st box.e + (.4, 0) ljust
"B^C" at 1st box.s - (0, .2) below
"C^D" at 1st box.w - (.4, 0) rjust
"A^D" at 1st box.n + (0, .2) above
"\s-1A^B^D\s+1" at 1st box.ne + (.15,  .03)
"\s-1A^B^C\s+1" at 1st box.se + (.15, -.03)
"\s-1B^C^D\s+1" at 1st box.sw - (.15,  .03)
"\s-1A^C^D\s+1" at 1st box.nw - (.15, -.03)
.PE
下面是输出的jpg。当我切到盒子时,我可能会失去一些决心


对于pic来说,尽可能实用,postscript确实是这方面的自然选择

好的,我还没有解决标签问题,但这是一个广义图。事实上,您只需将中心放置在该n的正多边形的顶点上

但其中一些空间变得非常小。所以我在想一些带标签的弧线,螺旋形的。也许标签的半径应该反映指定分区的深度

编辑:我重新设计了代码,因此在修订版1中有一个相当不错的15个图表页面

编辑:我刚刚接受维基百科的教育。事实证明,我所说的四单元维恩图实际上根本不是维恩图

这是一张欧拉图。问题是,没有任何地方可以单独从图的对边获得两个区域的交点。不管你怎么做,真正的4单元图都会变得很奇怪。因此,答案的范围比我在上两次编辑中所追求的要小

对于2圆图,我能找到的最佳位置是通过图中心到圆心到边的半径的交点来定义的,定义圆放置在圆心上。

对于三圆图,我能找到的最佳位置是由半径(和旋转半径)与旋转三角形近似的交点分别定义为圆和未旋转三角形。

代码的一个版本可以在本答案的上一版本中找到。我在线程中向usenet发布了一个扩展版本。但是,由于这个答案有点过火(而且实际上还没有画出任何标签或返回它们的位置),而真正的广义维恩图则有点过火,所以在将这个问题置于任何更长的代码块之前,我需要整理一下大部分的包袱

编辑:我想我已经把这个差不多搞定了。该程序仅包含前一程序中在“理想”标签位置生成带小圆的2-和3-维恩图所需的部分。对于2单元图,解决方案非常简单(定义半径的两倍)。对于三单元图,解决方案是cos(60)*圆半径+定义半径,或者先乘,或者先加

编辑:最后,编辑标签。由于我使用矩阵旋转来寻找点,所以需要在最后一分钟进行一些技巧。这意味着当我试着打印标签时,它们的方向都很奇怪。所以“中心秀”程序比通常的要多一些。它必须在离开translate时重置当前变换矩阵的缩放部分
%!

%cp:xy  rad  circ  -
/circ {
    currentpoint newpath
        2 copy 5 -1 roll 0 360 arc stroke
    moveto
} def

%rad n  poly  [pointlist]
/poly {
    1 dict begin exch /prad exch def
    [ exch
        0 exch 360 exch div 359.9 {
            [ exch
                dup cos prad mul exch
                sin prad mul
            ]
        } for
    ]
    end
} def

%[list] rad  subcirc  -
/subcirc {
    1 dict begin /crad exch def gsave
        currentpoint translate
        { aload pop moveto crad circ } forall
    grestore end
} def

%[list]  locate  -
%draw little circles around each point
/locate {
    gsave
        currentpoint translate
        0 0 moveto 5 circ
        { aload pop moveto 5 circ } forall
    grestore
} def

%cp:xy  (string)  cshow  -
/cshow {
    gsave
        currentpoint translate %0 0 moveto
        matrix currentmatrix
        dup 0 normal 0 4 getinterval %reset rotation, keep translation
        putinterval setmatrix
        dup true charpath flattenpath pathbbox
        3 -1 roll sub 3 1 roll sub
        2 div exch -2 div moveto show
    grestore
} def

%[list] [labels]  label  -
%print label text centered on each point
/label {
    gsave
        currentpoint translate
        0 1 3 index length 1 sub {
            2 index 1 index get aload pop moveto
            2 copy get cshow pop
        } for
        pop pop
    grestore
} def

%[x0 y0] [x1 y1]  pyth-dist  radius
/pyth-dist {
    aload pop 3 -1 roll aload pop % x1 y1 x0 y0
    exch % x1 y1 y0 x0
    3 1 roll sub dup mul % x1 x0 dy^2
    3 1 roll sub dup mul % dy^2 dx^2
    add sqrt
} def

/rotw { 180 n div rotate } def

%cp:xy rad n  venn  -
%make the circles intersect the opposite point of def poly
/venn {
    3 dict begin /n exch def /vrad exch def
        vrad n poly
        dup 0 get exch
        dup length 2 idiv get
        pyth-dist /crad exch def
        %vrad crad n ven
        vrad n poly crad subcirc  %the Venn circles
        [[0 0]] [(All)] label
        n 2 eq {
            %vrad 2 mul n poly locate
            vrad 2 mul n poly
            [(A) (B)] label
        }{
            n 3 eq {
                %vrad crad 60 cos mul add n poly locate
                vrad crad 60 cos mul add n poly
                [ (A) (B) (C) ] label
                %gsave rotw vrad crad add 60 cos mul n poly locate grestore
                gsave rotw vrad crad add 60 cos mul n poly
                [ (A^B) (B^C) (A^C) ] label
                grestore
            } if
        } ifelse
    end
} def

/normal matrix currentmatrix def
/in{72 mul}def
/Palatino-Roman 20 selectfont
4.25 in 8.25 in moveto
1 in 2 venn
4.25 in 3.5 in moveto
1 in 3 venn
showpage