Calculando a posição dos pontos em um círculo


87

Estou com a mente um pouco em branco sobre isso no momento. Eu tenho um problema em que preciso calcular a posição dos pontos em torno de um ponto central, presumindo que eles estão todos equidistantes do centro e uns dos outros.

O número de pontos é variável, então DrawCirclePoints(int x) tenho certeza de que há uma solução simples, mas pela minha vida, simplesmente não consigo ver :)


1
Todos deram ótimas respostas, muito rápido, então dei um visto na primeira resposta :) Todas foram ótimas :)
JoeBrown

Respostas:


72

Um ponto no ângulo theta no círculo cujo centro é (x0,y0)e cujo raio é ré (x0 + r cos theta, y0 + r sin theta). Agora escolha thetavalores uniformemente espaçados entre 0 e 2pi.


A pergunta clássica é o valor de pi 3,14 ou 180? (ou seja, o ângulo está em graus ou radianos?)
nirvanaswap

Definitivamente radianos. Se você usar graus, precisará de ângulos entre 0 e 360.
Gareth McCaughan

7
(O valor de pi é 3,14ish independentemente de como você prefere escrever ângulos, é claro. É o que é.)
Gareth McCaughan

87

Dado um comprimento de raio r e um ângulo t em radianos e o centro de um círculo (h, k) , você pode calcular as coordenadas de um ponto na circunferência da seguinte forma (este é um pseudocódigo, você terá que adaptá-lo ao seu língua):

float x = r*cos(t) + h;
float y = r*sin(t) + k;

Você inverteu as funções cos e sin devem ser sin para xe cos para y. Não o contrário.
Andreas de

18
Meu diploma em matemática, assim como todas as outras respostas aqui, dizem que você está incorreto.
Brian Driscoll de

2
Hm .. bem na wikipedia sueca diz que sin é o eixo x Eu sei que esta não é uma fonte segura, mas então usei sin em xe cos em y meu cubo começou a se mover na direção certa. Até meu professor de matemática disse que eu os invertei. Você consegue pensar em alguma outra razão pela qual meu cubo se moveria em um padrão estranho para longe do local de destino e então eu o virei e ele se move para sua posição?
Andreas

Este é o código que escrevi, talvez você possa dizer por que funciona com eles invertidos? jsfiddle.net/Lf5sZ
Andreas

3
Nas coordenadas da tela, o eixo y positivo é invertido, de modo que faz sentido.
Brian Driscoll

51

Aqui está uma solução usando C #:

void DrawCirclePoints(int points, double radius, Point center)
{
    double slice = 2 * Math.PI / points;
    for (int i = 0; i < points; i++)
    {
        double angle = slice * i;
        int newX = (int)(center.X + radius * Math.Cos(angle));
        int newY = (int)(center.Y + radius * Math.Sin(angle));
        Point p = new Point(newX, newY);
        Console.WriteLine(p);
    }
}

Saída de amostra de DrawCirclePoints(8, 10, new Point(0,0));:

{X=10,Y=0}
{X=7,Y=7}
{X=0,Y=10}
{X=-7,Y=7}
{X=-10,Y=0}
{X=-7,Y=-7}
{X=0,Y=-10}
{X=7,Y=-7}

Boa sorte!


1
Excelente! Funcionou muito bem para mim, já traduzi para php-cairo e funciona muito bem!
Melsi

procuro fazer o mesmo tipo de tarefa, porém a minha depende do Triggertrap / SeekArc · GitHub, quando um usuário move o polegar, quero colocar uma imagem para indicar aquele progresso selecionado da pessoa .... tudo o que tenho tentei me dar os pontos um pouco fora e não a
perfeição

9

Usando uma das respostas acima como base, aqui está o exemplo Java / Android:

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    RectF bounds = new RectF(canvas.getClipBounds());
    float centerX = bounds.centerX();
    float centerY = bounds.centerY();

    float angleDeg = 90f;
    float radius = 20f

    float xPos = radius * (float)Math.cos(Math.toRadians(angleDeg)) + centerX;
    float yPos = radius * (float)Math.sin(Math.toRadians(angleDeg)) + centerY;

    //draw my point at xPos/yPos
}

4

Colocando um número em um caminho circular

// variable

let number = 12; // how many number to be placed
let size = 260; // size of circle i.e. w = h = 260
let cx= size/2; // center of x(in a circle)
let cy = size/2; // center of y(in a circle)
let r = size/2; // radius of a circle

for(let i=1; i<=number; i++) {
  let ang = i*(Math.PI/(number/2));
  let left = cx + (r*Math.cos(ang));
  let top = cy + (r*Math.sin(ang));
  console.log("top: ", top, ", left: ", left);
}

3

Eu tive que fazer isso na web, então aqui está uma versão em coffeescript da resposta de @scottyab acima:

points = 8
radius = 10
center = {x: 0, y: 0}

drawCirclePoints = (points, radius, center) ->
  slice = 2 * Math.PI / points
  for i in [0...points]
    angle = slice * i
    newX = center.x + radius * Math.cos(angle)
    newY = center.y + radius * Math.sin(angle)
    point = {x: newX, y: newY}
    console.log point

drawCirclePoints(points, radius, center)

3

Solução PHP:

class point{
    private $x = 0;
    private $y = 0;
    public function setX($xpos){
        $this->x = $xpos;
    }
    public function setY($ypos){
        $this->y = $ypos;
    }
    public function getX(){
        return $this->x;
    }
    public function getY(){
        return $this->y;
    }
    public function printX(){
        echo $this->x;
    }
    public function printY(){
        echo $this->y;
    }
}
function drawCirclePoints($points, $radius, &$center){
    $pointarray = array();
    $slice = (2*pi())/$points;
    for($i=0;$i<$points;$i++){
        $angle = $slice*$i;
        $newx = (int)($center->getX() + ($radius * cos($angle)));
        $newy = (int)($center->getY() + ($radius * sin($angle)));
        $point = new point();
        $point->setX($newx);
        $point->setY($newy);
        array_push($pointarray,$point);
    }
    return $pointarray;
}

Eu acredito que o parêntese é incorreto para $newxe $newy, colocando as coordenadas maneira fora do raio do círculo. Experimente $newx = (int)($center->getX() + ($radius * cos($angle)));e semelhante para $newy.
Jason

2

Para fins de conclusão, o que você descreve como "posição de pontos em torno de um ponto central (assumindo que todos eles estão equidistantes do centro)" nada mais é que "Coordenadas polares". E você está pedindo maneira de converter entre coordenadas polares e cartesianas que é dada como x = r*cos(t), y = r*sin(t).


1

O ângulo entre cada um dos seus pontos será 2Pi/xentão você pode dizer que para os pontos n= 0 to x-1o ângulo de um ponto 0 definido é2nPi/x .

Supondo que seu primeiro ponto esteja em (r,0)(onde r é a distância do ponto central), então as posições relativas ao ponto central serão:

rCos(2nPi/x),rSin(2nPi/x)

1

Solução de trabalho em Java:

import java.awt.event.*;
import java.awt.Robot;

public class CircleMouse {

/* circle stuff */
final static int RADIUS = 100;
final static int XSTART = 500;
final static int YSTART = 500;
final static int DELAYMS = 1;
final static int ROUNDS = 5;

public static void main(String args[]) {

    long startT = System.currentTimeMillis();
    Robot bot = null;

    try {
        bot = new Robot();
    } catch (Exception failed) {
        System.err.println("Failed instantiating Robot: " + failed);
    }
    int mask = InputEvent.BUTTON1_DOWN_MASK;

    int howMany = 360 * ROUNDS;
    while (howMany > 0) {
        int x = getX(howMany);
        int y = getY(howMany);
        bot.mouseMove(x, y);
        bot.delay(DELAYMS);
        System.out.println("x:" + x + " y:" + y);
        howMany--;
    }

    long endT = System.currentTimeMillis();
    System.out.println("Duration: " + (endT - startT));

}

/**
 * 
 * @param angle
 *            in degree
 * @return
 */
private static int getX(int angle) {
    double radians = Math.toRadians(angle);
    Double x = RADIUS * Math.cos(radians) + XSTART;
    int result = x.intValue();

    return result;
}

/**
 * 
 * @param angle
 *            in degree
 * @return
 */
private static int getY(int angle) {
    double radians = Math.toRadians(angle);
    Double y = RADIUS * Math.sin(radians) + YSTART;
    int result = y.intValue();

    return result;
}
}

1

Aqui está uma Rversão baseada na resposta @Pirijan acima.

points <- 8
radius <- 10
center_x <- 5
center_y <- 5

drawCirclePoints <- function(points, radius, center_x, center_y) {
  slice <- 2 * pi / points
  angle <- slice * seq(0, points, by = 1)

  newX <- center_x + radius * cos(angle)
  newY <- center_y + radius * sin(angle)

  plot(newX, newY)
}

drawCirclePoints(points, radius, center_x, center_y)

1

Aqui está como descobri um ponto em um círculo com javascript, calculando o ângulo (grau) a partir do topo do círculo.

  const centreX = 50; // centre x of circle
  const centreY = 50; // centre y of circle
  const r = 20; // radius
  const angleDeg = 45; // degree in angle from top
  const radians = angleDeg * (Math.PI/180);
  const pointY = centreY - (Math.cos(radians) * r); // specific point y on the circle for the angle
  const pointX = centreX + (Math.sin(radians) * r); // specific point x on the circle for the angle

0

Com base na resposta de Daniel acima, aqui está minha opinião sobre o uso do Python3.

import numpy


def circlepoints(points,radius,center):
    shape = []
    slice = 2 * 3.14 / points
    for i in range(points):
        angle = slice * i
        new_x = center[0] + radius*numpy.cos(angle)
        new_y = center[1] + radius*numpy.sin(angle)

        p = (new_x,new_y)
        shape.append(p)

    return shape

print(circlepoints(100,20,[0,0]))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.