web-dev-qa-db-fra.com

Trouvez le point sur un cercle avec un centre, un rayon et un degré donnés

Cela fait 10 ans que je n'ai pas fait de maths comme ça ... Je programme un jeu en 2D et je déplace un joueur. Lorsque je déplace le joueur, je tente de calculer le point sur un cercle situé à 200 pixels de la position du joueur, en prenant un angle négatif OR positif (degré) compris entre -360 et 360. L’écran affiche 1280x720 avec 0,0 être le point central de l'écran. Le joueur tourne autour de tout ce système de coordonnées cartésien. Le point que j'essaie de trouver peut être hors écran. 

J'ai essayé les formules de l'article Trouvez le point avec le rayon et l'angle mais je ne crois pas comprendre ce qu'est "Angle" parce que j'obtiens des résultats étranges lorsque je passe Angle de -360 à 360 en Cos ( angle) ou Sin (angle).

Donc, par exemple, j'ai ...

  • 1280x720 sur un plan cartésien 
  • Point central (la position du joueur):
    • soit x = un nombre entre minimum -640 et maximum 640
    • soit y = un nombre compris entre minimum -360 et maximum 360 
  • Rayon de cercle autour du joueur: Soit toujours r = 200 
  • Angle: Soit a = un nombre donné entre -360 et 360 (permet à négatif de pointer vers le bas ou positif de pointer vers le haut pour que -10 et 350 donnent la même réponse)

Quelle est la formule pour retourner X sur le cercle?

Quelle est la formule pour retourner Y sur le cercle?

enter image description hereenter image description here

71
Kyle Anderson

Les équations simples de votre lien donnent les coordonnées X et Y du point sur le cercle par rapport au centre du cercle .

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

Cela vous indique à quelle distance le point est décalé du centre du cercle. Puisque vous avez les coordonnées du centre (Cx, Cy), ajoutez simplement le décalage calculé.

Les coordonnées du point sur le cercle sont:

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

Vous devriez poster le code que vous utilisez. Cela aiderait à identifier le problème exactement.

Cependant, puisque vous avez mentionné la mesure de votre angle en termes de -360 à 360, vous utilisez probablement les unités incorrectes pour votre bibliothèque mathématique. La plupart des implémentations de fonctions de trigonométrie utilisent des radians pour leur entrée. Et si vous utilisez des diplômes à la place ... vos réponses seront étrangement fausses.

x_oncircle = x_Origin + 200 * cos (degrees * pi / 180)
y_oncircle = y_Origin + 200 * sin (degrees * pi / 180)

Notez que vous pouvez également rencontrer des cas où le quadrant n'est pas ce que vous attendez. Cela peut être corrigé en choisissant avec soin l'emplacement de l'angle zéro ou en cochant manuellement le quadrant souhaité et en appliquant vos propres signes aux valeurs obtenues.

10
Seth Battin

Je suggère fortement d'utiliser des matrices pour ce type de manipulations. C'est l'approche la plus générique, voir exemple ci-dessous:

// 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); 
  • Remarque secondaire, la convention est de mesurer l'angle sous forme d'axe X positif dans le sens anti-horaire 
6
Johan Larsson

J'avais aussi besoin de cela pour former le mouvement des aiguilles d'une horloge en code. J'ai essayé plusieurs formules mais elles n'ont pas fonctionné. Voici donc ce que j'ai trouvé:

  • mouvement - dans le sens des aiguilles d'une montre
  • points - tous les 6 degrés (parce que 360 ​​degrés divisés par 60 minuites est 6 degrés)
  • longueur de la main - 65 pixels
  • centre - x = 75, y = 75

Donc, la formule serait

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

où x et y sont les points de la circonférence d'un cercle, Cx et Cy sont les coordonnées x, y du centre, r le rayon et d la quantité de degrés.

4
Wraithious

J'obtiens des résultats étranges lorsque je passe Angle de -360 à 360 en Cos (angle) ou Sin (angle).

Je pense que votre tentative n'a pas fonctionné parce que vous passiez des angles en degrés. Les fonctions trigonométriques sin et cos attendent des angles exprimés en radians. Les nombres doivent donc être compris entre 0 et 2*M_PI. Pour d degrés, vous passez M_PI*d/180.0. M_PI est une constante définie dans l'en-tête math.h.

4
dasblinkenlight

Je voulais partager comment vos contributions ci-dessus m'ont aidé à produire un compas Arduino LCD. J'espère que c'est la bonne étiquette ... Je viens de rejoindre stackoverflow afin de pouvoir vous remercier, bons amis.

En me tenant sur les épaules des géants de la géométrie ci-dessus, j'ai pu produire cet exemple de compas: Compas Arduino TFT avec plusieurs relèvements

Le code de la fonction que j'ai appelée à plusieurs reprises (pour différents roulements que vous voyez en minuscule texte jaune) est écrit en Arduino (un peu comme "C") ... et peut être traduit facilement:

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

}
1
TomOfMilton

Voici l'implémentation c #. La méthode renverra les points circulaires dont le paramètre est radius, center et angle interval. Angle est passé comme 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;
        }

et l'exemple d'appelant:

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

Recommander:

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

0
kid

La réponse devrait être exactement opposée.

X = Xc + rSin (angle)

Y = Yc + rCos (angle)

où Xc et Yc sont les coordonnées du centre du cercle et r le rayon.

0
Aditya Aggarwal