楕円の計算と作図
楕円の作図に関しては、作図の項目にもありますが、ここでは、離心率の観点から、検討します。
楕円の、作図、積分計算や接線等のプログラムを検討してきましたが、基本的な部分について抜けていましたので、改めてプログラムを組んでみました。
計算そのものは、非常に単純な計算です。
楕円、双曲線の公式は、上記です。
x,yは座標、a,bは、楕円の半径で、離心率 k パラメータ m=k2 です。
楕円の半径aを1とすると、xに対するyの値は、y=√(b2-b2x2)となるのは周知の如くです、b2はmに対して b2=1-m
となります。
mが0より小さいと、aの半径よりbの半径が大きい縦長の楕円となります。
mの値がゼロだと円、ゼロより大きく1以下なら、横長の楕円です。
m=1だと、Xの値が-aから+aの直線となり
1より大きくなると、双曲線となるので、双曲線も楕円に含まれることになるようです。
双曲線となった時の漸近線の角度は、楕円のパラメータmの値の実数積分範囲の角度を α とすると π/2 - α の角度となります。
楕円積分が、y軸から始まるためです。
ですがが、mが1より大きいときの楕円積分の値の実数となる部分は、双曲線が作図された、線のない部分なので、疑問が残ります。
虚数となるのは、実際に線が描画されている部分です。
入力をmかkを選択して作図する簡単なプログラムです。
プログラム
unit main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, Vcl.ExtCtrls; type TForm1 = class(TForm) BitBtn1: TBitBtn; LabeledEdit1: TLabeledEdit; Image1: TImage; LabeledEdit2: TLabeledEdit; RadioButton1: TRadioButton; RadioButton2: TRadioButton; procedure FormCreate(Sender: TObject); procedure BitBtn1Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } procedure clear; procedure Linetod(x, y: double); procedure Movetod(x, y: double); procedure anglline(q, r: double); procedure mnoe; procedure large(m :double); procedure normal(m :double); procedure minus(m :double); function mtobh2(m: double): double; procedure ellipse(bh2, dx, one: double; c : integer); end; var Form1: TForm1; implementation {$R *.dfm} uses system.Math; var yc, xc : integer; // 中心座標 sc : double = 30; // スケール procedure TForm1.clear; var rect: Trect; begin Rect.Top := 0; Rect.Left := 0; Rect.Right := Image1.Width; Rect.Bottom := Image1.Height; Image1.canvas.Brush.Style := bsSolid; Image1.canvas.Brush.Color := clBtnface; Image1.canvas.FillRect(Rect); end; procedure TForm1.Linetod(x, y: double); var xi, yi: integer; begin xi := round(x * sc + xc); yi := round(yc - y * sc); Image1.canvas.Lineto(xi, yi); end; procedure TForm1.Movetod(x, y: double); var xi, yi: integer; begin xi := round(x * sc + xc); yi := round(yc - y * sc); Image1.canvas.Moveto(xi, yi); end; // q 角度deg r 半径 procedure TForm1.anglline(q, r: double); var x, y : integer; begin x := round(cos(q) * r * sc); y := round(sin(q) * r * sc); Image1.canvas.Moveto(xc - x, yc - y); Image1.canvas.lineto(xc + x, yc + y); end; // パラメータm m = k^2 から b^2の値計算 k 離心率 // m = (a^2 - b^2) / a^2 // m = 1- b^2 a = 1 として // b^2 = 1- m // m > 1 の時 B^2 < 0 となり x^2 / a^2 - y^2 / b^2 = 1 放物線となります // m = 1 の時 y = 0 x で水平直線 // 0 < m < 1 の時 横長楕円 // m = 0 円 // m < 0 の時 縦長楕円 function TForm1.mtobh2(m: double): double; var bh: double; // b^2 begin bh := 1 - m; // x^2 / a^2 - y^2 / bh = 1 a = 1 result := bh; if bh >= 0 then begin bh := sqrt(bh); Image1.Canvas.TextOut(10, Image1.Height - 17, ' a = 1, ' + 'b = ' + floatTostr(bh)); end else begin bh := sqrt(-bh); Image1.Canvas.TextOut(10, Image1.Height - 17, ' a = 1, ' + 'b = ' + floatTostr(bh) + 'i'); end; end; // m = 1 の時の 作図 // y^2 = 0 + 0 * x^2 // y = 0 * x 水平直線 procedure TForm1.mnoe; begin sc := 10; image1.Canvas.Pen.Color := clred; Image1.Canvas.Pen.Style := psDashDot; movetod(0, 5); lineTod(0, -5); image1.Canvas.Pen.Color := clblack; Image1.Canvas.Pen.Style := psSolid; movetod(-15, 0); lineTod(15, 0); Image1.Canvas.TextOut(10, Image1.Height - 17, ' a = 1, ' + 'b = 0'); end; // 楕円 双曲線 作図 // bh2 b^2 // dx Δx // one xの最小値 0 or 1 // c 分割数 procedure TForm1.ellipse(bh2, dx, one: double; c : integer); var i : integer; x, yh2, y: double; begin x := one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); movetod(x, y); for i:= 1 to c do begin x := i * dx + one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); linetod(x, y); end; x := one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); movetod(x, -y); for i:= 1 to c do begin x := i * dx + one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); linetod(x, -y); end; x := one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); movetod(-x, y); for i:= 1 to c do begin x := i * dx + one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); linetod(-x, y); end; x := one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); movetod(-x, -y); for i:= 1 to c do begin x := i * dx + one; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); linetod(-x, -y); end; end; // m > 1 // x^2 / a^2 + y^2 / b^2 = 1 楕円の公式 // y^2 = b^2 - b^2 * x^2 a = 1 として // y = √y // xの値は x >= 1 or x <= -1 procedure TForm1.large(m :double); const c = 50; var Q, Qb : double; bh2, k : double; dx : double; begin Sc := 15; k := sqrt(m); Qb := arcsin(1 / k); Q := pi / 2 - Qb; Image1.Canvas.TextOut(10, 0, '漸近線角度 = ' + floatTostr(Q / pi * 180) + '°'); Image1.Canvas.pen.Color := clred; anglline(Q, 12); anglline(-Q, 12); Image1.Canvas.Pen.Color := clblack; Image1.Canvas.Pen.Style := psSolid; bh2 := mtobh2(m); dx := 12 * cos(Q) / c; // 放物線 ellipse(bh2, dx, 1, c); // 内接楕円 // Image1.Canvas.Pen.Color := clgreen; // dx := 1 / c; // ellipse(-bh2, dx, 0, c); end; // 0 <= m < 1 // m < 1 はすべて同じです計算です 作図上分けています (円と横長楕円) // x^2 / a^2 + y^2 / b^2 = 1 楕円の公式 // y^2 = b^2 - b^2 * x^2 a = 1 として // y = √y // xの値は -1 <= x <= 1 procedure TForm1.normal(m :double); const c = 100; var bh2 : double; dx : double; begin sc := 100; image1.Canvas.Pen.Color := clred; Image1.Canvas.Pen.Style := psDashDot; movetod(0, -1.2); linetod(0, 1.2); movetod(-1.2, 0); linetod(1.2, 0); Image1.Canvas.Pen.Color := clblack; Image1.Canvas.Pen.Style := psSolid; bh2 := mtobh2(m); dx := 1 / c; // 円、横長楕円 ellipse(bh2, dx, 0, c); end; // m < 0 // m < 1 はすべて同じです計算です 作図上分けています (縦長楕円) // x^2 / a^2 + y^2 / b^2 = 1 楕円の公式 // y^2 = b^2 - b^2 * x^2 a = 1 として // y = √y // xの値は -1 <= x <= 1 procedure TForm1.minus(m :double); const c = 50; var bh2, yh2: double; dx, x, y : double; begin bh2 := mtobh2(m); dx := 1 / c; x := 0; yh2 := bh2 - bh2 * x * x; y := sqrt(yh2); sc := 100; Image1.Canvas.Pen.Color := clred; Image1.Canvas.Pen.Style := psDashDot; movetod(0, -1.2); linetod(0, 1.2); movetod(-1.2, 0); linetod(1.2, 0); if 1 <= y then sc := 100 / y; Image1.Canvas.Pen.Color := clblack; Image1.Canvas.Pen.Style := psSolid; // 縦長楕円 ellipse(bh2, dx, 0, c); end; // 値入力と楕円計算 procedure TForm1.BitBtn1Click(Sender: TObject); var m, k : double; ch, l : integer; kstr, kss: string; c : char; FI : boolean; begin m := 0; if radiobutton1.Checked = true then begin val(labelededit1.Text, m, ch); if ch <> 0 then begin application.MessageBox('入力値に誤りがあります。','注意',0); exit; end; end; FI := False; if radiobutton2.Checked = true then begin kstr := LabeledEdit2.Text; l := length(kstr); // 文字の長さ取得 c := kstr[l]; // iの文字確認 if (c = 'i') or (c = 'I') then begin // i虚数指定だったら kss := copy(kstr, 1, l - 1); // iの前までコピー FI := True; // 虚数フラグセット end else Kss := kstr; val(kss, k, ch); if ch <> 0 then begin application.MessageBox('k(離心率)の値に間違いがあります。','k(離心率)',0); exit; end; m := k * K; if FI then m := -m; // kが虚数だったらm -> -m end; clear; // 画面消去 if m < 0 then begin k := sqrt(-m); kstr := 'k = ' + floatTostr(k) + 'i'; end else begin k := sqrt(m); kstr := 'k = ' + floatTostr(k); end; Image1.Canvas.TextOut(10,15, kstr); if m > 1 then large(m); if m = 1 then mnoe; if (0 <= m) and (m < 1) then normal(m); if m < 0 then minus(m); end; // 初期設定 procedure TForm1.FormCreate(Sender: TObject); begin Image1.Top := 10; Image1.Left := 10; Image1.height := clientheight - 20; Image1.Width := clientwidth - 150; xc := Image1.Width div 2; // 中心座標X yc := Image1.Height div 2; // 中心座標Y image1.Canvas.Font.Size := 11; Image1.Canvas.Pen.Width := 1; clear; normal(0.64); end; end.
ellipse_k.zip
各種プログラム計算例に戻る