カテナリー曲線と直線(傾き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.

    download catenary_tangent.zip

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

      最初に戻る