web-dev-qa-db-ja.com

デカルト座標でn面の正多角形を描画する方法は?

私は、n辺の正多角形を作成するためのx、y点を計算する単純なプログラムを作成する方法を理解しようとしています。誰かが、ポリゴンを描画する既存の関数を使用しないコード例を教えてもらえますか?私はこのプロセスを次のように想定しているプロセスを理解したいと思います。

  1. 半径と中心点から開始する角度を選択してください
  2. どういうわけか、中心からその距離でのX、Y位置を計算します(どうですか?)
  3. 360を辺の数で割り、その距離を移動し、最初のx、y点から次の線を描きます
  4. angle = 360をその数で割るまで続けます。

私の仮定が正しいと仮定すると、主なことは、x、y点の計算方法を理解することです。

Visual Basic(または古いスタイルのMicrosoft/Atari/Commodore BASIC)または人間が読める英語の一連のステップで回答を優先します。数式で答える必要がある場合は、コンピューター言語で実行して、私がそれを読むことができるようにします。CまたはC++でもそれを理解できますが、数学的表記の読み方がわかりません。私が使用している言語は、Visual Basicに似た言語で、線描画以外のグラフィックスプリミティブはほとんどありません。

25
alphablender

[〜#〜] n [〜#〜],0)を中心とする半径---(rの多角形を描画するとします。次にn頂点は次のように与えられます:

x[n] = r * cos(2*pi*n/N)
y[n] = r * sin(2*pi*n/N)

ここで、0 <= n <[〜#〜] n [〜#〜]です。ここでのcossinは、度ではなくラジアンで動作していることに注意してください(これはほとんどのプログラミング言語でかなり一般的です)。

別の中心が必要な場合は、中心点の座標をそれぞれに追加します(x [n]y [n])。別の方向が必要な場合は、一定の角度を追加するだけです。したがって、一般的な形式は次のとおりです。

x[n] = r * cos(2*pi*n/N + theta) + x_centre
y[n] = r * sin(2*pi*n/N + theta) + y_centre
44
_angle = start_angle
angle_increment = 360 / n_sides
for n_sides:
    x = x_centre + radius * cos(angle)
    y = y_centre + radius * sin(angle)
    angle += angle_increment
_

実際には、コーナーポイントを計算するだけでなく線を描く場合も、最初のポイントを繰り返すことによってポリゴンを「結合」する必要があります。

また、sin()およびcos()が度ではなくラジアンで機能する場合は、_2 * PI_ではなく_360_を使用します。

7
andrew cooke

これが正多角形のポイントを出力する完全なc ++プログラムです。この場合、pは辺の数、rはポリゴンの半径、dは中心からの最初のポイントの方向または角度です。多分これは役立つでしょう。

//g++ ck.cpp -o ck && ./ck
#include <stdio.h>
#include <math.h>

int p=3; //number of sides
double r=1000,d=3/4.0;

int main()
{
 int i=0;
 double x,y,t;
 while(i<p)
 {
  t=2*M_PI*((double)i/p+d);
  x=cos(t)*r;
  y=sin(t)*r;
  printf("x%i:%f y%i:%f\n",i,x,i,y);
  i++;
 }
}

エラーの蓄積を犠牲にして高速化したい場合は、(複雑な)プリミティブn乗根を使用して、その能力を利用します(言語に組み込みの複素数サポートを使用するか、手動で乗算をコーディングします) 。 C:

complex double omega=cexp(2*M_PI*I/n), z;
for (i=0, z=1; i<n; i++, z*=omega) {
    /* do something with z */
}

「for n_sides:」の答えが最も簡単です。複素数を使用して計算を簡略化できると提案した人のために、ほとんどすべての数学ライブラリには、効率的な補間を備えたテーブルベースのcos()およびsin()ルーチンが含まれているため、比較的あいまいなソリューションを掘り下げる必要はありません。通常、通常のnゴンを初期化し、OpenGLのハードウェアスケーリングを使用して、特定のインスタンスに対してそれをスケーリング/変換できます。

それについてハードコアになりたい場合は、必要なすべてのnゴンを事前に生成し、それらを頂点バッファーにロードします。

余談ですが、ここにLuaでの上記のソリューションがあります。座標を出力するだけですが、もちろん、座標を配列/テーブルで返すこともできます。返された座標は、OpenGL GL_LINE_LOOPメッシュプリミティブを初期化するために使用できます。

require 'math'

-- computes coordinates for n-sided, regular polygon of given radius and start angle
-- all values are in radians

function polypoints(sides, radius, start)
    local x_center = 0.0
    local y_center = 0.0
    local angle = start
    local angle_increment = 2 * math.pi / sides
    local x=0.0
    local y=0.0

    print(string.format("coordinates for a %d sided regular polygon of radius %d\nVertex",sides,radius),"X"," ","Y")
    for i=1,sides do
        x = x_center + radius * math.cos(angle)
        y = y_center + radius * math.sin(angle)
        print(string.format("%d\t%f\t%f",i,x,y))
        angle = angle + angle_increment
    end
end

-- Generate a regular hexagon inscribed in unit circle 
polypoints(6, 1.0, 0.0)
1
eris0xff

Visual Basicで回答を求めたのは知っていますが、 これはJavaScriptのソリューションです です。

1
CrazyTim