Metafont/Metapost — 查找通过外部点的切线路径

Metafont/Metapost — 查找通过外部点的切线路径

假设我有给定的路径P,并让T为路径外的一个点。有没有一种简单的方法可以找到路径上的P点,使得切线经过该点?XPXT

Metapost 中的示例:

outputformat := "svg";
outputtemplate := "%j-%c.svg";
beginfig(1)
pair T,X; path P;
T:=(800,900); P:=(0,0)..(300,100)..(200,600);
draw P withpen pencircle scaled 10;
draw T withpen pencircle scaled 20 withcolor red;
endfig; end

基本上,我需要的是:(X = directionpoint (T-X) of P这当然是一个错误)。

我能想到的唯一解决方案是检查路径上的每个点,直到找到它,例如:

numeric v; v:=0;
forever: X:=point v of P;
exitif abs(angle(T-X) - angle(direction v of P)) < 0.001; % for example
v:=v+epsilon; endfor;

当然,这个特定的代码并不是在所有情况下都能正常工作。而且它的速度非常慢。

有没有更好的解决方案?当然,一般情况下可能没有解决方案,或者不止一个解决方案。

答案1

尝试这个:

outputformat := "svg";
outputtemplate := "%j-%c.svg";
beginfig(1);
pair T,X; path P;
T:=(800,900); P:=(0,0)..(300,100)..(200,600);
draw P withpen pencircle scaled 10;
draw T withpen pencircle scaled 20 withcolor red;

vardef f(expr t) = angle direction t of P - angle (T - point t of P) < eps enddef;
X = point solve f (0, 2) of P;
draw X -- T withpen pencircle scaled 5 withcolor red;

endfig; end

这得到了这个(虽然我使用 eps 作为输出格式并将其转换为 png 以获得这个实际的图片)

在此处输入图片描述

solve的解释如下Metafont 书籍pp.176-177。换句话说,宏使用二分搜索来找到非线性方程的数值(强力)解。您必须定义一个宏使用单个参数返回 或true。然后,false您将宏的名称solve作为传递给suffix,后跟一对和(a, b)f(a)宏返回和之间的值,该值“处于真假之间的边缘”。truef(b)falsesolveab

您可以在本地副本中找到该宏plain.mp

vardef solve@#(expr true_x,false_x)= 
 tx_:=true_x; fx_:=false_x;
 forever: x_:=.5[tx_,fx_]; exitif abs(tx_-fx_)<=tolerance;
 if @#(x_): tx_ else: fx_ fi :=x_; endfor
 x_ enddef; % now x_ is near where @# changes from true to false
newinternal tolerance, tx_,fx_,x_; tolerance:=.01;

注意传递的宏是如何被调用的@#(x_)......

相关内容