2009-09-24 10 views
6

Hej, próbuję obliczyć wierzchołki obróconego prostokąta (2D).Obliczanie wierzchołków obróconego prostokąta

To proste, jeśli prostokąt nie został obrócony, wymyśliłem tę część.

Jeśli prostokąt został obrócony, pomyślałem o dwóch możliwych sposobach obliczania wierzchołków. 1) Dowiedz się, jak przekształcić wierzchołki z przestrzeni lokalnej/obiektowej/modelu (te, które znalazłem poniżej) w przestrzeń światową. Szczerze mówiąc nie mam pojęcia, a jeśli to jest najlepszy sposób, to czuję, że wiele się z tego nauczyłbym, gdybym mógł to rozgryźć ...

2) Użyj trig, aby w jakiś sposób dowiedzieć się, gdzie znajdują się punkty końcowe prostokąt są względem położenia prostokąta w przestrzeni świata. W ten sposób próbowałem do tej pory, po prostu nie wiem, jak.

Oto funkcja, która oblicza wierzchołki do tej pory, dzięki za wszelką pomoc

void Rect::calculateVertices() 
{ 
    if(m_orientation == 0) // if no rotation 
    { 
     setVertices(
     &Vertex((m_position.x - (m_width/2) * m_scaleX), (m_position.y + (m_height/2) * m_scaleY), m_position.z), 
     &Vertex((m_position.x + (m_width/2) * m_scaleX), (m_position.y + (m_height/2) * m_scaleY), m_position.z), 
     &Vertex((m_position.x + (m_width/2) * m_scaleX), (m_position.y - (m_height/2) * m_scaleY), m_position.z), 
     &Vertex((m_position.x - (m_width/2) * m_scaleX), (m_position.y - (m_height/2) * m_scaleY), m_position.z)); 
    } 
    else 
    { 
     // if the rectangle has been rotated.. 
    } 

    //GLfloat theta = RAD_TO_DEG(atan(((m_width/2) * m_scaleX)/((m_height/2) * m_scaleY))); 
    //LOG->writeLn(&theta); 

} 

Odpowiedz

16

Chciałbym po prostu przekształcić każdy punkt, stosując tę ​​samą macierz obrotu dla każdego z nich. Jeśli jest to płaska 2D rotacji będzie wyglądać następująco:

x' = x*cos(t) - y*sin(t) 
y' = x*sin(t) + y*cos(t) 

gdzie (x, y) są pierwotne punkty, (x „y”) są obrócone współrzędnych, a T jest kąt mierzony w radiany z osi X. Obrót odbywa się w kierunku przeciwnym do ruchu wskazówek zegara, zgodnie z opisem.

Moja rekomendacja to zrobić to na papierze tylko raz. Narysuj prostokąt, obliczyć nowe współrzędne i przerysuj prostokąt, aby upewnić się, że jest poprawny przed rozpoczęciem kodowania. Następnie użyj tego przykładu jako testu jednostkowego, aby upewnić się, że został poprawnie zakodowany.

+1

+1 - Wolę odwrócić się i wykonać jakąkolwiek pracę, co uprości życie. –

+2

W ten sposób można uzyskać tylko wykonując 2 operacje trig (jeśli przechowujesz wyniki 'cos (t)' i 'sin (t)' przed obliczeniem jakichkolwiek obróconych wierzchołków). – jnylen

+0

Jak ten wzór miałby obracać się zgodnie z ruchem wskazówek zegara? –

2

Myślę, że jesteś na dobrej drodze, używając atan() do zwrócenia kąta. Jednak chcesz przekazać height podzielone przez width zamiast na odwrót. Da to domyślny (nieobrotowy) kąt do górnego prawego wierzchołka prostokąta. Powinieneś być w stanie zrobić resztę tak:

// Get the original/default vertex angles 
GLfloat vertex1_theta = RAD_TO_DEG(atan(
      (m_height/2 * m_scaleY) 
      /(m_width/2 * m_scaleX))); 
GLfloat vertex2_theta = -vertex1_theta; // lower right vertex 
GLfloat vertex3_theta = vertex1_theta - 180; // lower left vertex 
GLfloat vertex4_theta = 180 - vertex1_theta; // upper left vertex 

// Now get the rotated vertex angles 
vertex1_theta += rotation_angle; 
vertex2_theta += rotation_angle; 
vertex3_theta += rotation_angle; 
vertex4_theta += rotation_angle; 

//Calculate the distance from the center (same for each vertex) 
GLfloat r = sqrt(pow(m_width/2*m_scaleX, 2) + pow(m_height/2*m_scaleY, 2)); 

/* Calculate each vertex (I'm not familiar with OpenGL, DEG_TO_RAD 
* might be a constant instead of a macro) 
*/ 
vertexN_x = m_position.x + cos(DEG_TO_RAD(vertexN_theta)) * r; 
vertexN_y = m_position.y + sin(DEG_TO_RAD(vertexN_theta)) * r; 

// Now you would draw the rectangle, proceeding from vertex1 to vertex4. 

oczywiście bardziej rozwlekłości niż to konieczne, dla jasności. Oczywiście rozwiązanie duffymo za pomocą macierzy transformacji jest prawdopodobnie bardziej eleganckie i wydajne :)

EDIT: Teraz mój kod powinien zadziałać. Zmieniłem (width/height) na (height/width) i wykorzystałem stały promień ze środka prostokąta do obliczenia wierzchołków. Działający kod Pythona (żółwia) pod numerem http://pastebin.com/f1c76308c

+0

DEG_TO_RAD to makro, które napisałem. –

Powiązane problemy