以下 tikz 代码:
\begin{tikzpicture}
\coordinate (point) at (0,0);
% draw the arrows.
\foreach \angle in {0,15,...,360}
\draw[->] (point) -- (\angle:2);
% draw floor
\draw (-3.5,-1) -- (3.5,-1);
\end{tikzpicture}
结果如下:
但是,我希望射线在与地板碰撞时停止。我想要这样的东西(请原谅我糟糕的绘画技巧):
我该如何实现这个?
答案1
这个库intersections
很有帮助。如果一支箭穿过地板,则保存在宏中的交叉点数\total
将为 1,否则为 0。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
\coordinate (point) at (0,0);
% Draw floor
\draw[name path=floor] (-3.5,-1) -- (3.5,-1);
% Draw the arrows
\foreach \angle in {0,15,...,360} {
% Name the path for an arrow with full length
\path[name path=ray] (point) -- (\angle:2);
% Draw the arrow depending on an intersection point
% with the floor.
\draw[
->,
name intersections={
of=ray and floor,
total=\total
},
]
\ifnum\total>0
(point) -- (intersection-1)
\else
(point) -- (\angle:2)
\fi
;
}
\end{tikzpicture}
\end{document}
答案2
作为练习,我允许自己使用 MetaPost 进行这幅有趣的绘画。
MetaPost 的二元运算intersectiontimes
符在这里很重要:应用于两个路径 p1 和 p2,它返回一对数值 (t1, t2)。如果这两条路径相交,则对于每个 i,数值 ti 是定位 pi 上第一个交点的(非负)参数。否则(如果没有交点),它返回一对 (-1, -1)。
u = cm; % general unit
path ray, floor ; floor = (-3.5, -1) -- (3.5, -1);
beginfig(1);
draw floor scaled u ;
for theta = 0 step 15 until 345:
ray := origin -- 2dir theta ;
t := xpart(ray intersectiontimes floor) ; % t = -1 if no intersection
if t = -1: drawarrow ray scaled u;
else: drawarrow origin -- u*point t of ray;
fi;
endfor;
endfig;
end.
由于我更喜欢获取 MetaPost 图片的 PDF 版本,因此我通常使用 MPtoPDF 实用程序来执行其代码:mptopdf mydrawing.mp
结果:
编辑应 Thruston 的要求 ;-) 并遵循(不完全符合)他的示例,这是我的代码的简化版本,使用宏cutafter
代替。当然,它产生的结果与以前相同。
u = cm; % general unit
path ray, ground;
ground = (-3.5, -1) -- (3.5, -1); ray = origin -- (2, 0);
beginfig(1);
draw ground scaled u;
for theta = 0 step 15 until 345:
drawarrow (ray rotated theta cutafter ground) scaled u;
endfor;
endfig;
end.
答案3
向@fpast 致歉,这是一个相当简单的 Metapost 版本。
prologues := 3;
outputtemplate := "%j%c.eps";
beginfig(1);
path ray, base ;
ray = origin -- right scaled 60;
base = (left -- right) scaled 100 shifted 30 down;
draw base;
for theta = 0 step 15 until 359:
drawarrow ray rotated theta cutafter base;
endfor;
endfig;
end.
“plain.mp” 中的宏cutafter
在这里完成了所有艰苦的工作。诀窍是在程序中的同一点将缩放应用于两条路径。出于风格考虑,我更喜欢在开始绘制之前将其放入路径定义中。