给定角度和尺寸,找到沿矩形周长的坐标

发布于 2024-07-24 10:08:14 字数 244 浏览 7 评论 0原文

我正在编写一个脚本,其中图标围绕给定的枢轴(或原点)旋转。 我已经能够使图标围绕椭圆旋转,但我还想让它们围绕具有特定宽度、高度和原点的矩形的周边移动。

我这样做是因为我当前的代码将所有坐标存储在一个数组中,并以每个角度整数作为键,并且重用此代码会更容易使用。

如果有人能给我一个 100x150 矩形的例子,那就太好了。

编辑:澄清一下,旋转是指围绕形状的周边(或轨道)移动。

I'm writing a script where icons rotate around a given pivot (or origin). I've been able to make this work for rotating the icons around an ellipse but I also want to have them move around the perimeter of a rectangle of a certain width, height and origin.

I'm doing it this way because my current code stores all the coords in an array with each angle integer as the key, and reusing this code would be much easier to work with.

If someone could give me an example of a 100x150 rectangle, that would be great.

EDIT: to clarify, by rotating around I mean moving around the perimeter (or orbiting) of a shape.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

離人涙 2024-07-31 10:08:14

您知道矩形的大小,并且需要将整个角度间隔分成四个不同的角度间隔,这样您就知道来自矩形中心的射线是否与矩形的右侧、顶部、左侧或底部相交。

如果角度为:-atan(d/w) < 阿尔法< atan(d/w) 射线与矩形的右侧相交。 那么既然你知道从矩形中心到右侧的x位移是d/2,那么位移dy除以d/2就是tan(alfa),所以

dy = d/2 * tan(alfa)

你将以类似的方式处理其他三个角度间隔。

好的,开始了。 你有一个宽度为 w 深度为 d 的矩形。 中间有中心点 cp。 我假设你想计算 P,对于角度 alfa 的不同值。

alt text

我将矩形分为四个不同的区域或角度间隔(1 到 4)。 我上面提到的区间是右边第一个区间。 我希望这对你有意义。

首先需要计算角度间隔,这些角度间隔完全由 w 和 d 决定。根据 alfa 的值,相应地计算 P,即从 CP 到 P 的“射线”是否与上部相交,矩形的下边、右边或左边。

干杯

You know the size of the rectangle and you need to split up the whole angle interval into four different, so you know if a ray from the center of the rectangle intersects right, top, left or bottom of the rectangle.

If the angle is: -atan(d/w) < alfa < atan(d/w) the ray intersects the right side of the rectangle. Then since you know that the x-displacement from the center of the rectangle to the right side is d/2, the displacement dy divided by d/2 is tan(alfa), so

dy = d/2 * tan(alfa)

You would handle this similarily with the other three angle intervals.

Ok, here goes. You have a rect with width w and depth d. In the middle you have the center point, cp. I assume you want to calculate P, for different values of the angle alfa.

alt text

I divided the rectangle in four different areas, or angle intervals (1 to 4). The interval I mentioned above is the first one to the right. I hope this makes sense to you.

First you need to calculate the angle intervals, these are determined completely by w and d. Depending on what value alfa has, calculate P accordingly, i.e. if the "ray" from CP to P intersects the upper, lower, right or left sides of the rectangle.

Cheers

波浪屿的海角声 2024-07-31 10:08:14

这是为 Pebble 智能手表设计的,并经过验证可以在 Pebble 智能手表上运行,但修改为伪代码:

struct GPoint {
  int x;
  int y;
}

// Return point on rectangle edge.  Rectangle is centered on (0,0) and has a width of w and height of h
GPoint getPointOnRect(int angle, int w, int h) {
  var sine = sin(angle), cosine = cos(angle);   // Calculate once and store, to make quicker and cleaner
  var dy = sin>0 ? h/2 : h/-2;                  // Distance to top or bottom edge (from center)
  var dx = cos>0 ? w/2 : w/-2;                  // Distance to left or right edge (from center)
  if(abs(dx*sine) < abs(dy*cosine)) {           // if (distance to vertical line) < (distance to horizontal line)
    dy = (dx * sine) / cosine;                  // calculate distance to vertical line
  } else {                                      // else: (distance to top or bottom edge) < (distance to left or right edge)
    dx = (dy * cosine) / sine;                  // move to top or bottom line
  }
  return GPoint(dx, dy);                        // Return point on rectangle edge
}


Use:
rectangle_width  = 100;
rectangle_height = 150;
rectangle_center_x = 300;
rectangle_center_y = 300;
draw_rect(rectangle_center_x - (rectangle_width/2), rectangle_center_y - (rectangle_center_h/2), rectangle_width, rectangle_height);
GPoint point = getPointOnRect(angle, rectangle_width, rectangle_height);
point.x += rectangle_center_x;
point.y += rectangle_center_y;
draw_line(rectangle_center_x, rectangle_center_y, point.x, point.y);

This was made for and verified to work on the Pebble smartwatch, but modified to be pseudocode:

struct GPoint {
  int x;
  int y;
}

// Return point on rectangle edge.  Rectangle is centered on (0,0) and has a width of w and height of h
GPoint getPointOnRect(int angle, int w, int h) {
  var sine = sin(angle), cosine = cos(angle);   // Calculate once and store, to make quicker and cleaner
  var dy = sin>0 ? h/2 : h/-2;                  // Distance to top or bottom edge (from center)
  var dx = cos>0 ? w/2 : w/-2;                  // Distance to left or right edge (from center)
  if(abs(dx*sine) < abs(dy*cosine)) {           // if (distance to vertical line) < (distance to horizontal line)
    dy = (dx * sine) / cosine;                  // calculate distance to vertical line
  } else {                                      // else: (distance to top or bottom edge) < (distance to left or right edge)
    dx = (dy * cosine) / sine;                  // move to top or bottom line
  }
  return GPoint(dx, dy);                        // Return point on rectangle edge
}


Use:
rectangle_width  = 100;
rectangle_height = 150;
rectangle_center_x = 300;
rectangle_center_y = 300;
draw_rect(rectangle_center_x - (rectangle_width/2), rectangle_center_y - (rectangle_center_h/2), rectangle_width, rectangle_height);
GPoint point = getPointOnRect(angle, rectangle_width, rectangle_height);
point.x += rectangle_center_x;
point.y += rectangle_center_y;
draw_line(rectangle_center_x, rectangle_center_y, point.x, point.y);
べ繥欢鉨o。 2024-07-31 10:08:14

使用角度作为参数来执行此操作的一种简单方法是使用矩形的边界简单地裁剪 X 和 Y 值。 换句话说,计算位置,就像图标将围绕圆形或椭圆形路径旋转一样,然后应用此:(

假设轴对齐矩形以 (0,0) 为中心,X 轴长度为 XAxis,Y 轴长度为YAxis):

if (X > XAxis/2)    
         X = XAxis/2;

if (X < 0 - XAxis/2)
         X = 0 - XAxis/2;

if (Y > YAxis/2)    
         Y = YAxis/2;

if (Y < 0 - YAxis/2)    
         Y = 0 - YAxis/2;

这种方法的问题是角度不完全准确,并且沿矩形周边的速度不会恒定。 建立一个在其角部与矩形密切接触的椭圆模型可以最大限度地减少影响,但如果您正在寻找平滑、恒速的“轨道”,则此方法是不够的。

One simple way to do this using an angle as a parameter is to simply clip the X and Y values using the bounds of the rectangle. In other words, calculate position as though the icon will rotate around a circular or elliptical path, then apply this:

(Assuming axis-aligned rectangle centered at (0,0), with X-axis length of XAxis and Y-axis length of YAxis):

if (X > XAxis/2)    
         X = XAxis/2;

if (X < 0 - XAxis/2)
         X = 0 - XAxis/2;

if (Y > YAxis/2)    
         Y = YAxis/2;

if (Y < 0 - YAxis/2)    
         Y = 0 - YAxis/2;

The problem with this approach is that the angle will not be entirely accurate and the speed along the perimeter of the rectangle will not be constant. Modelling an ellipse that osculates the rectangle at its corners can minimize the effect, but if you are looking for a smooth, constant-speed "orbit," this method will not be adequate.

冷月断魂刀 2024-07-31 10:08:14

如果你认为你的意思是像地球绕太阳旋转一样旋转(而不是自转......所以你的问题是如何沿着矩形的边缘滑动?)

如果是这样,你可以尝试一下:

# pseudo coode
for i = 0 to 499
  if i < 100:  x++
  else if i < 250: y--
  else if i < 350: x--
  else y++

  drawTheIcon(x, y)

更新:(请参阅下面的评论)

要使用角度,一条线将是

y / x = tan(th)       # th is the angle

其他线很简单,因为它们只是水平或垂直的。 例如,x = 50,您可以将其放入上面的行中以获得 y。 对水平线和垂直线的交点执行此操作(例如,角度为 60 度,它拍摄“东北”...现在您有两个点。那么最接近原点的点就是击中原点的点首先是矩形)。

If think you mean rotate like the earth rotates around the sun (not the self-rotation... so your question is about how to slide along the edges of a rectangle?)

If so, you can give this a try:

# pseudo coode
for i = 0 to 499
  if i < 100:  x++
  else if i < 250: y--
  else if i < 350: x--
  else y++

  drawTheIcon(x, y)

Update: (please see comment below)

to use an angle, one line will be

y / x = tan(th)       # th is the angle

the other lines are simple since they are just horizontal or vertical. so for example, it is x = 50 and you can put that into the line above to get the y. do that for the intersection of the horizontal line and vertical line (for example, angle is 60 degree and it shoot "NorthEast"... now you have two points. Then the point that is closest to the origin is the one that hits the rectangle first).

长安忆 2024-07-31 10:08:14

使用2D 变换矩阵。 许多语言(例如 Java)本身就支持这一点(查找 AffineTransformation); 否则,自己写一个例程进行轮换,一次,调试好,永远使用。 我必须用不同的语言写五本。

一旦你可以简单地进行旋转,通过执行线与线相交来找到矩形上的位置。 通过两条线相交来找到轨道图标的中心:

  1. 从旋转中心以所需角度发出的射线
  2. 四条边之一,以所需角度为界(四个象限)。

Use a 2D transformation matrix. Many languages (e.g. Java) support this natively (look up AffineTransformation); otherwise, write out a routine to do rotation yourself, once, debug it well, and use it forever. I must have five of them written in different languages.

Once you can do the rotation simply, find the location on the rectangle by doing line-line intersection. Find the center of the orbited icon by intersecting two lines:

  1. A ray from your center of rotation at the angle you desire
  2. One of the four sides, bounded by what angle you want (the four quadrants).
葮薆情 2024-07-31 10:08:14

在一张纸上为自己画一个草图,其中包含一个矩形和一个旋转中心。 首先将矩形平移到坐标系原点的中心(记住平移参数,稍后您需要反转平移)。 旋转矩形,使其边与坐标轴平行(同样的原因)。

现在你有了一个原点角度已知的三角形,对边的长度已知(矩形一侧长度的一半),现在你可以:

-- 求解三角形

-- 撤消旋转

-- 撤消译文

Draw yourself a sketch on a piece of paper with a rectangle and a centre of rotation. First translate the rectangle to centre at the origin of your coordinate system (remember the translation parameters, you'll need to reverse the translation later). Rotate the rectangle so that its sides are parallel to the coordinate axes (same reason).

Now you have a triangle with known angle at the origin, the opposite side is of known length (half of the length of one side of the rectangle), and you can now:

-- solve the triangle

-- undo the rotation

-- undo the translation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文