2

我正在尝试从闭合曲线外的给定点(不在曲线上)找到切线。曲线定义为点的 2D x 和 y 坐标,例如不规则椭圆。

如果用户给定一个点:(x0,y0) = (-30,80),我怎么知道曲线上的切点(显然是平滑曲线离散点中最近的点)(即来自 (x0, y0) 弯曲)?

4

1 回答 1

4

一种可能性是使用数值微分来找到每个点的切线,并确定它是否“足够接近”到给定点。但是,必须认真考虑“足够接近”以避免没有匹配或太多。

这是另一种方法:考虑从给定点 (x0,y0) 指向曲线上的点的单位向量。找到它们之间的最大差距(命令 convhull 在这里有帮助)。间隙两侧的矢量确定切线。

一般来说,这只会找到两条切线,而不是全部。但是如果曲线是凸的,那么无论如何只有两条切线。

这是给定点位于曲线凸包内的棘手情况的示例。

棘手

产生上图的代码:

t = linspace(0,2*pi,100);
x = 10*cos(t) + sin(7*t);
y = 6*sin(t) + cos(13*t);                 % x,y  describe the curve; 

x0 = 4; y0 = 5;                           % given point 

xn = (x-x0)./sqrt((x-x0).^2+(y-y0).^2);   % unit vectors 
yn = (y-y0)./sqrt((x-x0).^2+(y-y0).^2);   % from x0,y0 to points on the curve
cvx = convhull(xn,yn);                    % convex hull of unit vectors  

[~,i] = max(diff(xn(cvx)).^2+diff(yn(cvx)).^2);    % largest gap in the hull
x1 = xn(cvx(i)); y1=yn(cvx(i));            % vectors on both sides
x2 = xn(cvx(i+1)); y2=yn(cvx(i+1));        % of the gap     

plot(x,y)
hold on
s = linspace(0,10);
plot(x0+s*x1, y0+s*y1, 'r')                % output
plot(x0+s*x2, y0+s*y2, 'r') 
hold off

另一种方法,如果 (x0,y0) 不在曲线的凸包内,则效果很好。

用于convhull查找曲线和给定点联合的凸包(x0,y0)(x0,y0)与曲线相切的凸包的两条边:

凸包

产生上图的代码:

t = linspace(0,2*pi,100);
x = 10*cos(t) + sin(7*t);
y = 6*sin(t) + cos(13*t);                 % x,y  describe the curve; 

x0 = 4; y0 = 8;                           % given point 

xe = [x0, x]; ye = [y0, y];               % put all points together 
cvx = convhull(xe,ye);                    % find convex hull 

x1 = xe(cvx(2)); y1=ye(cvx(2));           % one neighbor of (x0,y0)
x2 = xe(cvx(end-1)); y2=ye(cvx(end-1));   % another neighbor

plot(x,y)
hold on
s = linspace(0,2);
plot(x0+s*(x1-x0), y0+s*(y1-y0), 'r')     % plot the lines 
plot(x0+s*(x2-x0), y0+s*(y2-y0), 'r') 
hold off
于 2015-04-26T21:18:23.297 回答