如何生成一组等距且位于圆上的点

4

我试图生成一个包含n个点的数组,这些点在C语言中等距分布在一个圆上。基本上,我需要传递一个函数我想要生成的点数,然后得到一个点的数组。

5个回答

6

我已经很久没有使用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:%lf\n", i, x, y);

        current += step;
    }

    return 0;
}

1
我选择这个作为被接受的答案,因为你向我展示了如何获取点的x和y,这对我的项目很有帮助。能否给我解释一下这个数学问题?我只有13岁,所以请尽量简单易懂地解释。 - Shane M. Pelletier

5
尝试像这样做:

试试这个:

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

这是未经测试的,角度步骤计算中可能会出现一个偏差,但应该很接近。

当然,这是基于我正确理解问题的前提。

更新:重新计算角度,不再进行递增操作,以减少由于重复加法而导致的浮点精度损失。


重复的加法会导致误差累积 - 最好在循环中使用 angle = i * 2 * M_PI / num; - caf
1
另外,如果您不关心小错误的积累,可以通过计算cossin仅一次,然后循环获取复值cos(angle)+i*sin(angle)的幂来解决问题。这种方法速度将会快得多 - R.. GitHub STOP HELPING ICE

2
这里有一个优化过的解决方案,尚未经过测试。错误可能会积累,但使用 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;
    }
}

要挑剔一点,对于大的n值,通过这种方式更新x和y会稍微失去一些精度,因为x0将接近1。使用d0 = cos(2pi/n)-1 = -2sin(pi/n)sin(pi/n)可以减少精度损失,然后更新为tmp = xd0-yy0; y += xd0 + yx0; x += tmp; - dmuir
公平地说,我说过当n很大时会累积误差,但感谢你的改进。 :-) - R.. GitHub STOP HELPING ICE

0
这是一个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;
}

你好,欢迎来到Stack Overflow。虽然这个问题很容易翻译成C语言,但请在以后的回答中遵守标签。这是一个关于C语言的问题,应该给出C语言的答案。 - user13500

0
您需要使用C语言解决此问题:
在x-y笛卡尔坐标系中,圆心坐标为(a,b),半径为r的圆是所有满足以下条件的点(x,y)的集合:
(x-a)^2 +(y-b)^2 = r^2

1
这就是为什么我写花哨的解决方案并挑战OP向他们的教授解释它,如果他们直接复制粘贴...;-) - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接