首先,我想告诉你,我的时间非常有限。 所以我会用这项任务来帮助你。
我必须在每个对角线上画一个正多边形。
(附件: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
这就是我所能做的一切,我不知道如何绘制对角线。
答案 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
以下是生成的不同连接多边形的示例:
答案 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)映射到每次迭代的多边形的连续点。使用此功能,图形本身非常简单。作为控制结构,它不仅限于绘制多边形,还可以用于在较小的多边形顶点定位较小的图形,甚至可以生成顶点的数组。
另请注意,此代码不必调用sin
或cos
,因为这是通过旋转坐标系来处理的。这里的主要技巧是使用扫描仪生成优化的循环体(过程数组)。
将init incr max
控件值放在for
循环的堆栈上后,它会执行({...}) token pop exch pop bind end exec
,它会动态创建一个过程并执行对for
的调用。 token
在字符串上调用(成功)将在堆栈上产生多个值:空字符串,扫描令牌本身(相应类型的ps对象)和布尔true
。所以pop exch pop
只修剪布尔值和空字符串。 bind
然后用运算符本身替换运算符名称,因此我们在循环期间执行更少的哈希查找。然后end
在exec
过程之前删除我们的临时字典。
这是有效的,因为所有变量都被token
运算符直接替换,因为它们被写为//immediate-names
,当token
执行此操作时,临时字典在dict堆栈上可用。删除dict使得它成为一个真正的控制结构,不会干扰user-proc使用的任何名称的含义,即使它使用s
,p
和m
之类的名称
生成的过程正文{{//s setmatrix rotate //p exec} for //m setmatrix}
具有用户proc嵌入//p
和两个矩阵,//s
由rad
参数和//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
输出:
我认为这些块可以作为程序包装。这些仍然需要上面的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