Dado um ângulo e as dimensões, encontrar uma coordenada ao longo do perímetro de um rectângulo

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

  •  06-07-2019
  •  | 
  •  

Pergunta

Eu estou escrevendo um script onde os ícones girar em torno de um determinado pivô (ou origem). Eu tenho sido capaz de fazer este trabalho para girar os ícones em torno de uma elipse, mas eu também quero tê-los mover-se ao redor do perímetro de um retângulo de largura determinada, altura e origem.

Estou fazendo isso desta forma porque meu atual código Comércio todas as coordenadas em uma matriz com cada inteiro ângulo como a chave, e reutilizar este código seria muito mais fácil de trabalhar.

Se alguém pudesse me dar um exemplo de um retângulo 100x150, que seria ótimo.

EDIT:. para clarificar, por rotação em torno I significa movendo em torno do perímetro (ou orbita) de uma forma

Foi útil?

Solução

Você sabe o tamanho do rectângulo e você precisa dividir todo o intervalo do ângulo em quatro diferentes, assim você sabe se um raio a partir do centro dos cruza retângulo direita, de cima, esquerda ou inferior do retângulo.

Se o ângulo é: -atan (d / w)

dy = d / 2 * tan (alfa)

Você iria lidar com isso de modo semelhante com os outros intervalos de três ângulos.

Ok, aqui vai. Você tem um rect com largura w e d profundidade. No meio você tem o ponto central, cp. Eu suponho que você quer calcular P, para diferentes valores do alfa ângulo.

text alt

I dividiu o retângulo em quatro áreas diferentes, ou intervalos de ângulo (1 a 4). O intervalo eu mencionei acima é o primeiro para a direita. Espero que isso faz sentido para você.

Primeiro você precisa calcular os intervalos de ângulo, estes são determinados completamente por w e d. Dependendo do que o valor alfa tem, calcular P em conformidade, ou seja, se o "raio" da CP para cruza P o superior, inferior, lado direito ou esquerdo do retângulo.

Felicidades

Outras dicas

Isto foi feito para e verificado para o trabalho no smartwatch Pebble, mas modificado para ser pseudocódigo:

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

Uma maneira simples de fazer isso usando um ângulo como um parâmetro é simplesmente o clipe de valores X e Y usando os limites do retângulo. Em outras palavras, a posição de calcular como se o ícone irá girar em torno de um caminho circular ou elíptico, em seguida, aplicar o seguinte:

(Assumindo rectângulo alinhado ao eixo centrado em (0,0), com um comprimento de X-eixo de XAxis e comprimento do eixo Y do eixo 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;

O problema com esta abordagem é que o ângulo não vai ser totalmente correto e a velocidade ao longo do perímetro do retângulo não será constante. Modelagem de uma elipse que osculates o retângulo em seus cantos pode minimizar o efeito, mas se você está procurando um liso, de velocidade constante "órbita", este método não será adequada.

Se acha que girar média como a Terra gira ao redor do sol (não a auto-rotação ... então a sua pergunta é sobre como a deslizar ao longo das bordas de um retângulo?)

Se assim for, você pode tentar dar um presente:

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

Update: (veja comentário abaixo)

para usar um ângulo, uma linha será

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

as outras linhas são simples, uma vez que são apenas horizontal ou vertical. assim, por exemplo, é x = 50 e você pode colocar isso em linha acima para obter o y. fazer isso para a intersecção da linha horizontal e uma linha vertical (por exemplo, o ângulo é de 60 graus e atirar "Nordeste" ... agora você tem dois pontos. Então o ponto que está mais próximo da origem é aquele que atinge o retângulo primeiro).

Use a 2D matriz de transformação. Muitas línguas (por exemplo, Java) apoiar esta nativamente (olhar para cima AffineTransformation); caso contrário, escreva uma rotina para fazer a rotação mesmo, uma vez, depurá-lo bem, e usá-lo para sempre. I deve ter cinco deles escritos em linguagens diferentes.

Uma vez que você pode fazer a rotação simplesmente, encontrar a localização no retângulo fazendo -line linha cruzamento. Encontre o centro do ícone orbitado por interseção de duas linhas:

  1. Um raio a partir do seu centro de rotação no ângulo desejado
  2. Um dos quatro lados, delimitadas pelo ângulo que você quiser (os quatro quadrantes).

Desenhe-se um esboço em um pedaço de papel com um retângulo e um centro de rotação. Primeiro traduzir o retângulo ao centro na origem do seu sistema de coordenadas (lembre-se os parâmetros de tradução, você precisa reverter a tradução mais tarde). Rodar o rectângulo de modo a que os seus lados são paralelos aos eixos de coordenadas (mesma razão).

Agora você tem um triângulo com ângulo conhecido na origem, o lado oposto é de comprimento conhecido (a metade do comprimento de um lado do retângulo), e pode agora:

- resolver o triângulo

- desfazer a rotação

- desfazer a tradução

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top