Een punt rond een ander punt draaien (2D)

Ik probeer een kaartspel te maken waarbij de kaarten uitwaaieren. Om het nu weer te geven, gebruik ik de Allegro API die een functie heeft:

al_draw_rotated_bitmap(OBJECT_TO_ROTATE,CENTER_X,CENTER_Y,X
        ,Y,DEGREES_TO_ROTATE_IN_RADIANS);

dus hiermee kan ik mijn fan-effect gemakkelijk maken. Het probleem is dan te weten welke kaart er onder de muis zit. Om dit te doen, dacht ik aan een polygoonbotsingstest. Ik weet alleen niet zeker hoe ik de 4 punten op de kaart moet draaien om de veelhoek te vormen. Ik moet eigenlijk dezelfde bewerking uitvoeren als Allegro.

de 4 punten van de kaart zijn bijvoorbeeld:

card.x
card.y
card.x + card.width
card.y + card.height

Ik zou een functie nodig hebben zoals:

POINT rotate_point(float cx,float cy,float angle,POINT p)
{
}

Bedankt


Antwoord 1, autoriteit 100%

Trek eerst het draaipunt (cx,cy)af, draai het dan en voeg het punt opnieuw toe.

Niet getest:

POINT rotate_point(float cx,float cy,float angle,POINT p)
{
  float s = sin(angle);
  float c = cos(angle);
  // translate point back to origin:
  p.x -= cx;
  p.y -= cy;
  // rotate point
  float xnew = p.x * c - p.y * s;
  float ynew = p.x * s + p.y * c;
  // translate point back:
  p.x = xnew + cx;
  p.y = ynew + cy;
  return p;
}

Antwoord 2, autoriteit 21%

Als je het punt (px, py)rond het punt (ox, oy)draait met de hoek theta, krijg je:

p'x = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox

p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy

dit is een gemakkelijke manier om een punt in 2D te roteren.


Antwoord 3, autoriteit 18%

Het coördinatensysteem op het scherm is linkshandig, d.w.z. de x-coördinaat neemt toe van links naar rechts en de y-coördinaat neemt toe van boven naar beneden. De oorsprong, O(0, 0) bevindt zich in de linkerbovenhoek van het scherm.

Een met de klok meerotatie rond de oorsprongvan een punt met coördinaten (x, y) wordt gegeven door de volgende vergelijkingen:

waarbij (x’, y’) de coördinaten zijn van het punt na rotatie en hoek theta, de rotatiehoek (moet in radialen zijn, d.w.z. vermenigvuldigd met: PI / 180).

Om een rotatie rond een ander punt dan de oorsprong O(0,0) uit te voeren, laten we zeggen punt A(a, b) (draaipunt). Eerst vertalen we het te roteren punt, d.w.z. (x, y) terug naar de oorsprong, door de coördinaten van het draaipunt (x – a, y – b) af te trekken.
Dan voeren we de rotatie uit en krijgen de nieuwe coördinaten (x’, y’) en tenslotte vertalen we het punt terug, door de coördinaten van het draaipunt op te tellen bij de nieuwe coördinaten (x’ + a, y’ + b).

Volgens de bovenstaande beschrijving:

een 2D rechtsom theta gradenrotatie van punt (x, y)rond punt (a, b)is:

Uw functie-prototype gebruiken: (x, y) -> (p.x, p.y); (a, b) -> (cx, cy); theta -> hoek:

POINT rotate_point(float cx, float cy, float angle, POINT p){
     return POINT(cos(angle) * (p.x - cx) - sin(angle) * (p.y - cy) + cx,
                  sin(angle) * (p.x - cx) + cos(angle) * (p.y - cy) + cy);
}

Antwoord 4, Autoriteit 9%

float s = sin(angle); // angle is in radians
float c = cos(angle); // angle is in radians

Voor de klok in rotatie:

float xnew = p.x * c + p.y * s;
float ynew = -p.x * s + p.y * c;

Voor tegen de klok in rotatie:

float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;

Antwoord 5

Dit is het antwoord van Nils Pipenbrinck, maar geïmplementeerd in C # Fiddle.

https://dotnetfidddle.net/btmjlg

using System;
public class Program
{
    public static void Main()
    {   
        var angle = 180 * Math.PI/180;
        Console.WriteLine(rotate_point(0,0,angle,new Point{X=10, Y=10}).Print());
    }
    static Point rotate_point(double cx, double cy, double angle, Point p)
    {
        double s = Math.Sin(angle);
        double c = Math.Cos(angle);
        // translate point back to origin:
        p.X -= cx;
        p.Y -= cy;
        // rotate point
        double Xnew = p.X * c - p.Y * s;
        double Ynew = p.X * s + p.Y * c;
        // translate point back:
        p.X = Xnew + cx;
        p.Y = Ynew + cy;
        return p;
    }
    class Point
    {
        public double X;
        public double Y;
        public string Print(){
            return $"{X},{Y}";
        }
    }
}

Ps: blijkbaar kan ik niet reageren, dus ik ben verplicht om het als antwoord te posten …


Antwoord 6

Ik worstelde tijdens het werken met MS OCR Read API die de rotatiehoek teruggeeft binnen het bereik (-180, 180]. Dus ik moet een extra stap doen om negatieve hoeken om te zetten in positief. Ik hoop dat iemand worstelt met puntrotatie met negatief of positieve hoeken kunnen het volgende gebruiken.

def rotate(origin, point, angle):
    """
    Rotate a point counter-clockwise by a given angle around a given origin.
    """
    # Convert negative angles to positive
    angle = normalise_angle(angle)
    # Convert to radians
    angle = math.radians(angle)
    # Convert to radians
    ox, oy = origin
    px, py = point
    # Move point 'p' to origin (0,0)
    _px = px - ox
    _py = py - oy
    # Rotate the point 'p' 
    qx = (math.cos(angle) * _px) - (math.sin(angle) * _py)
    qy = (math.sin(angle) * _px) + (math.cos(angle) * _py)
    # Move point 'p' back to origin (ox, oy)
    qx = ox + qx
    qy = oy + qy
    return [qx, qy]
def normalise_angle(angle):
    """ If angle is negative then convert it to positive. """
    if (angle != 0) & (abs(angle) == (angle * -1)):
        angle = 360 + angle
    return angle

Other episodes