根据角度计算从矩形点到边缘的矢量

时间:2010-07-05 13:52:24

标签: .net math vector 2d intersection

根据丹尼尔的说法,在他的回答中,没有简单的方法来修改下面的功能,所以我咬了一下子弹并从头开始。解决方案如下(作为答案)。实际上,忽略我的回答。看到汤姆·西格达斯的答案,它缩短了很多。


我需要修改这里找到的解决方案:Calculate a vector from the center of a square to edge based on radius,它从矩形的中心计算向量,以适用于矩形内的任何点。

这是以前的解决方案,来自链接:

    double magnitude;
    double abs_cos_angle= fabs(cos(angle));
    double abs_sin_angle= fabs(sin(angle));
    if (width/2*abs_sin_angle <= height/2*abs_cos_angle)
    {
            magnitude= width/2/abs_cos_angle;
    }
    else
    {
            magnitude= height/2/abs_sin_angle;
    }

    double check_x= x + cos(angle)*magnitude;
    double check_y= y + sin(angle)*magnitude;

check_x和check_y返回矩形边缘上的点,从中心以角度绘制的线将相交。

我去学校已经有一段时间了,所以我盲目地尝试用我感兴趣的点替换width / 2和height / 2.不幸的是,这不起作用。

有什么想法吗?

ETA:

如果线与顶部或左侧的矩形相交,则此盲修改始终返回正确的结果。根据原点所在的象限,当线与右或底相交时,它返回的点太远或太近。

5 个答案:

答案 0 :(得分:4)

假设矩形由(x1,y1,x2,y2)定义,让我们说光线从(px,py)开始。

设vx = cos(角度)

让vy = sin(角度)

沿着光线行进t的距离将带您到达该点(px + t vx,py + t vy)。

沿着光线旅行,

  • 当px + t * vx = x1或t =(x1-px)/ vx
  • 时我们碰到左墙
  • 当px + t * vx = x2或t =(x2-px)/ vx
  • 时,我们会碰到右墙
  • 当py + t * vy = y1或t =(y1-py)/ vy
  • 时我们碰到了顶墙
  • 当py + t * vy = y2或t =(y2-py)/ vy
  • 时我们碰到了底壁

因此,t有四种可能的解决方案。 t的正确值(在四个中)是最小的。实际交点位于该点(px + t vx,py + t vy)。小心不要除以零!

答案 1 :(得分:1)

最简单的解决方案可能只是执行四个射线线段交叉测试。我怀疑专用解决方案会更有效或更容易理解和维护。

答案 2 :(得分:0)

让我们直接澄清一件事:听起来像是你担心2D中的矢量。你的所有积分都在飞机上。这是一个你感兴趣的矩形也是如此(四角,都是90度角,两对相对的长度相同)?

矩形的中心由四个角点的平均值给出:

alt text http://www.equationsheet.com/latexrender/pictures/ccdca519c24bb6ab2b6164144645572a.gif

alt text http://www.equationsheet.com/latexrender/pictures/84550340ace7dade26dc3294fef8e156.gif

你的矢量有起点。

任何矢量都由两个点定义,因此您只需要第二个点(例如,边缘的中点)来计算2D空间中的矢量:

alt text http://www.equationsheet.com/latexrender/pictures/7c680a2354f4a2a0d05d6c97ba949bc4.gif

从中心点和角度开始的问题在于它为您提供了无限数量的向量,而不仅仅是一个向量。 (沿着以给定角度穿过中心点的线有无数个终点。)你必须从那个无限集中挑选出你感兴趣的精确终点。如果恰好是在任意点与你的一条边相交的那条,你必须先计算它。这是沿着矢量线的根发现问题。也许你可以查看割线或其他数值方法来弄清楚如何去做。

答案 3 :(得分:0)

以下解决方案为穿过所提供的点的线构建公式,并以指定的角度穿过矩形边框。根据角度,我测试它是否与2个矩形边框中的任何一个相交。我总是根据0到90度的角度进行检查。为了解释这一点,象限Q2和Q4中的测试使用的线与Q1和Q4中的线垂直。

当角度= 0时,线条指向东方 我从360减去了角度,使线条顺时针旋转而不是逆时针旋转。

Private Function GetIntersectionPoint(ByVal rectangleSize As SizeF, ByVal p As Point, ByVal degreeAngle As Single) As PointF

    Dim w = CInt(rectangleSize.Width)
    Dim h = CInt(rectangleSize.Height)
    degreeAngle = ((360 - degreeAngle) Mod 360)

    If degreeAngle = 0 Then
        Return New Point(w, p.Y)
    ElseIf degreeAngle = 90 Then
        Return New Point(p.X, 0)
    ElseIf degreeAngle = 180 Then
        Return New Point(0, p.Y)
    ElseIf degreeAngle = 270 Then
        Return New Point(p.X, h)
    End If

    Dim x, y As Integer

    If (degreeAngle > 0 AndAlso degreeAngle < 90) Then
        y = YFromX(degreeAngle, w, p)
        If y <= 0 AndAlso y >= -h Then
            Return New Point(w, -y)
        End If
        x = XFromY(degreeAngle, 0, p)
        Return New Point(x, 0)
    End If

    If (degreeAngle > 90 AndAlso degreeAngle < 180) Then
        degreeAngle -= 90
        y = YFromX_Perpedicular(degreeAngle, 0, p)
        If y <= 0 AndAlso y >= -h Then
            Return New Point(0, -y)
        End If
        x = XFromY_Perpendicular(degreeAngle, 0, p)
        Return New Point(x, 0)
    End If

    If (degreeAngle > 180 AndAlso degreeAngle < 270) Then
        degreeAngle -= 180
        y = YFromX(degreeAngle, 0, p)
        If y <= 0 AndAlso y >= -h Then
            Return New Point(0, -y)
        End If
        x = XFromY(degreeAngle, -h, p)
        Return New Point(x, h)
    End If

    If (degreeAngle > 270 AndAlso degreeAngle < 360) Then
        degreeAngle -= 270
        y = YFromX_Perpedicular(degreeAngle, w, p)
        If y <= 0 AndAlso y >= -h Then
            Return New Point(w, -y)
        End If
        x = XFromY_Perpendicular(degreeAngle, -h, p)
        Return New Point(x, h)
    End If

End Function

Private Function YFromX(ByVal degreeAngle As Single, ByVal x As Integer, ByVal p As Point) As Integer
    Dim alpha As Double = degreeAngle * Math.PI / 180
    Dim sinAlpha = Sin(alpha)
    Dim cosAlpha = Cos(alpha)
    Return CInt(sinAlpha / cosAlpha * (x - p.X) - p.Y)
End Function

Private Function XFromY(ByVal degreeAngle As Single, ByVal y As Integer, ByVal p As Point) As Integer
    Dim alpha As Double = degreeAngle * Math.PI / 180
    Dim sinAlpha = Sin(alpha)
    Dim cosAlpha = Cos(alpha)
    Return CInt(cosAlpha / sinAlpha * (y + p.Y) + p.X)
End Function

Private Function YFromX_Perpedicular(ByVal degreeAngle As Single, ByVal x As Integer, ByVal p As Point) As Integer
    Dim alpha As Double = degreeAngle * Math.PI / 180
    Dim sinAlpha = Sin(alpha)
    Dim cosAlpha = Cos(alpha)
    Return CInt((cosAlpha / sinAlpha) * (p.X - x) - p.Y)
End Function

Private Function XFromY_Perpendicular(ByVal degreeAngle As Single, ByVal y As Integer, ByVal p As Point) As Integer
    Dim alpha As Double = degreeAngle * Math.PI / 180
    Dim sinAlpha = Sin(alpha)
    Dim cosAlpha = Cos(alpha)
    Return CInt(p.X - sinAlpha / cosAlpha * (y + p.Y))
End Function

答案 4 :(得分:0)

你基本上要求矩形的极坐标方程,它是

r(t) = min(R, w*abs(sec(t)), h*abs(csc(t))); t = [0, 2pi]

其中w和h是半宽和半高,R是大于或等于sqrt(w ^ 2 + h ^ 2)的任何数。这假定矩形位于原点,如果不是,则所有要做的就是将中心的坐标添加到结果中,通过(r cos(t),r sin获得结果) T))。 当然,这种方法很糟糕,因为sec和csc有奇点,但是你可以用max(w,h)来限制它们。