简体   繁体   English

如何在矩形的周长中找到一个点?

[英]How to find a point in the perimeter of a rectangle?

I'm using Python 2.7 and Pygame but any language answer will do. 我正在使用Python 2.7和Pygame,但是任何语言的答案都可以。

I'm trying to find a given point along the vector in the perimeter of a rectangle. 我试图沿着矩形的周长沿着向量找到给定的点。 I know the vector, and the center, width and height of the rectangle, but the center can be (0, 0) for the sake of simplicity 我知道矢量,以及矩形的中心,宽度和高度,但是为了简单起见(0, 0)中心可以是(0, 0)

So for example I want to find the point in the perimeter of the rectangle following the vector of roughly (0.7, 0.7) of a rectangle that is 2 wide by 6 height. 因此,例如,我想在矩形的周长中找到一个点,该点遵循2乘以6的高度的矩形的大约(0.7, 0.7)向量。

What I've got working now does the work; 我现在正在做的工作已经完成; but there's has got to be a better, more elegant way: I'm taking the length of the wider value between height and width of the rectangle and using every number in between that and 0 and testing that against each of the 4 sides of the rectangle and see if it's in it. 但是必须有一种更好,更优雅的方法:我采用矩形的高度和宽度之间较宽的值的长度,并使用介于0和0之间的每个数字,并针对矩形的4个边分别进行测试。矩形,看看是否在其中。

This is the code I use specific to my game, not generalized at all: http://pastebin.com/8Ai1iQeL 这是我专用于我的游戏的代码,根本没有泛化: http : //pastebin.com/8Ai1iQeL

I'm going to do this for vectors in the upper right quadrant but it shouldn't be hard to generalize this to the others. 我将对右上象限中的向量执行此操作,但是将其推广到其他区域并不难。 You know the angle of the vector and side lengths of the rectangle. 您知道矢量的角度和矩形的边长。 So 所以

1) Determine whether the vector will hit the right side or the top of the rectangle. 1)确定矢量将到达矩形的右侧还是顶部。 Do this by constructing the right triangle whose hypotenuse is the diagonal of the rectangle, ie the line from the origin to the upper corner. 通过构造直角三角形来做到这一点,直角三角形的斜边是矩形的对角线,即从原点到上角的线。 If the angle A of the vector is greater than this angle, it will hit the top; 如果向量的角度A大于该角度,它将到达顶部; otherwise it will hit the side. 否则会撞到一边。

2) Suppose it hits the side (the solution will be analogous if it hits the top). 2)假设它碰到侧面(如果碰到顶部,解决方案将类似)。 If the width of the triangle is w, then you can construct a right triangle whose vertices are the origin, the point (w/2, 0), and the point (w/2, y), where (w/2, y) is the point you want to find. 如果三角形的宽度为w,则可以构造一个直角三角形,其顶点为原点,点(w / 2,0)和点(w / 2,y),其中(w / 2,y )是您要查找的点。 Then just use the law of sines to get y. 然后只要使用罪孽定律就可以得到y。

As written this solution involves some branching (4 x 2) to cover all of the possibilities, but I bet if you work through it you can find ways to eliminate code duplication. 在撰写本文时,此解决方案涉及一些分支(4 x 2),以涵盖所有可能性,但是我敢打赌,如果您通过它进行工作,则可以找到消除代码重复的方法。 For example, at the outset you can just rotate every vector into the upper right quadrant, and then after solving use the rotation to reconstruct the proper location of the point. 例如,一开始您可以将每个向量旋转到右上象限,然后在求解后使用旋转来重建该点的正确位置。

I'd go about this by comparing the ratio of the components of your vector, which is also the slope of the line parallel to the vector, to the same quantity for the vector pointing from the rectangle's center to its corner. 为此,我将比较矢量分量的比率(也就是平行于矢量的直线的斜率)与从矩形中心到其角点的矢量的相同比例。 That tells you whether the vector hits a horizontal or vertical side. 告诉您矢量是水平还是垂直。 After that, you can use a simple proportionality to find the intersection point. 之后,您可以使用简单的比例关系找到交点。

Suppose your vector is (x,y) , and for the moment assume that both coordinates are positive. 假设您的向量为(x,y) ,并且目前假设两个坐标均为正。 The slope is y/x and the equivalent quantity for the rectangle is h/w , using a coordinate system in which the rectangle's center is at (0,0) . 使用矩形中心为(0,0)的坐标系,斜率为y/x ,矩形的等效量为h/w Now, if y/x > h/w , your intersection point will be on the top edge, so you know its height is h/2. 现在,如果y/x > h/w ,则您的交点将位于顶部边缘,因此您知道其高度为h / 2。 You can then compute the coordinates as (0.5*h*x/y,0.5*h) . 然后可以将坐标计算为(0.5*h*x/y,0.5*h) If y/x < h/w , the intersection point is on the right edge, and the coordinates are (0.5*w,0.5*w*y/x) . 如果y/x < h/w ,则交点在右边缘,坐标为(0.5*w,0.5*w*y/x)

To use this in practice, you'd want to actually do the comparison between y*w and x*h , both to avoid problems with division by zero and to avoid the relatively expensive division operator (not that that really makes much of a difference). 要在实践中使用此方法,您实际上要在y*wx*h之间进行比较,既可以避免零除的问题,又可以避免使用相对昂贵的除法运算符(这并不是真的有很大的区别) )。 Also, you can find the correct signs for the components of the intersection point by just using the signs of x and y . 此外,仅使用xy的符号,就可以找到交点的正确符号。 So in code, it'd look something like this: 所以在代码中,它看起来像这样:

def intersect_perimeter(x, y, w, h):
    if abs(y*w) > abs(x*h):
        return (0.5*h*x/abs(y), 0.5*h*sign(y))
    else:
        return (0.5*w*sign(x), 0.5*w*y/abs(x))

(untested). (未经测试)。 This will fail if x is zero and either y or w is zero, but in that case you have either a zero vector (and the problem is undefined) or a zero-width rectangle (again, the problem is undefined). 如果x为零且yw为零,则此操作将失败,但在那种情况下,您将具有零向量(问题未定义)或零宽度矩形(同样,问题未定义)。 So I wouldn't bother with error checking for that case. 因此,我不会为这种情况而进行错误检查。

If your rectangle is centered at a point other than (0,0) , you just need to add the position vector representing the rectangle's center to the result from that function. 如果矩形的中心位于(0,0)以外的其他点,则只需将代表矩形中心的位置矢量添加到该函数的结果中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM