射线相交的地板

射线相交的地板

以下 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在这里完成了所有艰苦的工作。诀窍是在程序中的同一点将缩放应用于两条路径。出于风格考虑,我更喜欢在开始绘制之前将其放入路径定义中。

在此处输入图片描述

相关内容