postscript编程带对角线的正多边形

时间:2013-12-09 16:55:19

标签: polygon postscript

首先,我想告诉你,我的时间非常有限。 所以我会用这项任务来帮助你。

我必须在每个对角线上画一个正多边形。

(附件:http://s30.postimg.org/5m6cvd7u9/polygon_with_all_diagonal.png

有人可以帮我这个吗?

编辑:

请检查scource代码:

300 200 translate
/S 28 def
S S scale
4 S div setlinewidth
1 setlinecap
1 setlinejoin

/n 5 def
/r 5 def

newpath
r 0 moveto
1 1 n 1 sub
{
    /i exch def
    360 n div i mul cos r mul 
    360 n div i mul sin r mul lineto
} for
closepath
stroke

这就是我所能做的一切,我不知道如何绘制对角线。

4 个答案:

答案 0 :(得分:3)

从我的其他图形绘制例程中剪切和粘贴我得到类似的东西(有一些冗余代码,但这是因为人们可能想要自己创建邻接列表):

% routines

/ngon{ [ exch 360 exch div 
       0 exch 359.9 { 
       [ exch dup cos 40 mul exch sin 40 mul ]
       } for 
     ]
    } def

/fmtrx {[ 0 1 4 3 roll 1 sub  { [ 1 1 4 3 roll {pop 1} for ] } for ]} def


/drawnodelist { % nodes drawnodelist
  { 
    newpath aload pop 2.5 0 360 arc closepath fill 
  } forall 
} def

/drawedges { % adjacency_matrix nodes drawedges
  /drawnodes exch def
  dup
  /drawlist exch def
  /row 0 def
  { 
    /col 0 def
    {
        pop
        drawlist row get col get 1 eq 
        {
            newpath
            drawnodes row get aload pop moveto
            drawnodes col get aload pop lineto stroke
        } if
        /col col 1 add def
    } forall 
    /row row 1 add def
  } forall 
} def

/drawngon {
    dup /polygon exch ngon def
    polygon drawnodelist % remove this line if you do not want dots
    fmtrx polygon drawedges
} def

% call routines

90 rotate
6 drawngon

以下是生成的不同连接多边形的示例:

enter image description here

答案 1 :(得分:3)

这是我的看法:

/n 7 def            % number of sides
/R 100 def          % radius of circumscribed circle

R 2 mul dup translate

/A 360 n div def

% point given index
/P {
    A mul dup
    cos R mul
    exch
    sin R mul
} bind def

0 1 n 1 sub {
    dup P 3 2 roll
    1 add 1 n 1 sub {
        P moveto 2 copy lineto stroke
    } for
    pop pop
} for
showpage

答案 2 :(得分:1)

可以说,问题的一个更恰当的描述是你试图绘制一个完全连接的图

[Postpedia上的[维基百科条目] [http://en.wikipedia.org/wiki/PostScript#Units_of_length]揭示了一个可用于解决问题的简单程序:

For example, in order to draw a vertical line of 4 cm length, it is
sufficient to type:

0 0 moveto
0 113.385827 lineto stroke

观察上述样本可以很容易地适应任何线条;也就是说,它不一定必须是垂直线。现在,对于多边形的每个顶点,将一条线绘制到每个其他顶点。


知道 n - 多边形顶点的极坐标将是( rad ,i(2π/ n )) i = 0 .. n -1,您可以生成postscript代码来描述来自其他语言的多边形路径,例如C。

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void emitpoly (double x, double y, int n, double r, int up) {
    int i;
    double a;
    printf("%f %f moveto\n", x+r*cos(up?M_PI/2.0:0.0), y+r*sin(up?M_PI/2.0:0.0));
    for(i=1; i<n; i++){
        a=(double)i*(2*M_PI)/n;
        if (up) a += M_PI/2.0;
        printf("%f %f lineto\n", x+r*cos(a), y+r*sin(a));
    }
    printf("stroke\n");
}

void emitpolyweb (double x, double y, int n, double r, int up) {
    int i,j;
    double a,b;
    for(i=0; i<n; i++){
        a=(double)i*(2*M_PI)/n;
        if (up) a += M_PI/2.0;
        printf("%f %f moveto\n", x+r*cos(a), y+r*sin(a));
        for(j=0; j<n; j++){
            b=(double)j*(2*M_PI)/n;
            if (up) b += M_PI/2.0;
            printf("%f %f lineto\n", x+r*cos(b), y+r*sin(b));
            printf("closepath\n");
        }
    }
    printf("stroke\n");
}

int main(int argc, char**argv) {
    int up = 0, n = 3;
    double x = 0.0, y = 0.0, r = 1.0;
    if (argc>1) x = strtod(argv[1],NULL);    // set x from 1st arg, if present
    if (argc>2) y = strtod(argv[2],NULL);    // set y from 2nd arg, if present
    if (argc>3) n = strtol(argv[3],NULL,10); // set n from 3rd arg, if present
    if (argc>4) r = strtod(argv[4],NULL);    // set r from 4th arg, if present
    if (argc>5) up = strcmp(argv[5],"up") == 0;  // rotate 90-degrees if 5th arg is "up"

    //emitpoly(x,y,n,r,up);
    emitpolyweb(x,y,n,r,up);
    printf("showpage\n");
    return 0;
}

答案 3 :(得分:1)

我在使用venn diagrams时进一步在geodesic flowers中获得了一些结果。

此代码将多边形实现为控制结构,该结构采用半径和重复计数(多边形点数)并在每个点调用用户定义的过程 (通过缩放和旋转CTM) )。所以它是一个循环,使得用户点(1,0)映射到每次迭代的多边形的连续点。使用此功能,图形本身非常简单。作为控制结构,它不仅限于绘制多边形,还可以用于在较小的多边形顶点定位较小的图形,甚至可以生成顶点的数组。

另请注意,此代码不必调用sincos,因为这是通过旋转坐标系来处理的。这里的主要技巧是使用扫描仪生成优化的循环体(过程数组)。

init incr max控件值放在for循环的堆栈上后,它会执行({...}) token pop exch pop bind end exec,它会动态创建一个过程并执行对for的调用。 token在字符串上调用(成功)将在堆栈上产生多个值:空字符串,扫描令牌本身(相应类型的ps对象)和布尔true。所以pop exch pop只修剪布尔值和空字符串。 bind然后用运算符本身替换运算符名称,因此我们在循环期间执行更少的哈希查找。然后endexec过程之前删除我们的临时字典。

这是有效的,因为所有变量都被token运算符直接替换,因为它们被写为//immediate-names,当token执行此操作时,临时字典在dict堆栈上可用。删除dict使得它成为一个真正的控制结构,不会干扰user-proc使用的任何名称的含义,即使它使用spm之类的名称

生成的过程正文{{//s setmatrix rotate //p exec} for //m setmatrix}具有用户proc嵌入//p和两个矩阵,//srad参数和//m预先缩放的矩阵一个矩阵在最后恢复。 for循环体{//s setmatrix rotate //p exec}接收角度参数作为循环控件的一部分。它将CTM重置为我们的缩放,定向矩阵//s setmatrix,然后按参数角rotate旋转,然后执行user-proc //p exec

%rad n {proc}  atpoly  -
%call proc having rotated+scaled
%so (1,0) is each vertex of rad-radius n-polygon
/atpoly {
    4 dict begin /p exch def /n exch def % rad 
    /m matrix currentmatrix def 
    dup scale
    /s matrix currentmatrix def 
    0 360 n div 359.9 %0 dAng maxAng %{}for
    ({
        {
            //s setmatrix
            rotate
            //p exec
        } for 
        //m setmatrix
    }) token pop exch pop %instantiate code template
    bind
    end exec % run loop without dictionary
} bind def 

300 400 translate
/rad 100 def 
/n 9 def 

rad n { 
    1 0 moveto
    1 n { 
        1 0 lineto
        closepath
    } atpoly
} atpoly
stroke

要使用atpoly,我们必须转换为所需的中心点。然后伪代码是:

for each point in poly
    moveto point
    for each point in poly
        lineto point
        line back to last moveto point (closepath)
stroke

至少有两种方法可以用atpoly绘制多边形。您可以在开头添加冗余moveto并在过程中使用lineto,也可以使用第一次执行moveto的过程并重新定义自己以执行lineto其后。这是脚本部分的一个变体,它显示了两种方式,以及互连的poly。

/rad 100 def 
/n 9 def 

gsave
    400 200 translate
    rad n { 
        1 0 moveto
        1 n { 
            1 0 lineto
            closepath
        } atpoly
    } atpoly
    stroke
grestore

gsave
    200 200 translate
    rad 0 moveto
    rad n { 
        1 0 lineto
    } atpoly
    closepath stroke
grestore

gsave
    200 400 translate
    /action { moveto /action { lineto } def } def 
    rad n { 
        1 0 action
    } atpoly
    closepath stroke
grestore

输出:
enneagons

我认为这些块可以作为程序包装。这些仍然需要上面的atpoly功能。

/drawpoly { % rad n x y
    gsave
        translate 
        1 index 0 moveto
        {
            1 0 lineto
        } atpoly
        closepath stroke
    grestore
} def

% rad and n are needed in the outer call to atpoly,
% then n is needed for each iteration.
% To avoid adding a dictionary, duplicate n n-times.
% Once for each iteration.
/drawpolyweb { % rad n x y
    gsave
        translate      % rad n
        dup            % rad n n
        { dup } repeat % rad n^(n+1)
        1 add          % rad n^n n+1
        -1 roll        % n^n rad
        %pstack() =
        1 index        % n^n rad n
        {
            1 0 moveto  % n^(n-i)
            1 exch      % n^(n-i-1)  1 n
            {
                1 0 lineto
                closepath
            } atpoly
        } atpoly
        stroke
    grestore
} def

然后使用变得更简单:

%rad n  x   y
 100 9 300 200 drawpoly

 100 9 300 500 drawpolyweb