我正在尝试从闭合曲线外的给定点(不在曲线上)找到切线。曲线定义为点的 2D x 和 y 坐标,例如不规则椭圆。
如果用户给定一个点:(x0,y0) = (-30,80),我怎么知道曲线上的切点(显然是平滑曲线离散点中最近的点)(即来自 (x0, y0) 弯曲)?
我正在尝试从闭合曲线外的给定点(不在曲线上)找到切线。曲线定义为点的 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 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