楕円弧部各種計算

 楕円弧長さ、楕円弧面積、楕円弦長さ、楕円扇面積 計算

 楕円に対して、指定された角度の範囲に対して、楕円弧長さ、楕円弧面積、楕円弦長さ、楕円扇面積の計算をします。
 楕円弧長の計算には楕円積分が必要なので、楕円の周長2を参照してください、それ以外は、積分計算は必要ありません。
 楕円弦長さは、楕円と、指定された角度の直線と楕円の交点の座標から長さをけいさんします。
 扇面積は、上記交点のY座票を円の座標に変換し、円上の角度を計算、その角度から円上の扇部の面積を計算し、更に楕円比b/aで変換して、楕円上の扇面積とします。
 三角面積は、円上の角度と半径aの二等辺三角形の面積を計算、これも楕円比で変換して、楕円上の三角部の面積とします。
 楕円弧面積は、計算範囲の角度が180°より小さい場合は、扇面積から、三角面積を減算し、大きい場合は加算すれば得ることが出来ます。



プログラム

 楕円積分には、カールソンの第二種楕円積分を使用しています。
楕円弦長さは、楕円積分用に、円上の角度に変更してから、楕円上の座標を計算して求めています。
(楕円と、傾き角θの直線の交点を求めている時に計算しても良いのですが、計算の都合上、積分用角度から計算しています。)

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.ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Panel1: TPanel;
    arEdit: TLabeledEdit;
    brEdit: TLabeledEdit;
    sttEdit: TLabeledEdit;
    endEdit: TLabeledEdit;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    procedure ImageClear;
    function draw_ellipse: boolean;
    function EllipseInput(var ar, br, sttQ, endQ: double): boolean;
    procedure ellipse_calc(ar, br, q, magnification: double; var x, y: double);
    procedure Linedlaw(x1, y1, x2, y2: double; Xsift, Ysift: integer; LF: boolean);
    procedure divisionpartition;
    function second_imperfect_elliptic_integral(QD, K: double): double;
    procedure elliptic_integral;
    function circle_calc(ar, br, q: double): double;
    procedure elliptical_arc_area;
    function RF(x1, y1, z1: Extended): Extended;
    function RJ(x1, y1, z1, p1: Extended): Extended;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses System.Math;

//-----------------------------
// 表示画像消去
//-----------------------------
procedure TForm1.ImageClear;
begin
  image1.Canvas.Brush.Style := bsSolid;
  image1.Canvas.Brush.Color := clWhite;
  image1.Canvas.FillRect(Rect(0, 0, image1.Width, image1.Height));
end;

//--------------------------
// 2点間線引き
//--------------------------
procedure TForm1.Linedlaw(x1, y1, x2, y2: double; Xsift, Ysift: Integer; LF: boolean);
var
  xp1, yp1, xp2, yp2: integer;
begin
  if LF then begin
    xp1 := round(x1) + Xsift;
    yp1 := image1.Height - round(y1) - Ysift;
    image1.Canvas.MoveTo(xp1, yp1);
  end;
  xp2 := round(x2) + Xsift;
  yp2 := image1.Height - round(y2) - Ysift;
  image1.Canvas.LineTo(xp2, yp2);
end;

//-------------------------------------------------------------
// 楕円上の座標計算
//      q           角度
//      ar , br        半径
//      magnification  倍率
//      x, y         座標
// q 角度は中心に対するxy座標の角度ではないので注意が必要です。
//-------------------------------------------------------------
procedure TForm1.ellipse_calc(ar, br, q, magnification: double; var x, y: double);
begin
  x := ar * cos(q) * magnification;
  y := br * sin(q) * magnification;
end;

//-----------------------
// 楕円作図
//-----------------------
function TForm1.draw_ellipse: boolean;
const
  divideN = 2000;       // 作図用分割数
  draw_margin = 100;     // 作図余白
var
  ar, br      : double;
  sttQ, endQ  : double;
  stBQ, enBQ  : double;
  maxr        : double;
  I           : integer;
  dq          : double;
  x1, y1      : double;
  x2, y2      : double;
  Xsift, Ysift  : integer;
  magnification : double;
  sttN, endN    : integer;

  // x1,y1-x2,y2 線引き
  procedure DlawCalc;
  begin
    ellipse_calc(ar, br, dq * I, magnification,  x2, y2);
    if I = sttN + 1 then Linedlaw(x1, y1, x2, y2, Xsift, Ysift, True)
                    else Linedlaw(x1, y1, x2, y2, Xsift, Ysift, False);
    x1 := x2;
    y1 := y2;
  end;

begin
  result := True;
  if not EllipseInput(ar, br, sttQ, endQ) then begin
    result := False;
    exit;
  end;
  // 開始角と終了角が等しかったら全周とします。
  stBQ := sttQ / 180 * pi;
  enBQ := endQ / 180 * pi;
  if sttQ = endQ then begin
    sttQ := 0;
    endQ := 360;
  end;
// 画像消去
  ImageClear;
// 作図設定
  Xsift := image1.Width div 2;
  Ysift := image1.Height div 2 + 30;

  sttQ := sttQ / 180 * pi;
  endQ := endQ / 180 * pi;

  // 作図計算ピッチ計算
  dq := 2 * pi / divideN;
  // 大きい方の半径選択
  maxr := ar;
  if br > ar then maxr := br;
  // 作図倍率設定
  magnification := (Xsift - draw_margin) / maxr;
// 楕円作図
  image1.Canvas.Pen.Style := psSolid;
  image1.Canvas.Pen.Color := clBlue;
  image1.Canvas.Pen.Width := 1;
  sttN := 0;
  // 最初の角度
  ellipse_calc(ar, br, 0, magnification, x1, y1);
  // 最後まで
  for I := 1 to divideN do DlawCalc;
// 楕円弧作図
  image1.Canvas.Pen.Color := clRed;
  image1.Canvas.Pen.Width := 4;
  sttN := trunc(stBQ / dq);
  endN := trunc(enBQ / dq);
  // 最初の角度
  ellipse_calc(ar, br, stBQ, magnification, x1, y1);
  // 開始角より終了角が大きい場合
  if endQ > sttQ then begin
    ellipse_calc(ar, br, sttN * dq, magnification, x1, y1);
    for I := sttN + 1 to  endN do DlawCalc;
  end
  // 開始角より終了角が小さい場合
  else begin
    // 開始角より360°迄作図
    for I := sttN + 1 to divideN do DlawCalc;
    // 0°(=360°)から終了角迄作図
    for I := 1 to endN do DlawCalc;
  end;
  // 最後の角度
  ellipse_calc(ar, br, enBQ, magnification, x2, y2);
  Linedlaw(x1, y1, x2, y2, Xsift, Ysift, True);

// 楕円弦作図
  // 最後の角度
  ellipse_calc(ar, br, enBQ, magnification, x2, y2);
  // 最初の角度
  ellipse_calc(ar, br, stBQ, magnification, x1, y1);
  image1.Canvas.Pen.Color := clGreen;
  image1.Canvas.Pen.Width := 2;
  Linedlaw(x1, y1, x2, y2, Xsift, Ysift, true);
// 扇線作図
  image1.Canvas.Pen.Color := clMaroon;
  image1.Canvas.Pen.Width := 2;
  Linedlaw(X1, Y1, 0, 0, Xsift, Ysift, true);
  Linedlaw(0, 0, X2, Y2, Xsift, Ysift, true);

// 中心線作図
  image1.Canvas.Pen.Width := 1;
  image1.Canvas.Pen.Style := psDashDot;
  image1.Canvas.Pen.Color := clGreen;
  Linedlaw(-50,  0,  50,  0, Xsift, Ysift, True);
  Linedlaw(  0, -50,  0, 50, Xsift, Ysift, True);
end;

//-------------------------------------------------------------
// 円変換時の 角度計算
// 積分角度 q 角度
//          ar , br 半径
// x^2/a^2 + y^2/b^2 = 1 と 角度θの直線y = cx の連立方程式の
// の解法による円変換時の角度の計算
//-------------------------------------------------------------
function TForm1.circle_calc(ar, br, q: double): double;
var
  c, ga, sq, cb: double;
  x, y         : double;
begin
  if (q = 0) or (q = 90) or (q = 180) or (q = 270) or (q = 360)  then begin
    result := q;
    exit;
  end;
  // 楕円と直線の交点の計算
  sq := pi / 180 * q;
  c := tan(sq);                                   // y = cx 傾斜c計算
  cb := c * c / br / br;                          // y^2/b^2 のyに代入
  ga := 1 / ar / ar;                              //
  x := sqrt(1 / (ga + cb));                       // xの値
  // xの値がプラスしか計算されないので角度により符号設定
  if (q >  90) and (q < 270) then x := - x;
  y := c * x * ar / br;                           // 円上のyの値
  // xy座標円中心角度に変換
  result := arctan2(y, x) / pi * 180;
  // -角度は時はプラスに修正
  if result < 0 then result := result + 360;
end;

//--------------------
// 楕円の値入力処理
//--------------------
function TForm1.EllipseInput(var ar, br, sttQ, endQ: double): boolean;
var
  ch : integer;
begin
  result := false;
  val(arEdit.Text, ar, ch);
  if ch <> 0 then begin
    application.MessageBox('半径aは数値ではありません。', '半径a', 0);
    exit;
  end;
  if ar <= 0 then begin
    application.MessageBox('半径aがゼロ 又はゼロ以下です。', '半径a', 0);
    exit;
  end;
  val(brEdit.Text, br, ch);
  if ch <> 0 then begin
    application.MessageBox('半径bは数値ではありません。', '半径b', 0);
    exit;
  end;
  if br < 0 then begin
    application.MessageBox('半径bがゼロ 又はゼロ以下です。', '半径b', 0);
    exit;
  end;
  val(sttEdit.Text, sttQ, ch);
  if ch <> 0 then begin
    application.MessageBox('開始角は数値ではありません。', '開始角', 0);
    exit;
  end;
  val(endEdit.Text, endQ, ch);
  if ch <> 0 then begin
    application.MessageBox('終了角は数値ではありません。', '終了角', 0);
    exit;
  end;
  // 角度が0~360°の範囲に無かったら修正
  Repeat
    if sttQ > 360 then sttQ := sttQ - 360;
    if sttQ  < 0   then sttQ := SttQ + 360;
    if endQ > 360  then endQ := endQ - 360;
    if endQ  < 0  then endQ := endQ + 360;
  Until (sttQ >= 0) and (sttQ <= 360) and (endQ >= 0) and (endQ <= 360);
  // 入力角度に長径を基準とした角度θをを使用しています。
  // 楕円積分は短径を基準にsinαで表される距離に対する積分となります。
  // 入力された角度をそのまま使用する事は出来ません。
  // 楕円の中心位置を通る直線 y=cx の cを c= tanθ として楕円との交点を求め
  // 交点yの値を円変換時の値y'=y*a/bに変換、φ=arctan2(y',x)として
  // 円上の角度に変換して、x=cos(φ)*a y=sin(φ)*b θ=arctan(x,y)のθが入力値と
  // 一致するようにします。
  // 楕円積分時は更に、長径基準φを短径基準αに変換して計算します。
  sttQ := circle_calc(ar, br, sttQ);
  endQ := circle_calc(ar, br, endQ);
  if sttQ = 360 then sttQ := 0;
  result := true;
end;

//---------------------------------
// 周長 楕円弧長の分割計算
//---------------------------------
procedure TForm1.divisionpartition;
const
  divideN = 1440000;       // 全周計算分割数
  divide4 =    4000;       // 指定範囲分割数基礎数
  PI2     = 2 * pi;        // 2π
  K180    = 180;           // 180°
  K360    = 360;           // 360°
var
  ar, br      : double;    // 半径a , b
  sttQ, endQ  : double;    // 積分開始角、積分終了角 deg単位
  I           : integer;   //
  dq          : double;    // 微小角Δq
  x1, y1      : double;    // 始点座標
  x2, y2      : double;    // 終点座標
  sttN        : integer;   // 分割数
  Lng, All    : double;    // 楕円弧長 周長
  Q           : double;    // 座標計算角度
  basQ, topQ  : double;    // 積分開始角、積分終了角 rad単位

  // 座標の計算と微小角に対する距離の計算と加算
  procedure LngCalc;
  var
    xh2, yh2 : double;
  begin
    Q := basQ + dq * I;                         // 座標計算角度
    if Q >= PI2  then Q := Q - PI2;
    ellipse_calc(ar, br, Q, 1, x2, y2);         // 座標計算
    xh2 := x2 - x1;
    yh2 := y2 - y1;
    Lng := Lng + sqrt(xh2 * xh2 + yh2 * yh2);
    x1 := x2;
    y1 := y2;
  end;

begin
  // 各値の入力値変換
  if not EllipseInput(ar, br, sttQ, endQ) then exit;
  // 全周計算ピッチ計算
  dq := PI2 / divideN;
  Lng := 0;
  // 全周長計算
  ellipse_calc(ar, br, 0, 1, x1, y1);
  for I := 1 to divideN do LngCalc;
  All := Lng;                                   // 全周長

  // 指定範囲計算
  basQ := sttQ / K180 * pi;
  topQ := endQ / K180 * pi;
  // 分割数と微小角度Δqの計算
  if endQ >= sttQ then begin
    sttN := round((endQ - sttq) * divide4);         // 分割数
    if sttN = 0 then sttN := 1;                     // ゼロでの除算防止
    dq := (topQ - basQ) / sttN;                     // Δq
  end
  else begin
    sttN := round((endQ + K360 - sttQ) * divide4);  // 分割数
    if sttN = 0 then sttN := 1;                     // ゼロでの除算防止
    dq := (topQ + PI2 - basQ) / sttN;               // Δq
  end;

  Lng := 0;
  // 最初の座標
  ellipse_calc(ar, br, basQ, 1, x1, y1);
  for I := 1 to sttN do begin
    LngCalc;
  end;

  Image1.Canvas.TextOut(20, 2,'微小角分割積分 楕円弧長= ' + floatTostr(Lng));
  Image1.Canvas.TextOut(20,17,'微小角分割積分 周  長 = ' + floatTostr(ALL));
end;

// Carlson's Elliptic Integral RJ
function TForm1.RJ(x1, y1, z1, p1: Extended): Extended;
var
  s, fa, rj, rk   : Extended;
  la, mu          : Extended;
  al, be          : Extended;
  r1, a1, b1      : Extended;
  a2, b2, mv, s1  : Extended;
  rc, r0          : Extended;
  s12, s13, s14   : Extended;
  s15, s16        : Extended;
  x2, y2, z2      : Extended;
  x3, y3, z3      : Extended;
  s2, s3, p2, p3  : Extended;
  s4, s5          : Extended;
  x31, y31, z31, p31 : Extended;
  s22, s23, s2s3  : Extended;

  procedure rcab;
  begin
    rc := 1;
    a1 := al;
    b1 := be;
    repeat
      r1 := rc;
      la := 2 * sqrt(a1 * b1) + b1;
      a2 := (a1 + la) / 4;
      b2 := (b1 + la) / 4;
      mv := (a1 + 2 * b1) / 3;
      s1 := (b1 - a1) / (3 * mv);
      s12 := s1 * s1;
      s13 := s12 * s1;
      s14 := s13 * s1;
      s15 := s14 * s1;
      s16 := s15 * s1;
      rc := (1 + 3 * s12 / 10 + s13 / 7 + 3 * s14 / 8 + 9 * s15 / 22 + 159 * s16 / 208) / sqrt(mv);
      a1 := a2;
      b1 := b2;
    until r1 = rc;
  end;

  function ss: Extended;
  begin
    x31 := x31 * x3;
    y31 := y31 * y3;
    z31 := z31 * z3;
    p31 := p31 * p3;
    result := (x31 + y31 + z31 + p31);
  end;

begin
  s := 0;
  fa := 3;
  rj := 0;
  repeat
    r0 := rj;
    la := sqrt(x1 * y1) + sqrt(x1 * z1) + sqrt(y1 * z1);
    mu := (x1 + y1 + z1 + 2 * p1) / 5;
    x2 := (x1 + la) / 4;
    y2 := (y1 + la) / 4;
    z2 := (z1 + la) / 4;
    p2 := (p1 + la) / 4;
    x3 := 1 - x1 / mu;
    y3 := 1 - y1 / mu;
    z3 := 1 - z1 / mu;
    p3 := 1 - p1 / mu;
    x31 := x3;
    y31 := y3;
    z31 := z3;
    p31 := 2 * p3;
    s2 := ss / 4;
    s3 := ss / 6;
    s4 := ss / 8;
    s5 := ss / 10;
    al := (sqrt(x1) + sqrt(y1) + sqrt(z1)) * p1 + sqrt(x1 * y1 * z1);
    al := al * al;
    be := p1 * (p1 + la) * (p1 + la);
    rcab;
    s22 := 3 * s2 * s2 / 22;
    s23 := s2 * s2 * s2 / 10;
    s2s3 := s2 * s3 * 3 / 13;
    s := s + fa * rc;
    rk := 1 + 3 * s2 / 7 + s3 / 3 + s22 + s2s3 + 3 * s4 / 11 + 3 * s5 / 13 - s23;
    fa := fa / 4;
    mu := sqrt(1 / (mu * mu * mu));
    rj := s + fa / 4 * (rk + 3 * s3 * s3 / 10 + 3 * s2 * s4 / 5) * mu;
    x1 := x2;
    y1 := y2;
    z1 := z2;
    p1 := p2;
  until rj = r0;
  result := rj;
end;

// Carlson's Elliptic Integral RF
function TForm1.RF(x1, y1, z1: Extended): Extended;
var
  la, mu      : Extended;
  x2, y2, z2  : Extended;
  x3, y3, z3  : Extended;
  s2, s3      : Extended;
  r0, rf      : Extended;
  s22, s23, s2s3, s32 : Extended;
begin
  rf := 0;
  repeat
    r0 := rf;
    la := sqrt(x1 * Y1) + sqrt(x1 * z1) + sqrt(y1 * z1);
    mu := (x1 + y1 + z1) / 3;
    x2 := (x1 + la) / 4;
    y2 := (y1 + la) / 4;
    z2 := (z1 + la) / 4;
    x3 := 1 - x2 / mu;
    y3 := 1 - y2 / mu;
    z3 := 1 - z2 / mu;
    s2 := (x3 * x3 + y3 * y3 + z3 * z3) / 4;
    s3 := (x3 * x3 * x3 + y3 * y3 * y3 + z3 * z3 * z3) / 6;
    s22 := s2 * s2 / 6;
    s23 := 5 * s2 * s2 * s2 / 26;
    s32 := 3 * s3 * s3 / 26;
    s2s3 := s2 * s3 * 3 / 11;
    rf := (1 + s2 / 5 + s3 / 7 + s22 + s2s3 + s23 + s32) / sqrt(mu);
    x1 := x2;
    y1 := y2;
    z1 := z2;
  until rf = r0;
  result := rf;
end;

// 第二種楕円積分 --------------------------------------------------
function TForm1.second_imperfect_elliptic_integral(QD, K: double): double;
var
  s, s2, s3   : double;
  c2          : double;
  rf0, rd0    : double;
  k2          : double;
  eqk, eqk90  : double;
  eqd, eek    : double;
  eq          : double;
  J           : integer;
begin
  J := trunc(ABS(QD) / 90);
  if J mod 2 <> 0 then                          // 第2,第4象限の積分角度
    eqd := (J + 1) * 90 - ABS(QD)
  else                                          // 第1,第3象限の積分角度
    eqd := ABS(QD) - (90 * J);
  eq := eqd / 180 * pi;
  K2 := K * K;
  eqk90 := 0;
  if J > 0 then begin               // 積分範囲90度より大きかったら
    if K = 1 then eqk90 := 1        // k=1 だったら 90°の積分値は1
    else begin                      // K<1の時 90°の積分値計算
      rf0 := RF(0, 1 - k2, 1);
      rd0 := RJ(0, 1 - k2, 1, 1);
      eqk90 := rf0 - k2 / 3 * rd0;  // rf0 - k^2 / 3 * RD
    end;
  end;
  if (eqd < 90) or (K < 1) then begin
    if K < 1 Then begin
      c2 := cos(eq) * cos(eq);
      s  := sin(eq);
      s2 := s * s;
      s3 := s2 * s;
      rf0 := RF(c2, 1 - k2 * s2, 1);
      rd0 := RJ(c2, 1 - k2 * s2, 1, 1);
      eek := s * rf0 - k2 / 3 * s3 * rd0;
    end
    else eek := sin(eq);
  end
  else eek := 1;
  if j mod 2 <> 0 then begin          // 第2,第4象限の積分値
    eqk := (J + 1) * eqk90 - eek;
  end
  else begin                          // 第1,第3象限の積分値
    eqk := J * eqk90 + eek;
  end;
  if QD < 0 then eqk := - eqk;
  result := eqk;
end;

//--------------------------------------------------
// 楕円積分による周長計算
// カールソンによる計算をしていますが90°までしか
// 計算出来ないので90°に分けて計算しています。
// 楕円積分は短径が基準となっていますが、角度は長径が
// 基準となっているので楕円弧長計算時変換しています。
//--------------------------------------------------
procedure TForm1.elliptic_integral;
var
  ar, br      : double;
  sttQ, endQ  : double;
  K, A, L     : double;
  sttL, endL  : double;
  IND         : integer;

  // 角度、象限による楕円弧長計算
  function Elliptical_arc(q : double; I: integer): double;
  var
    sttendR : double;
  begin
    result := 0;
    case I of
      0, 2 :  begin                   // 第一、三象限
                sttendR := (I + 1) * 90 - q;
                result  := (I + 1) * A - ar * second_imperfect_elliptic_integral(sttendR, K);
              end;
      1, 3 :  begin                  // 第二、四象限
                sttendR := q - (90 * I);
                result  := I * A + ar * second_imperfect_elliptic_integral(sttendR, K);
              end;
    end;
  end;

begin
// 各値の入力値変換
  if not EllipseInput(ar, br, sttQ, endQ) then exit;
// 半径Brの方が大きかったら入れ替え 角度を90°変更
  if br > ar then begin
    k := ar;
    ar := br;
    br := k;
    if (sttQ <> 0) or (endQ <> 360) then begin
      sttQ := sttQ + 90;
      endQ := endQ + 90;
      if sttQ >= 360 then sttQ := sttQ - 360;
      if endQ >  360 then endQ := endQ - 360;
    end;
  end;
  sttL := 0;
  endL := 0;
  K := sqrt(1 - br * br / ar / ar);                       // k  離心率
  // double時のKの値の誤差対策
  if 1 - K < 1E-15 then K := 1;
// 角度90°楕円弧長計算
  A := ar * second_imperfect_elliptic_integral(90, K);    // 半径 x 第2種楕円積分
// 範囲計算  象限による計算
  for IND := 3 downto 0 do begin
    // 開始楕円弧長計算
    if (IND * 90 <= sttQ) and (sttQ < (IND + 1) * 90) then
      sttL := Elliptical_arc(sttQ, IND);
    // 終了楕円弧長計算
    if (IND * 90 < endQ) and (endQ <= (IND + 1) * 90) then
      endL := Elliptical_arc(endQ, IND);
  end;
// 開始角と終了角の大きさで計算方法変更
  if endQ >= sttQ then L := endL - sttL
                  else L := 4 * A - sttL + endL;
  Image1.Canvas.TextOut(20, image1.Height - 32,'楕円積分 楕円弧長= ' + floatTostr(L));
  Image1.Canvas.TextOut(20, image1.Height - 17,'楕円積分 周  長 = ' + floatTostr(4 * A));
end;

// 楕円弧部、扇部、楕円弦長等計算
procedure TForm1.elliptical_arc_area;
var
  ar, br          : double;
  sttQ, endQ      : double;
  x1, y1, x2, y2  : double;
  L, Sc, Sa, St   : double;
begin
// 各値の入力値変換
  if not EllipseInput(ar, br, sttQ, endQ) then exit;
  // 楕円弦長さ計算
  x1 := cos(sttQ / 180 * pi) * ar;
  y1 := sin(sttQ / 180 * pi) * br;
  x2 := cos(endQ / 180 * pi) * ar;
  y2 := sin(endQ / 180 * pi) * br;
  L := sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  Image1.Canvas.TextOut(20, image1.Height - 47,'楕円弦長= ' + floatTostr(L));
// 半径Rの円の面積
  Sc := pi * ar * ar;
// 扇部面積
  if endQ >= sttQ then
    Sa := Sc * (endQ - sttq) / 360
  else
    Sa := SC * (360 + endQ - sttq) / 360;
  Sa := Sa * br / ar;
  Image1.Canvas.TextOut(20, image1.Height - 62,'扇部面積= ' + floatTostr(Sa));
// 三角形部面積
  if endQ >= sttQ then begin
    St := ar * sin((endQ - sttq) / 180 * pi) / 2 * br;      // ar^2 * sin(θ) / 2 * br / ar
  end
  else begin
    St := ar * sin((360 + endQ - sttq) / 180 * pi) / 2 * br;
  end;
  Image1.Canvas.TextOut(20, image1.Height - 77,'三角部面積= ' + floatTostr(abs(St)));
  Image1.Canvas.TextOut(20, image1.Height - 92,'楕円弧部面積= ' + floatTostr(Sa - St));
  Image1.Canvas.TextOut(20, image1.Height - 107,'楕円面積= ' + floatTostr(ar * br * pi));

// 形状図形線色表示
  image1.Canvas.Pen.Style := psSolid;
  image1.Canvas.Pen.Width := 4;
  // 楕円弧長
  image1.Canvas.Pen.Color := clRed;
  image1.Canvas.MoveTo(270, image1.Height - 25);
  image1.Canvas.LineTo(300, image1.Height - 25);
  // 楕円弦長 
  image1.Canvas.Pen.Color := clGreen;
  image1.Canvas.MoveTo(270, image1.Height - 40);
  image1.Canvas.LineTo(300, image1.Height - 40);
  // 扇部面積
  image1.Canvas.Pen.Color := clMaroon;
  image1.Canvas.MoveTo(270, image1.Height - 55);
  image1.Canvas.LineTo(300, image1.Height - 55);
  image1.Canvas.MoveTo(330, image1.Height - 55);
  image1.Canvas.LineTo(360, image1.Height - 55);
  image1.Canvas.Pen.Color := clRed;
  image1.Canvas.MoveTo(300, image1.Height - 55);
  image1.Canvas.LineTo(330, image1.Height - 55);
  // 三角部面積
  image1.Canvas.Pen.Color := clMaroon;
  image1.Canvas.MoveTo(270, image1.Height - 70);
  image1.Canvas.LineTo(300, image1.Height - 70);
  image1.Canvas.MoveTo(330, image1.Height - 70);
  image1.Canvas.LineTo(360, image1.Height - 70);
  image1.Canvas.Pen.Color := clGreen;
  image1.Canvas.MoveTo(300, image1.Height - 70);
  image1.Canvas.LineTo(330, image1.Height - 70);
  // 楕円弧部面積
  image1.Canvas.Pen.Color := clRed;
  image1.Canvas.MoveTo(270, image1.Height - 85);
  image1.Canvas.LineTo(300, image1.Height - 85);
  image1.Canvas.Pen.Color := clGreen;
  image1.Canvas.MoveTo(300, image1.Height - 85);
  image1.Canvas.LineTo(330, image1.Height - 85);
end;

//----------------------
// 周長 楕円弧長計算
//----------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
  if not draw_ellipse then exit;    // 作図
  divisionpartition;                // 分割計算
  elliptic_integral;                // 不完全楕円積分計算
  elliptical_arc_area;
end;

//------------
// 初期設定
//------------
procedure TForm1.FormCreate(Sender: TObject);
begin
  ClientHeight := 479;
  ClientWidth  := 639;
  Image1.Top := 0;
  Image1.Left := 0;
  Image1.Height := ClientHeight;
  Image1.Width  := ClientHeight;
  Image1.Canvas.Font.Height := 15;
  Panel1.Top    := 8;
  Panel1.Left   := 502;
  Panel1.Height := 313;
  Panel1.Width  := 113;
end;

end.

    download EllipsePerimeterNo3.zip

各種プログラム計算例に戻る

      最初に戻る