カテナリー曲線と直線(傾きa)の接点
カテナリー曲線のx点の傾きはa=sinh(x/C)と簡単な式となっています。
x=Csinh-1(a)となり簡単に接点のx座標を求めることが出来ます。
逆双曲線関数の計算は、PC用の計算プログラムには標準で入っており、簡単に計算が出来ます。
左図には無いのですが逆双曲線関数のべき級数展開式は公開されており自分でプログラムを組んで値を求めることもできます。
プログラム
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, VclTee.TeeGDIPlus, VCLTee.TeEngine, VCLTee.Series, VCLTee.TeeProcs, VCLTee.Chart; type TForm1 = class(TForm) Memo1: TMemo; Panel1: TPanel; a_Edit: TLabeledEdit; C_Edit: TLabeledEdit; Chart1: TChart; Series1: TLineSeries; Series2: TPointSeries; Button1: TButton; Series3: TLineSeries; Label1: TLabel; Label2: TLabel; CheckBox1: TCheckBox; Series4: TPointSeries; procedure Button1Click(Sender: TObject); private { Private 宣言 } function datainput: boolean; procedure Drawing(yyt, yyb: double); public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} uses system.Math; var C : double; // カテナリー数 a : double; // 直線の傾き b : double; // 直線の切片 xs, xe: double; // X軸の範囲 yt, yb: double; // y軸の範囲 // 入力処理 function TForm1.datainput: boolean; var ch: integer; begin result := false; C := 0; val(C_edit.Text, C, ch); if (ch <> 0) or (C <= 0) then begin application.MessageBox('カテナリー数に間違いがあります。','注意',0); exit; end; val(a_edit.Text, a, ch); if ch <> 0 then begin application.MessageBox('直線の傾きに間違いがあります。','注意',0); exit; end; result := true; end; // 懸垂線作図 // 低い方の支持位置基準 procedure TForm1.Drawing(yyt, yyb: double); const K = 500; var xn : double; x, dx : double; y : double; i : integer; begin dx := (xe - xs) / K; // 懸垂線作図 for i := -10 to K + 10 do begin xn := i * dx + xs; // 計算位置 x := abs(xn); // 最大弛み位置からの距離 y := C * (cosh(x / C) - 1); // カテナリー数 y if (y < yyt) and (y >= yyb) then Series1.AddXY(xn, y); y := a * xn + b; // 直線 if (y < yyt) and (y >= yyb) then Series3.AddXY(xn, y); end; end; // カテナリー線と直線の接線計算の実行 procedure TForm1.Button1Click(Sender: TObject); var fd: double; x : double; ys, yc : double; xxs, xxe : double; yyb, yyt : double; begin xs := -1; xe := 1; if not datainput then exit; memo1.Clear; Series1.Clear; Series2.Clear; Series3.Clear; Series4.Clear; // 傾きaのカテナリー曲線のx座標 x := arcsinh(a) * C; // x := ln(a + sqrt(a * a + 1)) * C; xs := x; yc := C * (cosh(x / C) - 1); memo1.Lines.Add('接点座標'); memo1.Lines.Add(' X= ' + floatTostr(xs)); memo1.Lines.Add(' Y= ' + floatTostr(yc)); b := yc - a * x; // 切片 ys := a * x + b; // 直線y値 memo1.Lines.Add('直線の切片 b= ' + floatTostr(b)); xxe := sinh(x / C); memo1.Lines.Add('カテナリー線接点位置傾き = ' + floatTostr(xxe)); // グラフスケール設定 if xs < 0 then xe := -xs else begin xe := xs; xs := -xs; end; if a > 0 then begin if C > 1 then xs := xs - sqrt(C) else xs := xs - C; xe := xe + C; end else begin xs := xs - C; if C > 1 then xe := xe + sqrt(C) else xe := xe + C; end; xxs := xs; xxe := xe; yb := 0; if a > 0 then yyb := (a * xs + b) / 10 else yyb := (a * xe + b) / 10; if -yyb > C then yyb := -C; yt := yc; yyt := yc; if xe - xs > yt then begin fd := ((xe - xs) - yt) / 2; yyb := yb - fd; yyt := yt + fd; end else begin fd := (yt - (xe - xs)) / 2; xxs := xs - fd; xxe := xe + fd; end; fd := (xxe - xxs) / 10; // グラフ余裕分 xxs := xxs - fd; xxe := xxe + fd; yyb := yyb - fd; yyt := yyt + fd; if checkbox1.Checked then begin Series2.AddXY(xxs, yyt); Series2.AddXY(xxs, yyb); Series2.AddXY(xxe, yyb); application.ProcessMessages; end; Drawing(yyt, yyb); // グラフ Series4.AddXY(x, ys); // 交点 直線 end; end.