内心を求めるには?

解決


ムー  2007-06-15 03:56:02  No: 26646

キャンバス上に3点(X1, Y1) , (X2, Y2) , (X3, Y3) があり、
三角形を描画しています。
この三角形の内心(三角形の各辺に接する内部の円の中心)
を描画したいのですが、どうすればよいのでしょうか?

各頂点の2等分線同士の交点が内心になるのですが
プログラムでどのようなコードを書けばよいのかわかりません。

すみませんが、教えてください。


ウォレス  2007-06-15 05:11:52  No: 26647

内心の座標を求めるのは結構難解なようです。
http://www.nn.iij4u.or.jp/~hsat/misc/math/centre/incentre.html
に求め方が書いてあります(が、中身は理解不能です)。
幸い中身が分からなくとも内心座標iは、
i= (1/(a + b + c))[aa→ + bb→ + cc→]
と出ています。
これで演算すればよろしかろうかと思います。
※一応、excelで確認してみました。

上記サイトで解説してありますが、
a = BC, b = CA, c = AB です。念のため。


ぽち  2007-06-15 07:22:53  No: 26648

おせわになります。

アプリケーションを終了しようと思い、
終了ボタンを作成し、そのノイベントにCloseと記述しましたが、
フォームが閉じない場合の原因と対処方法をご存知の方はおりませんか?
ちなみにフォーム右上のxを押した場合、反応はあるのですが閉じません。


ぽち  2007-06-15 07:27:08  No: 26649

上のメール間違って送ってしまいました。
大変失礼しました。


ムー  2007-06-16 03:32:04  No: 26650

すみません。
結局わかりませんでした。

位置ベクトルに直すと何が求まるのですか?
座標は、XとYの2つであらわしますが、
iは1つしかもとまりません。

i = (1/(a+b+c))[aa+bb+cc]

aa = a * a のことですよね。
それから、 aa+bb+cc が大かっこってことは
先に計算をするってことですか?
計算の順番でi の値が変わるとは思えないのですが

具体的にどうすればよいのでしょうか?
教えてください。


ウォレス  2007-06-19 03:52:54  No: 26651

ベクトルですから、直行する2つの値を持っています。
i(x,y)みたいにあらわします。
座標とベクトルとは共通するものと考えて差し支えないと思います。

aa→ = a * a  ではなく、a  とaベクトルを掛けることです。

紛らわしいですが、a  とaベクトル  とはマッタク違うものです。

a→=(x,y)のとき、
aa→ で、(ax,ay)となります。

高校1年生くらいで習う範囲だと思います。


ウォレス  2007-06-19 04:00:08  No: 26652

×直行
○直交

です。

それから[]カッコの意味は私もわかりません。()でも差し支えないと思います。

がんばってください。判らなければまた質問してください。


TS  2007-06-19 06:25:40  No: 26653

勉強不足でベクトル分かりませんが。
http://shigihara.hp.infoseek.co.jp/vx_index.htm
で取り急ぎ勉強してきました。
最初は面白かったですが、すぐ頭が付いていかなくなったので
適当に作ってみました。
var x1,y1,x2,y2,x3,y3:double;
    a,b,c:double;
    ix,iy:double;
begin
  x1:=0;
  y1:=0;
  x2:=0;
  y2:=100;
  x3:=100;
  y3:=0;
  a:=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));
  b:=sqrt((x3-x1)*(x3-x1)+(y3-y1)*(y3-y1));
  c:=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
  ix:=(1/(a+b+c))*(a * x1 + b * x2 + c * x3);
  iy:=(1/(a+b+c))*(a * y1 + b * y2 + c * y3);
     label1.Caption:='a='+FloatToStr(a)+':b='+FloatToStr(b)+':c='+FloatToStr(c)
                +':ix='+ FloatToStr(ix)+':iy='+FloatToStr(iy);
  ix:=(1/(-a+b+c))*(-a * x1 + b * x2 + c * x3);
  iy:=(1/(-a+b+c))*(-a * y1 + b * y2 + c * y3);
  Label2.Caption:='AAA'+FloatToStr(1/(a+b+c))+
                  'a='+FloatToStr(a)+':b='+FloatToStr(b)+':c='+FloatToStr(c)
                +':ix='+ FloatToStr(ix)+':iy='+FloatToStr(iy);
結果内心はまぐれで合っているようですが、後の答えが違います。
ウォレスさん正解の答えを教えて下さい。


「おやじ」改め「石橋屋」  URL  2007-06-19 18:51:51  No: 26654

ベクトル計算の枠組みを作ってから,
AI=(b/(a+b+c))AB+(c/(a+b+c))ACを計算すると見通しが良くなります。
ベクトル型変数と、それに関連した関数を作る。
type vector=recored
  x,y:double;
end;
function TForm1.plus(v1,v2:vector):vector;//ベクトルの加算
begin
  result.x:=v1.x+v2.x;
  result.y:=v1.y+v2.y;
end;
function TForm1.minus(v1,v2:vector):vector;//ベクトルの減算
begin
  result.x:=v1.x-v2.x;
  result.y:=v1.y-v2.y;
end;
function TForm1 mul(k:double;v:vector):vector;//定数との乗算
begin
  result.x:=k*v.x;
  result.y:=k*v.y;
end;
function dist(v1,v2:vector):double;//2つのベクトルの距離
begin
  result:=sqrt(sqr(v1.x-v2.x)+sqr(v1.y-v2.y));
end;
//****************************************
var pA,pB,pC,AI,AB,AC:vector;
    a,b,c,sum:double;
begin
  pA.x:=0;
  pA.y:=0;
  pB.x:=0;
  pB.y:=100;
  pC.x:=100;
  pC.y:=0;
  a:=dist(pB,pC);
  b:=dist(pC,pA);
  c:=dist(pA,pB);
  sum:=a+b+c;
  AB:=minus(pB,pA);
  AC:=minus(pC,pA);//AB,ACは点pAを原点としたベクトル
  AI:=plus(mul(b/sum,AB),mul(c/sum,AC));
  AI:=plus(AI,pA);//原点を移動
//AI.x,AI.yが内心の座標です。
end;


ウォレス  2007-06-19 20:35:46  No: 26655

今ちょっと試しが出来ない環境なのですが、

TSさんの、「結果内心はまぐれで合っているようですが、後の答えが違います。」に関して。。。

「後ろの答え」  とは
ix:=(1/(-a+b+c))*(-a * x1 + b * x2 + c * x3);
iy:=(1/(-a+b+c))*(-a * y1 + b * y2 + c * y3);
Label2.Caption:='AAA'+FloatToStr(1/(a+b+c))+
                  'a='+FloatToStr(a)+':b='+FloatToStr(b)+':c='+FloatToStr(c)
                +':ix='+ FloatToStr(ix)+':iy='+FloatToStr(iy);
のところでしょうか?
しかし、ここが何をしているのかわかりません。
aを-aにしているだけ・・?

しかし、これは何のため?
題意が内心を求めるコト  なわけですから、

ix:=(1/(a+b+c))*(a * x1 + b * x2 + c * x3);
iy:=(1/(a+b+c))*(a * y1 + b * y2 + c * y3);
label1.Caption:='a='+FloatToStr(a)+':b='+FloatToStr(b)+':c='+FloatToStr(c)
                +':ix='+ FloatToStr(ix)+':iy='+FloatToStr(iy);

まででよいのではないですか?
後ろ側の式も意味がわかりませんし・・
(頓珍漢なことを書いていたらごめんなさい)


ウォレス  2007-06-19 20:38:32  No: 26656

最近のDelphiには複素数ユニットがあるらしいのでこれを代用する、というのも手かもしれません。
C++だと四則演算や算術関数がそのままつかえたりしていますが、
Delphiだとどうなんでしょう?

もちろん、代用なのでベクトル同士の乗算とかはNGです。


TS  2007-06-19 21:24:07  No: 26657

>後ろ側の式も意味がわかりませんし・・
>http://www.nn.iij4u.or.jp/~hsat/misc/math/centre/incentre.html
に記載が有りました内心の次の傍心の計算をしたつもりでした。

すっきりしました。
ウォレスさんありがとうございました。


TS  2007-06-19 21:25:46  No: 26658

「おやじ」改め「石橋屋」さん計算式ありがとうございます。


石橋屋  2007-06-19 23:04:56  No: 26659

>最近のDelphiには複素数ユニットがあるらしいのでこれを代用する、というのも手かもしれません.
>もちろん、代用なのでベクトル同士の乗算とかはNGです。
複素数ユニット使うともっと簡単です,ベクトル同士の乗除算も可能です。
uses 節にvarCmplx を追加。
ベクトルの距離を求める関数を用意。
function TForm1.len(v1,v2:variant):double;
begin
  result:=sqrt(sqr(v1.real-v2.real)+sqr(v1.Imaginary-v2.Imginary));
end;
******
var pA,pB,pC,AI,AB,AC:variant;a,b,c,sum:double;
begin
  pA:=varComplexCreate(0,0);
  pB:=varComplexCreate(0,100);
  pC:=varComplexCreate(100,0);
  a:=len(pB,pC);
  b:=len(pC,pA);
  c:=len(pA,pB);
  sum:=a+b+c;
  AB:=pB-pA;
  AC:=pC-pA;
  AI:=b/sum*AB+c/sum*AC;
  AI:=AI+pA;
//内心の座標は(AI.real,AI.Imaginary)
end;


ウォレス  2007-06-21 20:34:26  No: 26660

成る程、複素数はそのように使うのですね。
石橋屋さんのを参考に私流に変えてみました。
ベクトルの長さはVarComplexAbs関数が定義されていますので用意する必要はありませんでした。

内接円を描画したくなるのが人情ですのでこれも試してみました。

内接円は既に中心(内心)が判っていますので半径rが判ればよいのですが、
実は簡単です。
シャノンの定理により、3辺a,b,cが判っていれば三角形の面積Sは
S=(s*(s-a)*(s-b)*(s-c))^0.5
です。(但し、s=(a+b+c+)/2 )

ところが三角形の面積Sは、内接円の半径rを用いて
S=(a+b+c)*r/2
と表せます。従って、
r=2*S/(a+b+c)
と求まります。

以下、コードです。ボタン、イメージ、メモをはっつけています。
メモは使っていませんが・・
----------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, varCmplx, StdCtrls, ExtCtrls, Math;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);

  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  pA,pB,pC,pI:variant;
  a,b,c,ss,sl,ss2,r:double;
  St : String;
begin
  pA:=varComplexCreate(4*50,6*50);
  pB:=varComplexCreate(9*50,2*50);
  pC:=varComplexCreate(1*50,1*50);

  a:=VarComplexAbs(pB-pC);
  b:=VarComplexAbs(pC-pA);
  c:=VarComplexAbs(pA-pB);

  ss := a+b+c;
  ss2:= (a+b+c)/2;

  pI:=1/ss*(c*pC+b*pB+a*pA);

  sl := Power( ss2*(ss2-a)*(ss2-b)*(ss2-c) ,0.5);
  r  := 2*sl/ss;

  //内心の座標は(I.real,I.Imaginary)
  {
    St := 'x=' + floattostr( pI.real) + '  y=' +floattostr( pI.imaginary );
    Memo1.Lines.Add(St);
  }

  //三角形の描画
  Image1.Canvas.Pen.Color := RGB(0,0,255);
  Image1.Canvas.MoveTo(pA.real ,pA.imaginary);

  Image1.Canvas.LineTo(pB.real ,pB.imaginary);
  Image1.Canvas.LineTo(pC.real ,pC.imaginary);
  Image1.Canvas.LineTo(pA.real ,pA.imaginary);

  Image1.Canvas.Pen.Color := RGB(255,0,0);

  //内接円の描画
  Image1.Canvas.Ellipse( pI.real -r,  pI.imaginary -r,  pI.real +r,  pI.imaginary +r );

  //内心の描画
  Image1.Canvas.Ellipse( pI.real -2,  pI.imaginary -2,  pI.real +2,  pI.imaginary +2 );

end;

end.


ウォレス  2007-06-21 20:50:46  No: 26661

なお、一般に、ベクトル同士の乗除算はベクトル空間上にマッピングされません。
(複素数は体を成していますので、複素数同士の四則演算が複素数上にマッピングされます。)

勿論、上記内心の演算にはベクトル同士の乗除算というものは出てきません。
従って、ベクトル同士の乗除算はNGと書きました。

(数学は大学1年生の前期終了レベルなので、間違っていたらご容赦ください)


ウォレス  2007-06-21 21:25:47  No: 26662

・・お腹が空いていた?ので間違えてしまいました。

× シャノンの定理
○ ヘロンの公式

ちなみにシャロンの定理とはサンプリング定理のことだそうです。
復元したい周波数の2倍以上の周波数でサンプリングすれば元の周波数を復元できる、っていう定理です。


TS  2007-06-23 21:52:09  No: 26663

私は最初の質問者ではありませんが、ムーさんが書き込みをされませんので
途中から質問させてもらったので代わりに
石橋屋さん、ウォレスさんに感謝します。
最初から順を追って解説していただいた様な形になり大変よくわかりました。
ありがとうございました。


ウォレス  2007-06-25 20:27:47  No: 26664

発言者が無反応なのは残念ですね。

私もDelphiで複素数ユニットをはじめてつかいました。
(Delphiでも演算子のオーバーロードができるんですね・・・汗)
勉強になります。
石橋屋さんに感謝します。

なお、C++だと複素数の利用はもっと簡単です^^;
exp(),abs()などの算術関数がそのまま使えますので。

若い頃、勉強のためにフィルタの周波数特性を描画するツールを作ったのを思い出しました。(実は今でも使っています^^)


石橋屋  2007-06-26 18:46:52  No: 26665

ウオレスさん、複素演算に興味を持っていただいてありがとうございます。
オリジナルの複素演算ライブラリーvarCmplxはバグを含んでいます。
回路系計算のように、変数の絶対値が小さくなると,Devide by zeroのような
エラーでとまります。私は,バグにパッチを当てて使っています。
なお,exp(),abs(),sin()なども使えます。何が使えるのかは,
ソースを覗かないと判らないようですが。


ムー  2007-07-03 20:04:49  No: 26666

みなさん、どうもありがとうございます。
無反応でほんとうにごめんなさい。

ベクトルについて勉強していたら
理解できず(頭がついていけず)に苦しんでいました。

ようやく、ここに書かれている内容が、少しわかるようになりました。
後はプログラムを作って試して見ます。
どうもすみませんでした。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加