Как сгенерировать набор точек, которые равноудалены друг от друга и лежат на окружности

#c #geometry

#c #геометрия

Вопрос:

Я пытаюсь сгенерировать массив из n точек, которые равноудалены друг от друга и лежат на окружности в C. В принципе, мне нужно иметь возможность передать функции количество точек, которое я хотел бы сгенерировать, и получить обратно массив точек.

Ответ №1:

Прошло действительно много времени с тех пор, как я работал на C / C , поэтому я попробовал это подробнее, чтобы посмотреть, как у меня получилось, но вот некоторый код, который рассчитает точки для вас. (Это консольное приложение VS2010)

 // CirclePoints.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "math.h"

int _tmain()
{
    int points = 8;
    double radius = 100;

    double step = ((3.14159265 * 2) / points);
    double x, y, current = 0;
    for (int i = 0; i < points; i  )
    {
        x = sin(current) * radius;
        y = cos(current) * radius;

        printf("point: %d x:%lf y:%lfn", i, x, y);

        current  = step;
    }

    return 0;
}
  

Комментарии:

1. Я выбираю это как принятый ответ, потому что вы показали мне, как получить x и y точек, которые мне были нужны для моего проекта. Могу ли я получить объяснение математики? Мне всего 13, поэтому, пожалуйста, постарайтесь, чтобы ваше объяснение было как можно более простым.

Ответ №2:

Попробуйте что-то вроде этого:

 void make_circle(float *output, size_t num, float radius)
{
  size_t i;

  for(i = 0; i < num; i  )
  {
    const float angle = 2 * M_PI * i / num;
    *output   = radius * cos(angle);
    *output   = radius * sin(angle);
  }
}
  

Это непроверено, возможно, при вычислении шага угла скрытие по одному, но оно должно быть близко.

Это предполагает, конечно, что я правильно понял вопрос.

ОБНОВЛЕНИЕ: Переделано вычисление угла так, чтобы оно не увеличивалось, чтобы уменьшить потерю точности с плавающей точкой из-за повторного добавления.

Комментарии:

1. Повторяющиеся добавления приведут к накоплению ошибок — вам лучше использовать angle = i * 2 * M_PI / num; в цикле.

2. В качестве альтернативы, если вас не волнует накопление незначительных ошибок, вы можете получить, вычислив cos и sin только один раз, затем выполнить цикл, чтобы получить степени комплексного значения cos(angle) i*sin(angle) . Так будет намного быстрее.

Ответ №3:

Вот решение, несколько оптимизированное, непроверенное. Ошибка может накапливаться, но использование double вместо float , вероятно, более чем компенсирует это, за исключением чрезвычайно больших значений n .

 void make_circle(double *dest, size_t n, double r)
{
    double x0 = cos(2*M_PI/n), y0 = sin(2*M_PI/n), x=x0, y=y0, tmp;
    for (;;) {
        *dest   = r*x;
        *dest   = r*y;
        if (!--n) break;
        tmp = x*x0 - y*y0;
        y = x*y0   y*x0;
        x = tmp;
    }
}
  

Комментарии:

1. Если быть по-настоящему разборчивым, при больших n вы немного потеряете точность, обновляя x и y таким образом, потому что x0 будет близко к 1. Вы теряете меньшую точность, используя d0 = cos (2pi / n) -1 = -2 * sin (pi / n) * sin (pi / n), а затем обновляете: tmp = x d0-y y0; y = x d0 y x0; x = tmp;

2. Честно говоря, я сказал, что вы будете накапливать ошибку для больших n , но спасибо за улучшение. 🙂

Ответ №4:

Вы должны решить это на языке c:

В декартовой системе координат x-y окружность с координатами центра (a, b) и радиусом r является множеством всех точек (x, y), таких, что

(x — a) ^ 2 (y — b) ^ 2 = r ^ 2

Комментарии:

1. Вот почему я пишу необычные решения и призываю OP объяснить это своему профессору, если они будут копировать это дословно … 😉

Ответ №5:

Вот реализация javascript, которая также использует необязательную центральную точку.

 function circlePoints (radius, numPoints, centerX, centerY) {
  centerX = centerX || 0;
  centerY = centerY || 0;

  var
    step = (Math.PI * 2) / numPoints,
    current = 0,
    i = 0,
    results = [],
    x, y;

  for (; i < numPoints; i  = 1) {
    x = centerX   Math.sin(current) * radius;
    y = centerY   Math.cos(current) * radius;

    results.push([x,y]);

    console.log('point %d @ x:%d, y:%d', i, x, y);

    current  = step;
  }

  return results;
}
  

Комментарии:

1. Привет, и добро пожаловать в Stack Overflow. Хотя это должно быть тривиально для перевода на C, пожалуйста, придерживайтесь тегов в будущих ответах. Это C-вопрос, и на него следует дать C-ответы.