gpt4 book ai didi

swift - 拖动线段控件 - 计算线上点

转载 作者:行者123 更新时间:2023-11-30 10:13:41 27 4
gpt4 key购买 nike

我有一条由 P1 和 P2 定义的线段,以及该线上的一个可以拖动的旋钮。如果拖动位置 L 远离线段,则拖动也应该起作用。

一个想法是找到垂直线,然后找到交点。但如果拖动位置 L 正好在线段上或穿过 P1 和 P2 的(无限)线上,则该方法不起作用。

事实上,归根结底,这应该是一个简单的 slider 控件,唯一的区别是该控件并不总是水平或垂直线段(您可以在其中拖动),而是可以是任何角度。

最佳答案

让我们将 V 定义为向量 P2 - P1。因此,有一条由 P1 + t V 定义的直线(对于所有实数 t),并且您的线段(称为 S)是该直线的子集,其中 0 ≤ t ≤ 1。

您想要找到 S 中最接近拖动点 L 的点。对于任意 t,从 L 到直线上 t 点的距离为

sqrt((P1x + t Vx - Lx)^2 + (P1y + t Vy - Ly)^2)).

为了找到距离 L 最近的点,我们需要找到使该距离最小化的 t。事实上,最小化距离的平方就足够了

(P1x + t Vx - Lx)^2 + (P1y + t Vy - Ly)^2

有时称为四边形。为了找到使象限最小化的 t,我们取象限相对于 t 的导数,将其设置为零,然后求解 t:

Solve[D[(P1x + t Vx - Lx)^2 + (P1y + t Vy - Ly)^2, t] == 0, t]

如果您将其输入 Mathematica ,你就会得到答案

{{t->(Lx Vx - P1x Vx + Ly Vy - P1y Vy) / (Vx^2 + Vy^2)}}

但是 t 可以是任何实数。您需要将其限制在 0 ... 1 范围内,以确保在线段中获得一个点。

在 swift :

extension CGPoint {

func closestPointOnLineSegment(start p1: CGPoint, end p2: CGPoint) -> CGPoint {
let v = CGPointMake(p2.x - p1.x, p2.y - p1.y)
var t: CGFloat = (self.x * v.x - p1.x * v.x + self.y * v.y - p1.y * v.y) / (v.x * v.x + v.y * v.y)
if t < 0 { t = 0 }
else if t > 1 { t = 1 }
return CGPointMake(p1.x + t * v.x, p1.y + t * v.y)
}

}

使用示例:

let knobPoint = dragPoint.closestPointOnLineSegment(start: p1, end: p2)

关于swift - 拖动线段控件 - 计算线上点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31459469/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com