假设我有给定的路径P
,并让T
为路径外的一个点。有没有一种简单的方法可以找到路径上的P
点,使得切线经过该点?X
P
X
T
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)
宏返回和之间的值,该值“处于真假之间的边缘”。true
f(b)
false
solve
a
b
您可以在本地副本中找到该宏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_)
......