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

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

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

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

Q&A

解決済

1回答

5028閲覧

ベジェ曲線について。。。

windowsaa

総合スコア16

C++

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

0グッド

0クリップ

投稿2017/10/09 13:26

このベジェ曲線に接線を引きたいと考えています。

が手つかずの状態です

どのような考え方で取り組めばいいですか?

C

1 2#include<stdlib.h> //C言語標準ライブラリのインクルード 3#include<GL/glut.h> //GLUTヘッダファイルのインクルード 4#include<GL/gl.h> //GLヘッダファイルのインクルード 5 6#define PI 3.14159265 7 8float controlpoints[4][3] = 9{ 10 {1,2,0}, 11 {2,3,0}, 12 {3,1,0}, 13 {5,1,0}, 14}; 15 16//プロトタイプ宣言 17 18void init(void); 19void keyboard(unsigned char key, int x, int y); 20void display(void); 21void resize(int w, int h); 22 23int main(int argc, char **argv) 24{ 25 glutInit(&argc, argv); 26 /* ウィンドウの生成 */ 27 glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH); 28 glutInitWindowPosition(200, 50); 29 glutInitWindowSize(400,400); 30 glutCreateWindow(argv[0]); 31 32 init(); 33 glutReshapeFunc(resize); 34 glutDisplayFunc(display); 35 glutKeyboardFunc(keyboard); 36 37 glutMainLoop(); 38 39 return 0; 40} 41 42void keyboard(unsigned char key, int x, int y) 43{ 44 switch (key) { 45 case '\33': 46 case 'q': 47 case 'Q': 48 exit(0); 49 break; 50 default: 51 break; 52 } 53} 54 55void display(void) 56{ 57 int i; 58 59 glClear(GL_COLOR_BUFFER_BIT); 60 61 glColor4f(1.0, 1.0, 1.0, 1.0); 62 glBegin(GL_LINE_STRIP); 63 for (i = 0; i <= 30; i++) 64 glEvalCoord1f((GLfloat)i / 30.0); 65 glEnd(); 66 67 /* 制御点を描く */ 68 glPointSize(5.0); 69 glColor4f(1.0,1.0,0.0,1.0); 70 glBegin(GL_POINTS); 71 for (i = 0; i < 4; i++) 72 glVertex3fv(&controlpoints[i][0]); 73 glEnd(); 74 75 glFlush(); 76} 77 78void resize(int w, int h) 79{ 80 glViewport(0, 0, (GLsizei)w, (GLsizei)h); 81 glMatrixMode(GL_PROJECTION); 82 glLoadIdentity(); 83 if (w <= h) 84 glOrtho(-5.0, 20.0, -5.0*(GLfloat)h / (GLfloat)w, 85 12.5*(GLfloat)h / (GLfloat)w, -10.0, 5.0); 86 else 87 glOrtho(-5.0*(GLfloat)w / (GLfloat)h, 88 5.0*(GLfloat)w / (GLfloat)h, -5.0, 5.0, -5.0, 5.0); 89 glMatrixMode(GL_MODELVIEW); 90 glLoadIdentity(); 91 glScalef(3,3,3); 92} 93 94 95void init(void) 96{ 97 glClearColor(0.0, 0.0, 0.0, 0.0); 98 glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &controlpoints[0][0]); 99 glEnable(GL_MAP1_VERTEX_3); 100} 101

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

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

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

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

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

LouiS0616

2017/10/09 13:29

OpenGLタグを追加してください。
guest

回答1

0

ベストアンサー

制御点を順にp0, p1, p2, p3としますと、3次のベジエ曲線の特徴から、p0地点の接線はp1を通過し、p3地点の接線がp2を通過します。

よって、p0,p3に接線(というより、ベジエ曲線を制御するハンドル)を描くだけが目的ならばp0->p1の線分とp3->p2の線分でこと足りると思います。


曲線上の任意の点pを通る接線ということになると、媒介変数をt(0.0~1.0の区間内を変化させる)としてtに対するベジエ曲線上の座標と傾きを求めることになります。もしそうした機能がOpenGLに既にあるなら自分で計算する必要はないですが、ちょこっと調べて見つからなかったので、ここでは自前で計算するとしたらという仮定で計算方法を書いてみます。(もし機能があるならスミマセン)

3次の場合、tに対応する曲線上の点は

p_x = (1-t)(1-t)(1-t)p0_x + 3(1-t)(1-t)tp1_x + 3(1-t)ttp2_x + tttp3_x;
p_y = (1-t)(1-t)(1-t)p0_y + 3(1-t)(1-t)tp1_y + 3(1-t)ttp2_y + tttp3_y;

となるとのことです。(適当なページからのコピペです)

傾きについてですが、まず上記の式をtにより以下のように整理します。

p_x = Ax * t * t * t + Bx * t * t + Cx * t + Dx
p_y = Ay * t * t * t + By * t * t + Cy * t + Dy

(Ax, Bx, ...などはp0_x, p1_x, ...できまる値ですが計算は省略)

これをtで微分してやると

∂p_x/∂t = dp_x = 3 * Ax * t * t + 2 * Bx * t + Cx
∂p_y/∂t = dp_y = 3 * Ay * t * t + 2 * By * t + Cy

で計算できます。これで傾き(dp_y/dp_x)が求まりますので、接線の長さを適当にLと決めるとその端点TPの座標TP_x, TP_yは曲線上の点の座標p_x, p_yと傾きから、以下のようになります。

magnitude = sqrt(dp_x * dp_x + dp_y * dp_y)

TP_x = p_x ± L / 2 * dp_x / magnitude
TP_y = p_y ± L / 2 * dp_y / magnitude

OpenGLの具体的コードは自分には書けないのですが、上記がヒントになればと思います。

投稿2017/10/09 22:39

KSwordOfHaste

総合スコア18394

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問