我正在寻找一个可以帮助我表示不同形状的混沌台球的 TikZ 库。
任何想法?
答案1
这是另一个不错的选择渐近线,可以轻松计算路径的交叉点和方向:
这是体育场台球的代码:
\documentclass{standalone}
\usepackage{asymptote}
\begin{document}
\begin{asy}[width=10cm,height=10cm]
import graph;
size(200);
// circle billiard
// path bill = Circle((0,0),90.0);
// real phi = 2*pi*0.23456;
// stadium billiard
path bill = (-50,-50)--(50,-50)--arc((50,0), 50, -90, 90)
--(50,50)--(-50,50)--arc((-50,0), 50, 90, 270)--cycle;
real phi = 2*pi*0.123456;
draw(bill);
pair s = (20,20), db, dt = exp(I*phi), e = s+200*dt;
path traj = s--e;
real [] c;
for(int i=0; i<50; ++i) {
c = intersect(bill, traj);
e = point(traj, c[1]);
db = dir(bill, c[0]);
draw(s--e,red);
dot(e,blue);
dt = -dt + 2*dot(dt,db)*db;
s = e;
e = s + 200*dt;
traj = (s+dt)--e;
}
\end{asy}
\end{document}
要得到圆圈,请取消注释以下行
// path bill = Circle((0,0),90.0);
// real phi = 2*pi*0.23456;
并注释掉台球路径
path bill = (-50,-50)--(50,-50)--arc((50,0), 50, -90, 90)
--(50,50)--(-50,50)--arc((-50,0), 50, 90, 270)--cycle;
real phi = 2*pi*0.123456;
编辑:这个问题太有趣了,我也不得不做西奈台球:
代码只有几行:
\documentclass{standalone}
\usepackage{asymptote}
\begin{document}
\begin{asy}[width=10cm,height=10cm]
import graph;
size(200);
// Sinai billiard
path bill = (-90,-90)--(90,-90)--(90,90)--(-90,90)--cycle;
path inner = reverse(Circle((0,0),30.0));
real phi = 2*pi*0.05;
filldraw(bill^^inner,lightgray,black);
pair s = (30,30), db, dt = exp(I*phi), e = s+200*dt;
path traj = s--e;
real [] co;
real [][] ci;
for(int i=0; i<80; ++i) {
co = intersect(traj, bill);
ci = intersections(traj, inner);
if(ci.length > 0) {
e = point(traj, ci[0][0]);
db = dir(inner, ci[0][1]);
} else {
e = point(traj, co[0]);
db = dir(bill, co[1]);
}
draw(s--e,red);
dot(e,blue);
dt = -dt + 2*dot(dt,db)*db;
s = e;
e = s + 200*dt;
traj = (s+dt)--e;
}
\end{asy}
\end{document}
答案2
为了进行比较,这里是 Alex 的代码到 Metapost 的翻译。
\starttext
\startMPpage[offset=2mm]
u := 1mm;
phi := 0.12345;
path billiard, ball, trajectory;
pair dt, hit, location, awayPoint, tangent;
% stadium billiard
billiard = (-50u,-50u)--( 50u,-50u) {right} .. {left} (50u, 50u)
-- (-50u, 50u)--(-50u, 50u) {left} .. {right} cycle;
ball := fullcircle scaled 3mm;
draw billiard;
location := (20u, 20u);
dt := dir(phi);
for i = 0 upto 50 :
awayPoint := location + 200u*dt ;
trajectory := (location+dt) -- awayPoint;
save timeBilliard, timeBall;
(timeBilliard, timeBall) = billiard intersectiontimes trajectory;
hit := point timeBilliard of billiard;
draw location -- hit withcolor red;
fill ball shifted hit withcolor blue;
tangent := direction timeBilliard of billiard;
% The result of direction has arbitrary magnitude. Normalize it;
tangent := tangent/abs(tangent);
dt := -dt + 2*(dt dotprod tangent)*tangent;
location := hit;
endfor
\stopMPpage
\stoptext
这使:
将反射次数增加到 500 可得到:
并将其增加到 2000 得到:
显示空间填充。
然而,如果从一个圆圈开始,那么 2000 次碰撞将得出:
一个有趣的选项是将反射随机化:在对切线进行归一化后,添加
% Randomize the tangent
tangent := tangent randomized 0.3;
% Renormalize the result
tangent := tangent/abs(tangent);
这使:
通过这种随机化,如果你从一个圆圈开始,你就会得到空间填充(2000 次碰撞后):