鲁洛三角形是一种宽度恒定的形状,有点像圆角等边三角形。
它可以像三集维恩图一样由三个圆圈相交形成。
(鲁洛三角形 -- 来自 Wolfram MathWorld)
使用 TikZ、Asymptote 或某些可嵌入到 LaTeX 中的语言绘制鲁洛三角形的最佳方法是什么?也许通过绘制维恩图的三个圆圈并切掉其余部分?
答案1
prologues := 3;
outputtemplate := "%j%c.eps";
vardef reuleaux(expr n) =
for t=0 step 360/n until 359:
1/2 up rotated t { left rotated (t+90/n) } .. { left rotated (t+270/n)}
endfor cycle enddef;
beginfig(1);
for i := 3 step 2 until 9:
draw reuleaux(i) scaled 40i withcolor .6 red withpen pencircle scaled 1;
draw fullcircle scaled 40i withcolor .6 white;
endfor
endfig;
end.
根据需要缩放、旋转、移动。其大小应适合缩放fullcircle
到相同量。
每个角都是point
路径的 ,因此如果要连接顶点,请连接 点0, 1, ..., n-1
;如果想要每个圆弧的中点,请使用 点1/2, 3/2, ..., n-1/2
,如下所示:
beginfig(2);
path t[];
for n := 3 upto 7:
t[n] = reuleaux(n) scaled 60 shifted (75n,0);
fill t[n] withcolor red+0.75green+0.2blue;
draw for i = 0 upto n-1: point i of t[n] -- endfor cycle withcolor .6 red;
draw for i = 0 upto n-1: point i+1/2 of t[n] -- endfor cycle withcolor .6 blue;
endfor
endfig;
显然,您也可以挑选出要标记的点。
beginfig(3);
path t; t = reuleaux(3) scaled 90;
draw t withcolor .6 red;
dotlabel.top (btex $A$ etex, point 0 of t);
dotlabel.llft(btex $B$ etex, point 1 of t);
dotlabel.lrt (btex $C$ etex, point 2 of t);
endfig;
解释
我对这个问题进行了几次修改,因为我对这个问题进行了更多的思考。使用了原始版本buildcycle
和预定义的圆形路径,但它们并不是真正需要的。这里的最终版本是我所能做到的简单而正确的。
函数reuleaux(n)
返回path
一个n顶点由圆弧连接,圆弧的半径是相应正多边形最长对角线的长度。
要理解它的作用,首先考虑以下函数,该函数返回正多边形的路径,其中n顶点:
vardef polygon(expr n) =
for t=0 step 360/n until 359:
up rotated t --
endfor cycle enddef;
up
扩展为(0,1)
,因此n=3 该函数扩展为
(0,1) -- (-0.866,-0.5) -- (0.866,-0.5) -- cycle
就像一个三边形的正多边形适合一个单位半径的圆一样。然而在 Metapost 中,预定义的fullcircle
路径有单位直径为了保持一致性,最好将多边形缩小 1/2,
vardef polygon(expr n) =
for t=0 step 360/n until 359:
1/2 up rotated t --
endfor cycle enddef;
MP 中的优先规则意味着1/2 up
扩展为(0,0.5)
我们想要的。
现在我们有一个正多边形,可以容纳fullcircle
,为了使它变成鲁洛多边形,我们必须将直线弯曲成以对顶点为中心的圆弧(或当n是偶数)。我们可以使用路径方向符号来实现这一点,并改为--
允许..
路径弯曲。
vardef reuleaux(expr n) =
for t=0 step 360/n until 359:
1/2 up rotated t { left rotated (t+90/n) } .. { left rotated (t+270/n)}
endfor cycle enddef;
因为left
是up rotated 90
,所需的方向由所示的公式给出,你可以利用一些基本的几何知识来推导出来:
如果你想让自己相信所得到的圆弧确实是圆形的,并且有正确的圆心,那么在上面画一个适当缩放和移动的圆。这种圆的半径将是多边形上最长对角线的长度——交流如上图所示 - 您可以使用length (point (n+1)/2 of r - point 0 of r)
where找到它r=reuleaux(n)
。
应用
鲁洛三角形具有一些传统的几何图案,例如:
我们可以像这样绘制:(如果有更好的平铺方法,请评论!)
beginfig(6);
path t, ring; s := 10;
t = reuleaux(3) scaled s;
ring = for i=0 upto 5: subpath(-1,1) of t shifted (0,s) rotated (i*60) .. endfor cycle;
pair offset;
for i=0 upto 5:
dx := 0;
for j=0 upto 13:
offset := (3*s,0) rotated (30*(j mod 2*2-1));
dx := dx + xpart offset;
dy := 3*i*s + 1/2 ypart offset;
draw ring shifted (dx,dy) withcolor (.5,.7,.9);
endfor
endfor
endfig;
这可能成为其他探索的基础。例如,只需改变的定义t
即可t = reuleaux(2) scaled s
产生这种相当奇妙的模式。
变化
如果您想要一个指向右而不是指向上的雷洛多边形,那么您只需将定义中的up
和替换为和。left
right
up
vardef reuleaux(expr n) =
for t=0 step 360/n until 359:
1/2 right rotated t { up rotated (t+90/n) } .. { up rotated (t+270/n)}
endfor cycle enddef;
beginfig(7);
for n=3 upto 7:
draw fullcircle scaled 60 shifted (75n,0) withcolor .8 white;
draw reuleaux(n) scaled 60 shifted (75n,0) withcolor .67 red;
endfor
endfig;
这与普通 MP 稍微一致,因为这些形状的 0 点对应于零度旋转。它们看起来像这样:
我们还可以交换定义中的两个方向来生成所谓的反鲁洛多边形。
vardef antireuleaux(expr n) =
for t=0 step 360/n until 359:
1/2 right rotated t { up rotated (t+270/n) } .. { up rotated (t+90/n)}
endfor cycle enddef;
正如你在下面看到的,这些反形状与以下形状相似,但又略有不同:内摆线曲線。
vardef hypocycloid(expr k) =
for t=0 step 1 until 360:
point 0 of (fullcircle scaled (1/k) rotated (-t*k)
shifted (1/2 right scaled (1-1/k))) rotated t --
endfor cycle
enddef;
还可以将 Reuleaux 多边形的角弄圆,同时仍保留恒定宽度属性。这是一个生成圆形的函数,它采用了略微更通用的方法。第一个参数是边数,第二个参数是圆角半径占宽度的比例。
vardef polygon(expr n) =
for t=0 step 360/n until 359:
1/2 right rotated t --
endfor cycle
enddef;
vardef rounded_reuleaux(expr n, s) =
save m, a, b, p; m := (n+1)/2;
pair a,b; path p; p := polygon(n);
for i = 0 upto n-1:
hide(
a := point i of p - point i+m of p;
b := point i+1 of p - point i+m of p;
)
point i of p + s*unitvector(a) { up rotated angle a } ..
point i+1 of p + s*unitvector(b) { up rotated angle b } ..
endfor cycle
enddef;
beginfig(8);
for n := 3 upto 7:
fill rounded_reuleaux(n,1/6) scaled 60 shifted (85n,0) withcolor (1/2,3/4,5/6);
draw reuleaux(n) scaled 60 shifted (85n,0);
endfor
答案2
另一个 TikZ 解决方案,但这次,TikZ 完成了所有工作。您只需提供两个坐标(等边三角形的两个顶点),另一个顶点和半径就会自动计算。例如,下面的图像是使用
\Reuleaux{0,0}{2,0}
\Reuleaux[Dandelion]{0,0}{3,-2}
代码:
\documentclass[dvipsnames]{article}
\usepackage{tikz}
\usetikzlibrary{intersections,positioning,calc}
\newcommand\Reuleaux[3][Aquamarine]{%
\def\A{#2}
\def\B{#3}
\begin{tikzpicture}
\begin{scope}
\clip[name path global=c1] (\A)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\clip[name path global=c2] (\B)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\clip[name path global=c3] ($ (\A) ! .5 ! (\B) ! {sin(60)*2} ! 90:(\B) $)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\fill[#1] (current bounding box.north west) rectangle (current bounding box.south east);
\end{scope}
\draw (\A)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\draw (\B)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\draw ($ (\A) ! .5 ! (\B) ! {sin(60)*2} ! 90:(\B) $)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\fill [name intersections={of=c1 and c2,by={a,b}}]
(a) circle (2pt) node[label=above:$A$] {};
\fill [name intersections={of=c2 and c3,by={c,d}}]
(d) circle (2pt) node[label=left:$B$] {};
\fill [name intersections={of=c3 and c1,by={e,f}}]
(f) circle (2pt) node[label=right:$C$] {};
\draw (a) -- (d) -- (f) -- cycle;
\end{tikzpicture}%
}
\begin{document}
\Reuleaux{0,0}{2,0}
\Reuleaux[Dandelion]{0,0}{3,-2}
\end{document}
如果仅要生成三角形,则可以从上述代码中抑制 \draw 命令:
\documentclass[dvipsnames]{article}
\usepackage{tikz}
\usetikzlibrary{intersections,positioning,calc}
\newcommand\Reuleaux[3][Aquamarine]{%
\def\A{#2}
\def\B{#3}
\begin{tikzpicture}
\begin{scope}
\clip[name path global=c1] (\A)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\clip[name path global=c2] (\B)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\clip[name path global=c3] ($ (\A) ! .5 ! (\B) ! {sin(60)*2} ! 90:(\B) $)
let
\p1 = ($ (\B) - (\A) $)
in
circle ({veclen(\x1,\y1)});
\fill[#1] (current bounding box.north west) rectangle (current bounding box.south east);
\end{scope}
\fill [name intersections={of=c1 and c2,by={a,b}}]
(a) circle (2pt) node[label=above:$A$] {};
\fill [name intersections={of=c2 and c3,by={c,d}}]
(d) circle (2pt) node[label=left:$B$] {};
\fill [name intersections={of=c3 and c1,by={e,f}}]
(f) circle (2pt) node[label=right:$C$] {};
\draw (a) -- (d) -- (f) -- cycle;
\end{tikzpicture}%
}
\begin{document}
\Reuleaux{0,0}{2,0}
\Reuleaux[Dandelion]{0,0}{3,-2}
\Reuleaux[Maroon]{-2,-2}{0,0}
\end{document}
答案3
使用 tkz-euclide
\documentclass{scrartcl}
\usepackage{tkz-euclide}
\usetkzobj{all}
\begin{document}
\begin{tikzpicture}
\tkzDefPoint(0,0){A}
\tkzDefPoint(5,0){B}
\tkzDefEquilateral(A,B)\tkzGetPoint{C}
\tkzDrawPolygon[red](A,B,C)
\tkzDrawArc[fill=gray!20](A,B)(C)
\tkzDrawArc[fill=gray!20](B,C)(A)
\tkzDrawArc[fill=gray!20](C,A)(B)
\end{tikzpicture}
\end{document}
和
\begin{tikzpicture}
\tkzDefPoint(0,0){A}
\tkzDefPoint(5,0){B}
\tkzDefEquilateral(A,B)\tkzGetPoint{C}
\tkzDrawPolygon[red](A,B,C)
\begin{scope}
\tkzSetUpLine[style=dashed,color=gray]
\tkzDrawCircle(B,C)
\tkzDrawCircle(A,B)
\tkzDrawCircle(C,A)
\end{scope}
\tkzDrawArc[fill=gray!20](A,B)(C)
\tkzDrawArc[fill=gray!20](B,C)(A)
\tkzDrawArc[fill=gray!20](C,A)(B)
\end{tikzpicture}
最后
\documentclass{scrartcl}
\usepackage{tkz-euclide}
\usetkzobj{all}
\begin{document}
\begin{tikzpicture}
\tkzDefPoint(0,0){A}
\tkzDefPoint(5,0){B}
\tkzDefEquilateral(A,B)\tkzGetPoint{C}
\tkzFillSector[fill=gray!20](A,B)(C)
\tkzFillSector[fill=gray!20](B,C)(A)
\tkzFillSector[fill=gray!20](C,A)(B)
\end{tikzpicture}
\end{document}
备注:可以使用最后一个代码创建一个宏。
附件:使用 tikz 的最小代码是(基于 Mark Wibrow 的回答)
\documentclass[tikz,border=5]{standalone}
\begin{document}
\tikz\draw[fill=blue!20] (0,0)
\foreach \i in {1,2,3}{ arc (\i*120:\i*120+60:4)} ;
\end{document}
答案4
根据 percusse 的建议,但在 Asymptote 中实现,不需要角度计算。关键是函数,它返回以从到arc(c, a, b)
为中心的圆弧。(如果没有这样的圆弧,则它返回以从到线为中心的圆弧。)c
a
b
c
a
c--b
还请注意使用&
运算符连接具有公共端点的两个路径。
\documentclass[margin=10pt]{standalone}
\usepackage{asymptote}
\begin{document}
\begin{asy}
unitsize(3cm);
path triangle = scale(1/2)*polygon(3);
pair a = point(triangle, 0), b=point(triangle,1), c=point(triangle,2);
path releaux = arc(c=a, b, c) & arc(c=b, c, a) & arc(c=c, a, b) & cycle;
fill(releaux, gray);
draw(releaux);
\end{asy}
\end{document}
结果: