Encuentre el punto en un círculo con un punto central, radio y grado dados

82

Han pasado 10 años desde que hice alguna matemática como esta ... Estoy programando un juego en 2D y moviendo a un jugador. Mientras muevo el reproductor, estoy tratando de calcular el punto en un círculo a 200 píxeles de la posición del jugador dado un ángulo (grados) positivo O negativo entre -360 y 360. La pantalla es de 1280x720 con 0,0 como el punto central de la pantalla. El jugador se mueve alrededor de todo este sistema de coordenadas cartesianas. El punto que intento encontrar puede estar fuera de la pantalla.

Probé las fórmulas del artículo Encuentra el punto con radio y ángulo, pero no creo que entienda qué es "Ángulo" porque obtengo resultados extraños cuando paso Ángulo como -360 a 360 en un Cos (ángulo) o Sin (ángulo).

Entonces, por ejemplo, tengo ...

  • 1280x720 en un plano cartesiano
  • Punto central (la posición del jugador):
    • sea ​​x = un número entre un mínimo de -640 y un máximo de 640
    • sea ​​y = un número entre un mínimo de -360 y un máximo de 360
  • Radio del círculo alrededor del jugador: sea r siempre = 200
  • Ángulo: sea a = un número dado entre -360 y 360 (permita que el negativo apunte hacia abajo o el positivo para apuntar hacia arriba para que -10 y 350 den la misma respuesta)

¿Cuál es la fórmula para devolver X en el círculo?

¿Cuál es la fórmula para devolver Y en el círculo?

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Kyle Anderson
fuente
16
¡¡¡Esta es una buena pregunta!!! +1
FrostyFire
1
Pregunta: ¿La mayoría de los juegos no tienen coordenadas en la parte superior izquierda a 0,0? y el eje y baja, no sube?
Persijn

Respuestas:

73

Las ecuaciones simples de su enlace dan las coordenadas X e Y del punto en el círculo en relación con el centro del círculo .

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

Esto le dice qué tan lejos está el punto del centro del círculo. Dado que tiene las coordenadas del centro (Cx, Cy), simplemente agregue el desplazamiento calculado.

Las coordenadas del punto en el círculo son:

X = Cx + (r * cosine(angle))  
Y = Cy + (r * sine(angle))
yoozer8
fuente
1
Mi confusión fue primero en la diferencia entre ÁNGULO y GRADO. Pensé que eran lo mismo. Luego pensé que estaba obteniendo el punto (x, y) en el plano, pero en realidad estaba obteniendo la longitud de los lados de xey. Lo dibujé en papel y luego lo puse en Excel para cubrir el rango de grados para verificar las fórmulas. Funciona ahora en mi código.
Kyle Anderson
3
¿No debería X = xcircle + (r * sine(angle))ser X = xcircle + (r * cosine(angle))(y viceversa para Y)?
txtechhelp
4
¡Observe que el ángulo debe ser un valor en radianes!
Roman M
17

Debes publicar el código que estás usando. Eso ayudaría a identificar el problema con exactitud.

Sin embargo, dado que mencionaste medir tu ángulo en términos de -360 a 360, probablemente estés usando las unidades incorrectas para tu biblioteca matemática. La mayoría de las implementaciones de funciones de trigonometría utilizan radianes para su entrada. Y si usa grados en su lugar ... sus respuestas serán extrañamente incorrectas.

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

Tenga en cuenta que también puede encontrarse con circunstancias en las que el cuadrante no sea el esperado. Esto se puede solucionar seleccionando cuidadosamente dónde está el ángulo cero, o verificando manualmente el cuadrante que espera y aplicando sus propios signos a los valores de resultado.

Seth Battin
fuente
1
Realmente debería ser un comentario más que una respuesta. Sin embargo, buena captura en radianes frente a grados.
yoozer8
Pregunta de publicación de zombies: en parens, ¿es así (deg * (pi / 180))o al revés ((deg * pi) / 180)? También gracias por especificar la diferencia entre rad vs deg.
Monsto
@monsto zombies todavía envía notificaciones. :). Los parens internos no importan porque la multiplicación y la división son demostraciones conmutativas . Wolfram.com/… . Durante mucho tiempo soy culpable de poner paréntesis excesivos en mi código. Finjo que es para mayor claridad, pero claramente eso no es estrictamente cierto, o no te habría molestado.
Seth Battin
6

Sugiero usar matrices para este tipo de manipulaciones. Es el enfoque más genérico, vea el ejemplo a continuación:

// 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); 
  • Nota al margen, la convención es medir el ángulo en sentido antihorario desde la forma inicial (positiva) del eje X
Johan Larsson
fuente
5

Obtengo resultados extraños cuando paso el ángulo como -360 a 360 en un Cos (ángulo) o Sin (ángulo).

Creo que la razón por la que su intento no funcionó es que estaba pasando ángulos en grados. Las funciones trigonométricas siny cosesperan ángulos expresados ​​en radianes, por lo que los números deben ser de 0a 2*M_PI. Para dgrados pasas M_PI*d/180.0. M_PIes una constante definida en el math.hencabezado.

Sergey Kalinichenko
fuente
Pensé que el ángulo y el grado probablemente no eran lo mismo, así que ¿estoy en lo correcto al decir Angle = M_PI * d / 180.0 donde d puede ser un número de -360 a 360 o necesito otro paso?
Kyle Anderson
1
@Kyle des de 0a 360o de -180a 180(un círculo completo), no de -360a 360(dos círculos completos).
Sergey Kalinichenko
4

También necesitaba esto para formar el movimiento de las manecillas de un reloj en código. Probé varias fórmulas pero no funcionaron, así que esto es lo que se me ocurrió:

  • movimiento - en sentido horario
  • puntos - cada 6 grados (porque 360 ​​grados divididos por 60 minutos son 6 grados)
  • longitud de la mano - 65 píxeles
  • centro - x = 75, y = 75

Entonces la fórmula sería

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

donde xey son los puntos en la circunferencia de un círculo, Cx y Cy son las coordenadas x, y del centro, r es el radio y d es la cantidad de grados.

Espeluznante
fuente
2

Aquí está la implementación de c #. El método devolverá los puntos circulares que toma radius, centery angle intervalcomo parámetro. El ángulo se pasa como 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;
        }

y el ejemplo de llamada:

List<PointF> LEPoints = getCircularPoints(10.0f, new PointF(100.0f, 100.0f), Math.PI / 6.0f);
MARYLAND. Nazmul Kibria
fuente
¡TENGA EN CUENTA que esto podría devolver 1 artículo menos de lo esperado debido a errores de redondeo! Por lo tanto, agregué un poco de marcado para obtener la cantidad correcta de elementos al final (mi ejemplo tiene flotadores en lugar de dobles); para (intervalo flotante = angleInterval; intervalo <2 * Math.PI + 0.0000099f; intervalo + = angleInterval)
sommmen
1

Quería compartir cómo sus contribuciones anteriores me ayudaron a producir una brújula LCD Arduino. Espero que esta sea la etiqueta correcta ... Me acabo de unir a stackoverflow para poder agradecerles a todos.

Mientras estaba de pie sobre los hombros de los gigantes de la geometría de arriba, pude producir esta brújula de muestra: brújula Arduino TFT con múltiples cojinetes

El código para la función que llamé repetidamente (para diferentes rodamientos que ves en un pequeño texto amarillo) está escrito en Arduino (algo así como "C") ... y es bastante traducible:

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);

}
TomOfMilton
fuente
0

La respuesta debería ser exactamente la opuesta.

X = Xc + rSin (ángulo)

Y = Yc + rCos (ángulo)

donde Xc e Yc son las coordenadas del centro del círculo y r es el radio.

Aditya Aggarwal
fuente
0

Recomendar:

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

niño
fuente
-3

Puedes usar esto:

Ecuación del círculo donde

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

donde k y v son constantes y R es el radio

Jaehoon
fuente