在与中心点相交的给定angular度的直线相交的UIView矩形上查找CGPoint

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

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

对于给定angular度的矩形上的查找点,有点令人困惑的(对我来说)math的,但可能是准确的答案导致我尝试下面的代码,但它不能正常工作。 这个问题类似于那个,但我正在寻找一个更正的Objective-C / iOS方法,而不是一般的math响应。

我认为代码问题的一部分与使用单个0到360度angular度(弧度不可能有负数)input有关,但可能还有其他问题。 下面的代码主要使用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); } 

而不是debugging你的代码,我只是解释我将如何做到这一点。

首先,几个条款。 我们将xRadius定义为框架宽度的一半, xRadius定义为框架高度的一半。

现在考虑框架的四个边,并将它们扩展为无限的线。 在这四条线的上面,按照您指定的angular度穿过镜框的中心线:

带有重叠线的矩形图

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

(为什么我们否定了顶边交点的坐标?因为UIView坐标系是从正常的math坐标系翻转过来的,在math中,y坐标增加到页面的顶部,在UIView ,y坐标增加到底部的视图。)

所以我们可以简单地计算线条与框架右边缘的交点。 如果交叉点在框架之外,那么我们知道该线必须与右边缘相交之前与顶边相交。 我们如何判断右边的交点是否越界? 如果它的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) { 

一旦我们知道它是在框架中,我们必须弄清楚我们是否想要与右边或左边的交点。 如果angular度小于π/ 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; 

接下来,我们计算出我们是要上边还是下边。 如果angular度小于π(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)); } 

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

看起来像这样:

边缘点屏幕截图