gpt4 book ai didi

iphone - 在与中心点成给定角度的直线相交的 UIView 矩形上找到 CGPoint

转载 作者:技术小花猫 更新时间:2023-10-29 10:57:33 25 4
gpt4 key购买 nike

在 iOS 中,我试图确定一个矩形上的点,该点与从中心点到矩形周边的假想线以预定角度相交。

假设我知道中心点、矩形的大小和角度(从东边的 0 度开始,逆时针方向经过北边的 90 度、西边的 180 度和南边的 270 度,再到东边的 360 度)。我需要知道相交点的坐标。

Finding points on a rectangle at a given angle 上的(对我而言)有点令人困惑的数学但大概是准确的答案让我尝试下面的代码,但它不能正常工作。这个问题与那个问题类似,但我正在寻找一种更正的 Objective-C/iOS 方法,而不是一般的数学响应。

我认为部分代码问题与使用单个 0 到 360 度角(以弧度表示,不可能为负数)输入有关,但可能还有其他问题。下面的代码主要使用 the answer from belisarius 中定义的符号,包括我尝试为此处定义的四个区域计算交点。

这段代码在我的 UIImageView 子类中:

- (CGPoint) startingPointGivenAngleInDegrees:(double)angle {
double angleInRads = angle/180.0*M_PI;
float height = self.frame.size.height;
float width = self.frame.size.width;
float x0 = self.center.x;
float y0 = self.center.y;
// region 1
if (angleInRads >= -atan2(height, width) && angleInRads <= atan2(height, width)) {
return CGPointMake(x0 + width/2, y0 + width/2 * tan(angleInRads));
}
// region 2
if (angleInRads >= atan2(height, width) && angleInRads <= M_PI - atan2(height, width)) {
return CGPointMake(x0 + height / (2*tan(angleInRads)),y0+height/2);
}
// region 3
if (angleInRads >= M_PI - atan2(height, width) && angleInRads <= M_PI + atan2(height, width)) {
return CGPointMake(x0 - width/2, y0 + width/2 * tan(angleInRads));
}
// region 4
return CGPointMake(x0 + height / (2*tan(angleInRads)),y0-height/2);
}

最佳答案

我不会调试您的代码,而只是解释我将如何做到这一点。

首先,几个术语。让我们将 xRadius 定义为框架宽度的一半,将 yRadius 定义为框架高度的一半。

现在考虑框架的四个边,并将它们延伸为无限长的线。在这四条线的顶部,放置一条以您指定的角度穿过框架中心的线:

diagram of rectangle with overlaid line

假设框架以原点为中心 - 框架的中心位于坐标 (0,0)。我们可以很容易地计算出对角线与框架右边缘相交的位置:坐标为 (xRadius, xRadius * tan(angle))。我们可以很容易地计算出对角线与框架顶部边缘相交的位置:坐标是 (-yRadius/tan(angle), -yRadius).

(为什么我们否定顶边交点的坐标?因为 UIView 坐标系是从正常的数学坐标系翻转过来的。在数学中,y 坐标向页面顶部增加. 在 UIView 中,y 坐标向 View 底部增加。)

所以我们可以简单地计算直线与框架右边缘的交点。如果该交点在框架之外,那么我们知道该线必须先与上边缘相交,然后再与右边缘相交。。我们如何判断右边缘交点是否越界?如果它的 y 坐标 (xRadius * tan(angle)) 大于 yRadius(或小于 -yRadius),则它超出范围。

因此,为了将它们放在一个方法中,我们首先计算 xRadiusyRadius:

- (CGPoint)radialIntersectionWithConstrainedRadians:(CGFloat)radians {
// This method requires 0 <= radians < 2 * π.

CGRect frame = self.frame;
CGFloat xRadius = frame.size.width / 2;
CGFloat yRadius = frame.size.height / 2;

然后我们计算与右边缘相交的 y 坐标:

    CGPoint pointRelativeToCenter;
CGFloat tangent = tanf(radians);
CGFloat y = xRadius * tangent;

我们检查交点是否在框架中:

    if (fabsf(y) <= yRadius) {

一旦我们知道它在框架中,我们就必须弄清楚我们想要与右边缘还是左边缘相交。如果角度小于 π/2 (90°) 或大于 3π/2 (270°),我们需要右边缘。否则我们需要左边。

        if (radians < (CGFloat)M_PI_2 || radians > (CGFloat)(M_PI + M_PI_2)) {
pointRelativeToCenter = CGPointMake(xRadius, y);
} else {
pointRelativeToCenter = CGPointMake(-xRadius, -y);
}

如果右边缘交点的 y 坐标 • 是*越界,我们计算与底部边缘交点的 x 坐标。

    } else {
CGFloat x = yRadius / tangent;

接下来我们要弄清楚我们是想要顶部边缘还是底部边缘。如果角度小于 π (180°),我们需要底边。否则,我们需要顶部边缘。

        if (radians < (CGFloat)M_PI) {
pointRelativeToCenter = CGPointMake(x, yRadius);
} else {
pointRelativeToCenter = CGPointMake(-x, -yRadius);
}
}

最后,我们将计算出的点偏移框架的实际中心并将其返回。

    return CGPointMake(pointRelativeToCenter.x + CGRectGetMidX(frame),
pointRelativeToCenter.y + CGRectGetMidY(frame));
}

在这里测试项目:https://github.com/mayoff/stackoverflow-radial-intersection

看起来像这样:

edgepoint screen shot

关于iphone - 在与中心点成给定角度的直线相交的 UIView 矩形上找到 CGPoint,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9526726/

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