Tìm điểm trên đường tròn có tâm, bán kính và tung độ đã cho


82

Đã 10 năm kể từ khi tôi làm bất kỳ phép toán nào như thế này ... Tôi đang lập trình một trò chơi ở dạng 2D và di chuyển một người chơi xung quanh. Khi di chuyển trình phát xung quanh, tôi đang cố gắng tính điểm trên một vòng tròn cách vị trí trình phát 200 pixel với góc dương HOẶC âm (độ) trong khoảng từ -360 đến 360. Màn hình có kích thước 1280x720 với 0,0 là tâm điểm của màn hình. Người chơi di chuyển xung quanh toàn bộ hệ tọa độ Descartes này. Điểm tôi đang cố gắng tìm có thể bị tắt màn hình.

Tôi đã thử các công thức trong bài viết Tìm điểm có bán kính và góc nhưng tôi không tin rằng mình đang hiểu "Góc" là gì vì tôi nhận được kết quả kỳ lạ khi chuyển Góc là -360 đến 360 thành Cos (góc) hoặc Sin (góc).

Ví dụ, tôi có ...

  • 1280x720 trên mặt phẳng Descartes
  • Điểm trung tâm (vị trí của người chơi):
    • đặt x = một số từ tối thiểu -640 đến tối đa 640
    • đặt y = một số từ nhỏ nhất -360 đến tối đa 360
  • Bán kính của Vòng tròn xung quanh người chơi: đặt r luôn = 200
  • Góc: cho a = một số được cho trong khoảng từ -360 đến 360 (cho phép âm hướng xuống hoặc dương hướng lên trên để -10 và 350 sẽ cho cùng một câu trả lời)

Công thức để trả về X trên đường tròn là gì?

Công thức để trả về Y trên đường tròn là gì?

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


16
Đây là một câu hỏi hay!!! +1
FrostyFire,

1
Câu hỏi: Không phải hầu hết các trò chơi đều có dây buộc ở trên cùng bên trái đến 0,0 sao? và trục y đi xuống, không đi lên?
Persijn

Câu trả lời:


73

Các phương trình đơn giản từ liên kết của bạn cho tọa độ X và Y của điểm trên đường tròn so với tâm của đường tròn .

X = r * cosine(angle)  
Y = r * sine(angle)

Điều này cho bạn biết điểm đó cách tâm của vòng tròn bao xa. Vì bạn có tọa độ của tâm (Cx, Cy), chỉ cần thêm phần bù đã tính.

Tọa độ của điểm trên đường tròn là:

X = Cx + (r * cosine(angle))  
Y = Cy + (r * sine(angle))

1
Sự nhầm lẫn của tôi đầu tiên là sự khác biệt giữa ANGLE và DEGREE. Tôi đã nghĩ chúng giống nhau. Sau đó, tôi nghĩ rằng tôi đang nhận được điểm (x, y) trên mặt phẳng nhưng tôi thực sự nhận được độ dài của các cạnh của x và y. Tôi đã vẽ nó ra giấy sau đó viết nó trong excel để bao gồm phạm vi độ để kiểm tra các công thức. Nó hoạt động ngay trong mã của tôi.
Kyle Anderson,

3
Không nên X = xcircle + (r * sine(angle))X = xcircle + (r * cosine(angle))(và ngược lại cho Y)?
txtechhelp

4
Lưu ý rằng góc phải là một giá trị tính bằng radian!
Roman M

17

Bạn nên đăng mã bạn đang sử dụng. Điều đó sẽ giúp xác định chính xác vấn đề.

Tuy nhiên, vì bạn đã đề cập đến việc đo góc của mình theo giới hạn -360 đến 360, nên có thể bạn đang sử dụng đơn vị không chính xác cho thư viện toán học của mình. Hầu hết việc triển khai các hàm lượng giác sử dụng radian cho đầu vào của chúng. Và nếu bạn sử dụng độ thay thế ... câu trả lời của bạn sẽ sai một cách kỳ lạ.

x_oncircle = x_origin + 200 * cos (degrees * pi / 180)
y_oncircle = y_origin + 200 * sin (degrees * pi / 180)

Lưu ý rằng bạn cũng có thể gặp phải trường hợp mà góc phần tư không như bạn mong đợi. Điều này có thể được khắc phục bằng cách chọn cẩn thận vị trí góc 0 hoặc bằng cách kiểm tra thủ công góc phần tư bạn mong đợi và áp dụng các dấu hiệu của riêng bạn cho các giá trị kết quả.


1
Đây thực sự nên là một bình luận hơn là một câu trả lời. Tuy nhiên, bắt tốt về radian so với độ.
yoozer8

Câu hỏi đăng zombie: trong parens, đó là (deg * (pi / 180))hay cách khác ((deg * pi) / 180)? Cũng cảm ơn bạn đã chỉ định sự khác biệt giữa rad và deg.
Monsto

@monsto zombies vẫn gửi thông báo. :). Các parens bên trong không quan trọng bởi vì phép nhân và phép chia là các phép chứng minh giao hoán.wolfram.com/ …. Tôi từ lâu đã có lỗi khi đặt quá nhiều parens trong mã của mình. Tôi giả vờ như vậy để rõ ràng nhưng rõ ràng điều đó không hoàn toàn đúng, nếu không bạn sẽ không thấy phiền vì điều đó.
Seth Battin

6

Tôi thực sự khuyên bạn nên sử dụng ma trận cho loại thao tác này. Đây là cách tiếp cận chung nhất, xem ví dụ bên dưới:

// The center point of rotation
var centerPoint = new Point(0, 0);
// Factory method creating the matrix                                        
var matrix = new RotateTransform(angleInDegrees, centerPoint.X, centerPoint.Y).Value;
// The point to rotate
var point = new Point(100, 0);
// Applying the transform that results in a rotated point                                      
Point rotated = Point.Multiply(point, matrix); 
  • Lưu ý bên cạnh, quy ước là đo góc ngược chiều kim đồng hồ dạng bắt đầu (dương) trục X

5

Tôi nhận được kết quả kỳ lạ khi tôi chuyển Góc là -360 đến 360 thành Cos (góc) hoặc Sin (góc).

Tôi nghĩ lý do mà nỗ lực của bạn không thành công là bạn đã vượt qua các góc theo độ. Các hàm lượng giác sincoslượng giác mong đợi các góc được biểu thị bằng radian, vì vậy các số phải từ 0đến 2*M_PI. Đối với các dmức độ bạn vượt qua M_PI*d/180.0. M_PIlà một hằng số được xác định trong math.htiêu đề.


Tôi đã tìm ra góc và độ có lẽ không giống nhau vì vậy tôi có đúng khi nói Angle = M_PI * d / 180.0 trong đó d có thể là một số từ -360 đến 360 hay tôi cần một bước khác?
Kyle Anderson,

1
@Kyle dlà từ 0đến 360hoặc từ -180đến 180(một vòng tròn hoàn chỉnh), không phải từ -360đến 360(hai vòng tròn hoàn chỉnh).
Sergey Kalinichenko,

4

Tôi cũng cần điều này để hình thành chuyển động của kim đồng hồ trong mã. Tôi đã thử một số công thức nhưng chúng không hoạt động, vì vậy đây là những gì tôi đã nghĩ ra:

  • chuyển động - theo chiều kim đồng hồ
  • điểm - mỗi 6 độ (vì 360 độ chia cho 60 minuites là 6 độ)
  • chiều dài tay - 65 pixel
  • tâm - x = 75, y = 75

Vì vậy, công thức sẽ là

x=Cx+(r*cos(d/(180/PI))
y=Cy+(r*sin(d/(180/PI))

trong đó x và y là các điểm trên chu vi của một vòng tròn, Cx và Cy là tọa độ x, y của tâm, r là bán kính và d là lượng độ.


2

Đây là cách triển khai c #. Phương pháp này sẽ trở lại với điểm tròn mà mất radius, centerangle intervalnhư tham số. Góc được chuyển là Radian.

public static List<PointF> getCircularPoints(double radius, PointF center, double angleInterval)
        {
            List<PointF> points = new List<PointF>();

            for (double interval = angleInterval; interval < 2 * Math.PI; interval += angleInterval)
            {
                double X = center.X + (radius * Math.Cos(interval));
                double Y = center.Y + (radius * Math.Sin(interval));

                points.Add(new PointF((float)X, (float)Y));
            }

            return points;
        }

và ví dụ gọi:

List<PointF> LEPoints = getCircularPoints(10.0f, new PointF(100.0f, 100.0f), Math.PI / 6.0f);

Cẩn thận rằng điều này có thể trả lại ít hơn 1 mặt hàng so với dự kiến ​​do lỗi làm tròn! Do đó, tôi đã thêm một số maring để cuối cùng tôi nhận được số lượng mục chính xác (ví dụ của tôi có float thay vì gấp đôi); for (float khoảng = angleInterval; khoảng <2 * Math.PI + 0,0000099f; khoảng + = angleInterval)
sommmen

1

Tôi muốn chia sẻ những đóng góp của bạn ở trên đã giúp tôi sản xuất la bàn LCD Arduino như thế nào. Tôi hy vọng đây là nghi thức phù hợp ... Tôi vừa tham gia stackoverflow nên tôi có thể cảm ơn các bạn tốt.

Trong khi đứng trên vai những người khổng lồ hình học ở trên, tôi đã có thể tạo ra la bàn mẫu này: la bàn Arduino TFT với nhiều vòng bi

Mã cho hàm mà tôi đã gọi nhiều lần (đối với các vòng bi khác nhau mà bạn nhìn thấy trong văn bản màu vàng nhỏ) được viết bằng Arduino (giống như "C") ... và khá dễ dịch:

void PaintCompassNeedle( int pBearingInDegrees, int pRadius, TSPoint pCentrePt ) {
    // ******************************************************************************
    // * Formula for finding pointX on the circle based on degrees around the circle:
    // * x_oncircle = x_origin + radius * cos (degrees * pi / 180)  
    // * y_oncircle = y_origin - radius * sin (degrees * pi / 180) //minus explained
    // * Thanks to folks at stackoverflow...standing on the shoulders of giants. :) 

    float bearingInRads = (pBearingInDegrees) * PI / 180; 
    // Degrees vs Rads...The math folks use Rads in their formulas

    // *******************************************************************
    // * bearingPt is the point on the circle that we are trying to find
    TSPoint bearingPt;
    // Find the X on the circle starting with orgin (centre)
    bearingPt.x = pCentrePt.x + pRadius * sin(bearingInRads); 
    // Notice the "minus" R * cos()...because TFT the y is upside down bearingPt.y = 
    pCentrePt.y - pRadius * cos(bearingInRads); 
    // * Extra Explanation: The TFT is the graphical display I'm using and it
    // * calculates x & y from the top left of screen (portrait mode) as (0,0)
    // * ...so by Subtracting from the Y orgin...I flip it vertically
    // * Other folks using x,y as increasing to the right and up respectively
    // * would keep the plus sign after the pCentrePt.y
    // *************************************************************************

    // ***************************************************************
    // * This part will change for the final product...but leaving
    // * it because when call numerous times it shows it working for
    // * a number of different quadrants (displaying yellow degrees text)
    tft.fillCircle( bearingPt.x, bearingPt.y, 5, RED); 
    tft.setCursor( bearingPt.x, bearingPt.y );
    tft.setTextSize( 1 );
    tft.setTextColor( YELLOW );
    tft.print( pBearingInDegrees );

    TSPoint innerPt;
    innerPt.x = pCentrePt.x + pRadius/2 * sin(bearingInRads);
    innerPt.y = pCentrePt.y - pRadius/2 * cos(bearingInRads);
    tft.drawLine(innerPt.x, innerPt.y, bearingPt.x, bearingPt.y, RED);

}

0

Câu trả lời phải hoàn toàn ngược lại.

X = Xc + rSin (góc)

Y = Yc + rCos (góc)

trong đó Xc và Yc là tọa độ tâm của đường tròn và r là bán kính.


0

Giới thiệu:

 public static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 
pivot, Vector3 angles)
    {
	    return Quaternion.Euler(angles) * (point - pivot) + pivot;
    }


-3

Bạn có thể sử dụng cái này:

Phương trình của đường tròn trong đó

(xk) 2 + (yv) 2 = R 2

trong đó k và v không đổi và R là bán kính

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.