代码之家  ›  专栏  ›  技术社区  ›  Jules

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

  •  2
  • Jules  · 技术社区  · 14 年前

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


    我需要修改这里找到的解决方案: 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;
    

    勾选X,勾选Y,返回矩形边缘上的点,从中心画一条线,以一定角度相交。

    我上过学已经有一段时间了,所以我盲目地尝试用我感兴趣的点来代替宽2和高2。不幸的是,这行不通。

    有什么想法吗?

    埃塔:

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

    5 回复  |  直到 14 年前
        1
  •  4
  •   Tom Sirgedas    14 年前

    假设矩形是由(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的正确值(在这四种中)是最小的。 积极的 一个。实际交叉点位于点(px+t VX,PY+T VY)。小心不要被零除!

        2
  •  1
  •   Daniel Brückner Pradip    14 年前

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

        3
  •  0
  •   duffymo    14 年前

    让我们马上澄清一件事:在我看来,你担心二维的向量,你所有的点都在平面上。你感兴趣的矩形也是真的吗(四个角,都是90度角,两对相对的边有相同的长度)?

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

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

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

    这是向量的起点。

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

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

    从中心点和角度出发的问题是,它给了你无穷多的向量,而不仅仅是一个。(沿着直线有无数个终点,以给定的角度穿过你的中心点。)你必须从这个无限集中选出你感兴趣的精确终点。如果它恰好是在任意点与你的一条边相交的,你必须首先计算它。这是一个沿着向量线的找根问题。也许你可以用割线或者其他数值方法来计算。

        4
  •  0
  •   Jules    14 年前

    下面的解决方案为通过提供的点并以指定角度穿过矩形边框的线构建公式。根据角度,我测试它是否与两个矩形边框相交。我总是以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
    
        5
  •  0
  •   Victor Liu    14 年前

    你基本上是在求一个矩形的极性方程,它是

    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 罪(t)。 当然,这种方法很糟糕,因为SEC和CSC都有奇点,但是您可以将它们限制在max(w,h)。