Étant donné un angle et des dimensions, trouvez une coordonnée le long du périmètre d'un rectangle.

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

  •  06-07-2019
  •  | 
  •  

Question

J'écris un script dans lequel les icônes tournent autour d'un pivot (ou d'une origine) donné. J'ai réussi à faire fonctionner cette icône en faisant pivoter les icônes autour d'une ellipse, mais je souhaite également qu'elles se déplacent autour du rectangle d'un rectangle d'une certaine largeur, hauteur et origine.

Je le fais de cette façon parce que mon code actuel stocke tous les coordonnées dans un tableau avec chaque angle entier comme clé et qu'il serait beaucoup plus facile de réutiliser ce code.

Si quelqu'un pouvait me donner un exemple de rectangle de 100 x 150, ce serait formidable.

MODIFIER: , pour préciser, par rotation, j'entends le déplacement autour du périmètre (ou la rotation) d'une forme.

Était-ce utile?

La solution

Vous connaissez la taille du rectangle et vous devez diviser l’intervalle des angles en quatre afin que vous sachiez si un rayon du centre du rectangle se croise à droite, en haut, à gauche ou en bas du rectangle.

Si l'angle est: -atan (d / w) < alfa < atan (d / w), le rayon coupe le côté droit du rectangle. Puis, puisque vous savez que le déplacement x du centre du rectangle au côté droit est d / 2, le déplacement dy divisé par d / 2 est bronzé (alfa), donc

dy = d / 2 * tan (alpha)

Vous devriez gérer cela de la même manière avec les trois autres intervalles angulaires.

Ok, c'est parti. Vous avez un rect de largeur w et de profondeur d. Au milieu, vous avez le point central, cp. Je suppose que vous voulez calculer P, pour différentes valeurs de l’angle alfa.

alt text

J'ai divisé le rectangle en quatre zones ou intervalles angulaires différents (1 à 4). L'intervalle que j'ai mentionné ci-dessus est le premier à droite. J'espère que cela a du sens pour vous.

Tout d'abord, vous devez calculer les intervalles d'angle. Ils sont complètement déterminés par w et d. En fonction de la valeur alfa, calculez P en conséquence, c'est-à-dire si le rayon & "; > quot; de CP à P coupe les côtés supérieur, inférieur, droit ou gauche du rectangle.

A bientôt

Autres conseils

Ceci a été conçu et vérifié pour fonctionner sur la montre intelligente Pebble, mais modifié pour devenir un pseudocode:

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

Une façon simple de faire cela en utilisant un angle en tant que paramètre consiste à couper les valeurs X et Y en utilisant les limites du rectangle. En d’autres termes, calculez la position comme si l’icône tournait autour d’un tracé circulaire ou elliptique, puis appliquez ceci:

(En supposant un rectangle aligné sur l'axe et centré sur (0,0), avec la longueur de l'axe X de XAxis et la longueur de l'axe Y de YAxis):

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;

Le problème avec cette approche est que l'angle ne sera pas tout à fait précis et que la vitesse le long du périmètre du rectangle ne sera pas constante. La modélisation d'une ellipse qui calcule le rectangle à ses angles peut minimiser cet effet, mais si vous recherchez une orbite lisse à vitesse constante, & "; Orbite, &"; cette méthode ne sera pas adéquate.

Si vous voulez dire tourner comme la terre tourne autour du soleil (pas l'auto-rotation ... alors votre question concerne la manière de glisser le long des bords d'un rectangle?)

Si oui, vous pouvez essayer ceci:

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

Mise à jour: (voir le commentaire ci-dessous)

pour utiliser un angle, une ligne sera

y / x = tan(th)       # th is the angle

les autres lignes sont simples car elles sont simplement horizontales ou verticales. Ainsi, par exemple, x = 50 et vous pouvez le mettre dans la ligne ci-dessus pour obtenir le y. faites-le pour l'intersection de la ligne horizontale et de la ligne verticale (par exemple, l'angle est de 60 degrés et il tire & "NorthEast &"; ... maintenant vous avez deux points. Ensuite, le point le plus proche de l’origine est celle qui frappe le rectangle en premier).

Utilisez une matrice de transformation 2D . De nombreux langages (Java, par exemple) supportent cela de manière native (recherchez AffineTransformation); sinon, écrivez une routine pour faire la rotation vous-même, une fois, bien la déboguer et l'utiliser pour toujours. Je dois en avoir cinq écrits dans différentes langues.

Une fois que vous pouvez effectuer la rotation simplement, recherchez l'emplacement sur le rectangle en effectuant line-line intersection . Recherchez le centre de l'icône en orbite en coupant deux lignes:

  1. Un rayon de votre centre de rotation à l'angle souhaité
  2. L'un des quatre côtés, délimité par l'angle souhaité (les quatre quadrants).

Dessinez vous-même un croquis sur une feuille de papier avec un rectangle et un centre de rotation. Commencez par traduire le rectangle au centre de l'origine de votre système de coordonnées (souvenez-vous des paramètres de traduction, vous devrez inverser la traduction ultérieurement). Faites pivoter le rectangle de sorte que ses côtés soient parallèles aux axes de coordonnées (même raison).

Vous avez maintenant un triangle avec un angle connu à l'origine, le côté opposé est de longueur connue (la moitié de la longueur d'un côté du rectangle) et vous pouvez maintenant:

- résolvez le triangle

- annuler la rotation

- annuler la traduction

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top