Dati un angolo e dimensioni, trova una coordinata lungo il perimetro di un rettangolo

StackOverflow https://stackoverflow.com/questions/1026763

  •  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.

È stato utile?

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.

alt text

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:

  1. Un raggio dal centro di rotazione nell'angolo desiderato
  2. 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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top