Dati un angolo e dimensioni, trova una coordinata lungo il perimetro di un rettangolo
-
06-07-2019 - |
Domanda
Sto scrivendo uno script in cui le icone ruotano attorno a un dato perno (o origine). Sono stato in grado di farlo funzionare per ruotare le icone attorno a un'ellisse, ma voglio anche farle muovere attorno al perimetro di un rettangolo di una certa larghezza, altezza e origine.
Lo sto facendo in questo modo perché il mio codice corrente memorizza tutti i coordini in un array con ogni angolo intero come chiave, e riutilizzare questo codice sarebbe molto più facile con cui lavorare.
Se qualcuno potesse darmi un esempio di un rettangolo 100x150, sarebbe fantastico.
MODIFICA: per chiarire, ruotando intorno intendo spostarmi attorno al perimetro (o in orbita) di una forma.
Soluzione
Conosci la dimensione del rettangolo e devi dividere l'intero intervallo angolare in quattro diversi, quindi sai se un raggio dal centro del rettangolo si interseca a destra, in alto, a sinistra o in fondo al rettangolo.
Se l'angolo è: -atan (d / w) < alfa < atan (d / w) il raggio interseca il lato destro del rettangolo. Quindi poiché sai che lo spostamento x dal centro del rettangolo al lato destro è d / 2, lo spostamento dy diviso per d / 2 è tan (alfa), quindi
dy = d / 2 * tan (alfa)
Lo gestiresti in modo simile con gli altri tre intervalli angolari.
Ok, ecco qui. Hai un rettangolo con larghezza w e profondità d. Nel mezzo hai il punto centrale, cp. Suppongo che tu voglia calcolare P, per diversi valori dell'angolo alfa.
Ho diviso il rettangolo in quattro diverse aree o intervalli angolari (da 1 a 4). L'intervallo che ho menzionato sopra è il primo a destra. Spero che questo abbia senso per te.
Per prima cosa devi calcolare gli intervalli angolari, questi sono determinati completamente da w e d. A seconda del valore di alfa, calcola P di conseguenza, cioè se il " raggio quot; da CP a P interseca i lati superiore, inferiore, destro o sinistro del rettangolo.
Saluti
Altri suggerimenti
Questo è stato creato e verificato per funzionare sullo smartwatch Pebble, ma modificato per essere pseudocodice:
struct GPoint {
int x;
int y;
}
// Return point on rectangle edge. Rectangle is centered on (0,0) and has a width of w and height of h
GPoint getPointOnRect(int angle, int w, int h) {
var sine = sin(angle), cosine = cos(angle); // Calculate once and store, to make quicker and cleaner
var dy = sin>0 ? h/2 : h/-2; // Distance to top or bottom edge (from center)
var dx = cos>0 ? w/2 : w/-2; // Distance to left or right edge (from center)
if(abs(dx*sine) < abs(dy*cosine)) { // if (distance to vertical line) < (distance to horizontal line)
dy = (dx * sine) / cosine; // calculate distance to vertical line
} else { // else: (distance to top or bottom edge) < (distance to left or right edge)
dx = (dy * cosine) / sine; // move to top or bottom line
}
return GPoint(dx, dy); // Return point on rectangle edge
}
Use:
rectangle_width = 100;
rectangle_height = 150;
rectangle_center_x = 300;
rectangle_center_y = 300;
draw_rect(rectangle_center_x - (rectangle_width/2), rectangle_center_y - (rectangle_center_h/2), rectangle_width, rectangle_height);
GPoint point = getPointOnRect(angle, rectangle_width, rectangle_height);
point.x += rectangle_center_x;
point.y += rectangle_center_y;
draw_line(rectangle_center_x, rectangle_center_y, point.x, point.y);
Un modo semplice per farlo usando un angolo come parametro è semplicemente tagliare i valori X e Y usando i limiti del rettangolo. In altre parole, calcola la posizione come se l'icona ruotasse attorno a un percorso circolare o ellittico, quindi applica questo:
(Supponendo che il rettangolo allineato agli assi sia centrato su (0,0), con la lunghezza dell'asse X dell'asse X e la lunghezza dell'asse Y dell'asse Y):
if (X > XAxis/2)
X = XAxis/2;
if (X < 0 - XAxis/2)
X = 0 - XAxis/2;
if (Y > YAxis/2)
Y = YAxis/2;
if (Y < 0 - YAxis/2)
Y = 0 - YAxis/2;
Il problema con questo approccio è che l'angolo non sarà del tutto accurato e la velocità lungo il perimetro del rettangolo non sarà costante. Modellare un'ellisse che oscilla il rettangolo ai suoi angoli può minimizzare l'effetto, ma se stai cercando un & Quot regolare, a velocità costante, orbita, & Quot; questo metodo non sarà adeguato.
Se pensi di voler dire ruotare come la terra ruota attorno al sole (non l'autorotazione ... quindi la tua domanda è su come scivolare lungo i bordi di un rettangolo?)
In tal caso, puoi provarlo:
# pseudo coode
for i = 0 to 499
if i < 100: x++
else if i < 250: y--
else if i < 350: x--
else y++
drawTheIcon(x, y)
Aggiornamento: (vedi commento sotto)
per usare un angolo, una linea sarà
y / x = tan(th) # th is the angle
le altre linee sono semplici poiché sono solo orizzontali o verticali. quindi, per esempio, è x = 50 e puoi inserirlo nella riga sopra per ottenere y. fallo per l'intersezione della linea orizzontale e della linea verticale (ad esempio, l'angolo è di 60 gradi e spara " NorthEast " ... ora hai due punti. Quindi il punto più vicino a l'origine è quella che colpisce per prima il rettangolo).
Utilizza una matrice di trasformazione 2D . Molte lingue (ad esempio Java) lo supportano in modo nativo (cercare AffineTransformation); altrimenti, scrivi una routine per eseguire la rotazione da solo, una volta, esegui il debug bene e usalo per sempre. Devo averne cinque scritte in diverse lingue.
Una volta che puoi fare semplicemente la rotazione, trova la posizione sul rettangolo facendo line-line intersezione . Trova il centro dell'icona orbita intersecando due linee:
- Un raggio dal centro di rotazione nell'angolo desiderato
- Uno dei quattro lati, delimitato dall'angolazione desiderata (i quattro quadranti).
Disegna uno schizzo su un pezzo di carta con un rettangolo e un centro di rotazione. Innanzitutto traduci il rettangolo in modo che sia centrato all'origine del tuo sistema di coordinate (ricorda i parametri di traduzione, dovrai invertire la traduzione in seguito). Ruota il rettangolo in modo che i suoi lati siano paralleli agli assi delle coordinate (stesso motivo).
Ora hai un triangolo con angolo noto all'origine, il lato opposto è di lunghezza nota (metà della lunghezza di un lato del rettangolo), e ora puoi:
- risolve il triangolo
- annulla la rotazione
- annulla la traduzione