从曲线外的用户给定点找到曲线上的切点 [英] Find tangent points on a curve from a user-given point outside the curve

查看:160
本文介绍了从曲线外的用户给定点找到曲线上的切点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到闭合曲线外的给定点(不在曲线上)的切线。例如,曲线被定义为点的2D x和y坐标,例如形状像一个不规则的椭圆。如果用户给出一个点:(x0,y0)= (-30,80),我怎么能知道曲线上的切点(即从(x0,y0)到曲线的切线)的切点(明显是离平滑曲线的离散点最近的点)?

解决方案

一种可能性是使用数值微分来找到每一点的切线,并决定它是否通过足够接近给定点。然而,人们必须认真思考足够接近以避免不匹配或者太多。

下面是另一种方法:考虑从给定点(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描述曲线;

x0 = 4; y0 = 5; %给出点

xn =(x-x0)./ sqrt((x-x0)。^ 2+(y-y0)。^ 2); %单位向量
yn =(y-y0)./ sqrt((x-x0)。^ 2+(y-y0)。^ 2); %从x0,y0到曲线上的点
cvx = convhull(xn,yn);单位向量的%凸包

[〜,i] = max(diff(xn(cvx))。^ 2 + diff(yn(cvx))。^ 2);船体最大空隙
x1 = xn(cvx(i)); Y1 = YN(CVX(I));两边的向量%
x2 = xn(cvx(i + 1)); Y2 = YN(CVX第(i + 1));缺口的百分比

plot(x,y)
持有
s = linspace(0,10);
plot(x0 + s * x1,y0 + s * y1,'r')%output
plot(x0 + s * x2,y0 + s * y2,'r')
推迟






另一种方法,如果(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描述曲线;

x0 = 4; y0 = 8; %给定点

xe = [x0,x]; ye = [y0,y]; %把所有点放在一起
cvx = convhull(xe,ye); %找到凸包

x1 = xe(cvx(2)); Y1 =咋(CVX(2)); %(x0,y0)
x2 = xe(cvx(end-1))的一个邻居; Y2 =咋(CVX(端-1)); %另一个邻居

plot(x,y)
持有
s = linspace(0,2);
plot(x0 + s *(x1-x0),y0 + s *(y1-y0),'r')%绘制线条
plot(x0 + s *(x2-x0), y0 + s *(y2-y0),'r')
延期


I am trying to find the tangent lines from a given point outside a closed curve (not on the curve). The curve is defined as 2D x and y coordinates of points,shaped like an irregular ellipse for example.

If given a point by the user: (x0,y0) = (-30,80), how can I know the tangent points (obviously closest point among discrete points from the smooth curve) on curve (i.e. tangent lines from (x0,y0) to curve)?

解决方案

One possibility is to use numerical differentiation to find the tangent line at every point, and decide whether it passes "close enough" to the given point. However, one has to think hard about "close enough" to avoid getting either no matches or too many.

Here is another approach: consider the unit vectors pointing from the given point (x0,y0) to the points on the curve. Find the largest gap between them (the command convhull helps here). The vectors on both sides of the gap determine tangent lines.

In general this will find only two tangent lines, not all of them. But if the curve is convex, there are only two tangent lines anyway.

Here is an example of the tricky situations where the given point is within the convex hull of the curve.

The code that produced the above picture:

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


Another approach, which works fine if (x0,y0) is not within the convex hull of the curve.

Use convhull to find the convex hull of the union of the curve and of the given points (x0,y0). The two edges of the convex hull that are incident to (x0,y0) are tangent to the curve:

The code that produced the above picture:

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

这篇关于从曲线外的用户给定点找到曲线上的切点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆