質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

9786閲覧

C++でベジェ曲線を描画したいです

RinT_hinabita39

総合スコア28

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/11/01 05:06

###前提・実現したいこと
C++のGLUTを使って3次ベジェ曲線を描画したいです。
割と近いところまで行ったのですがこの先どうしたらいいのかわかりません。

###発生している問題・エラーメッセージ
自分で書いたのは //制御点を結ぶ線分の描画 からvoidの前までのみなので、そこ以外は間違っていないはずです。
コンパイルは通るのですが、想定と少し違った図形が描画されてしまいます。

クリックで点を4つ打つと、それらを結ぶ"線分"と、それらの内側にベジェ曲線が表示されてほしいのですが、
どうやら4つの点を結んだ四角形になってしまうようです。
GL_LINE_STRIPにしているので、こうならないつもりだったのですが…

ちなみに、点の数が3n+1になった時に曲線を描くようにしてあり、図の例は点4つの場合ですが、7個以上の場合も曲線は正しく描画できています。(ただ謎の四角形は描画され続ける)

イメージ説明

###該当のソースコード

#include <cstdlib> #include <cmath> #include <vector> #include <GLUT/glut.h> // 2次元ベクトルを扱うためのクラス class Vector2d { public: double x, y; Vector2d() { x = y = 0; } Vector2d(double _x, double _y) { x = _x; y = _y; } void set(double _x, double _y) { x = _x; y = _y; } // 長さを1に正規化する void normalize() { double len = length(); x /= len; y /= len; } // 長さを返す double length() { return sqrt(x * x + y * y); } // s倍する void scale(const double s) { x *= s; y *= s; } // 加算の定義 Vector2d operator+(Vector2d v) { return Vector2d(x + v.x, y + v.y); } // 減算の定義 Vector2d operator-(Vector2d v) { return Vector2d(x - v.x, y - v.y); } // 内積の定義 double operator*(Vector2d v) { return x * v.x + y* v.y; } // 代入演算の定義 Vector2d& operator=(const Vector2d& v){ x = v.x; y = v.y; return (*this); } // 加算代入の定義 Vector2d& operator+=(const Vector2d& v) { x += v.x; y += v.y; return (*this); } // 減算代入の定義 Vector2d& operator-=(const Vector2d& v) { x -= v.x; y -= v.y; return (*this); } // 値を出力する void print() { printf("Vector2d(%f %f)\n", x, y); } }; // マイナスの符号の付いたベクトルを扱えるようにするための定義 例:b=(-a); のように記述できる Vector2d operator-( const Vector2d& v ) { return( Vector2d( -v.x, -v.y ) ); } // ベクトルと実数の積を扱えるようにするための定義 例: c=5*a+2*b; c=b*3; のように記述できる Vector2d operator*( const double& k, const Vector2d& v ) { return( Vector2d( k*v.x, k*v.y ) );} Vector2d operator*( const Vector2d& v, const double& k ) { return( Vector2d( v.x*k, v.y*k ) );} // ベクトルを実数で割る操作を扱えるようにするための定義 例: c=a/2.3; のように記述できる Vector2d operator/( const Vector2d& v, const double& k ) { return( Vector2d( v.x/k, v.y/k ) );} // ================================================================================================ std::vector<Vector2d> g_ControlPoints; // 制御点を格納する // 表示部分をこの関数で記入 void display(void) { glClearColor (1.0, 1.0, 1.0, 1.0); // 消去色指定 glClear (GL_COLOR_BUFFER_BIT ); // 画面消去 // 制御点の描画 glPointSize(5); glColor3d(0.0, 0.0, 0.0); glBegin(GL_POINTS); for(unsigned int i = 0; i < g_ControlPoints.size(); i++) { glVertex2d(g_ControlPoints[i].x, g_ControlPoints[i].y); } glEnd(); // 制御点を結ぶ線分の描画 glColor3d(1.0, 0.0, 0.0); glLineWidth(1); glBegin(GL_LINE_STRIP); for(unsigned int i = 0; i < g_ControlPoints.size(); i++) { glVertex2d(g_ControlPoints[i].x, g_ControlPoints[i].y); if(i%3==0 && i!=0) { for(float t=0; t<=1; t+=0.01) { glVertex2d((1-t)*(1-t)*(1-t)*g_ControlPoints[i-3].x + 3*(1-t)*(1-t)*t*g_ControlPoints[i-2].x + 3*(1-t)*t*t*g_ControlPoints[i-1].x + t*t*t*g_ControlPoints[i].x, (1-t)*(1-t)*(1-t)*g_ControlPoints[i-3].y + 3*(1-t)*(1-t)*t*g_ControlPoints[i-2].y + 3*(1-t)*t*t*g_ControlPoints[i-1].y + t*t*t*g_ControlPoints[i].y); } } } glEnd(); glutSwapBuffers(); } void resizeWindow(int w, int h) { h = (h == 0) ? 1 : h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // ウィンドウ内の座標系設定 // マウスクリックの座標と描画座標が一致するような正投影 glOrtho(0, w, h, 0, -10, 10); glMatrixMode(GL_MODELVIEW); } // キーボードイベント処理 void keyboard(unsigned char key, int x, int y) { switch (key) { case 'q': case 'Q': case '\033': exit(0); /* '\033' は ESC の ASCII コード */ default: break; } glutPostRedisplay(); } // マウスイベント処理 void mouse(int button, int state, int x, int y) { if(state == GLUT_DOWN) { switch (button) { case GLUT_LEFT_BUTTON: // クリックした位置に制御点を追加 g_ControlPoints.push_back(Vector2d(x, y)); break; case GLUT_MIDDLE_BUTTON: break; case GLUT_RIGHT_BUTTON: // 末尾の制御点の削除 if(!g_ControlPoints.empty()) { g_ControlPoints.pop_back(); } break; default: break; } glutPostRedisplay(); // 再描画 } } // メインプログラム int main (int argc, char *argv[]) { glutInit(&argc, argv); // ライブラリの初期化 glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); // 描画モードの指定 glutInitWindowSize(800 , 800); // ウィンドウサイズを指定 glutCreateWindow(argv[0]); // ウィンドウを作成 glutDisplayFunc(display); // 表示関数を指定 glutReshapeFunc(resizeWindow); // ウィンドウサイズが変更されたときの関数を指定 glutKeyboardFunc(keyboard); // キーボードイベント処理関数を指定 glutMouseFunc(mouse); // マウスイベント処理関数を指定 glutMainLoop(); // イベント待ち return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。

i=0~3の間、下記で4点描画しますね。

glVertex2d(g_ControlPoints[i].x, g_ControlPoints[i].y);

そして、i=3の時、それに続けてfor(float t=0; ...)の中のglVertex2d()を呼び出しますが、
これはt=0の時g_ControlPoints[0]に点を打つと思います。
結果、g_ControlPoints[3]→g_ControlPoints[0]の線が引かれるのではないでしょうか。

投稿2016/11/01 06:40

編集2016/11/01 06:42
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RinT_hinabita39

2016/11/01 06:49

言われてみると確かにそうっぽいですね… 皆目検討もつかないので、具体的にどう直せばいいのかも教えてくれると嬉しいです。
Chironian

2016/11/01 07:05

g_ControlPointsを結ぶ曲線とベジェ曲線を分けて、それぞれ別のglBegin()~forループ~glEnd()にするのが一番てっとり早いと思います。
RinT_hinabita39

2016/11/01 09:26

ありがとうございます、やってみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問