プロが教える店舗&オフィスのセキュリティ対策術

form1上に button1 と textbox1 を張り付けてください。
辺の長さ r1,r2,r3 が同じになるはずですがなりません。どなたか。助けて下さい。
私は、dimの integer,singleか、パソコンの解像度の問題か?とも思いますが?
よろしくお願いします。
pblic Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim g As Graphics = Me.CreateGraphics
Dim x1, y1 As Integer '点A の座標
Dim x2, y2 As Integer ' 点B の座標 
Dim x3, y3 As Integer '点Cの座標   点Aの周りにABを60度回転した点。


Dim r1, r2, r3 As Integer
Dim rd As Single = 60 * 3.14159 / 180 '60度回転
x1 = 500 : y1 = 400 ' ' 点A
x2 = 550 : y2 = 450 '点B

g.DrawLine(Pens.Black, x1, y1, x2, y2) ' 直線 AB
r1 = Math.Sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2)  'r1=AB

x3 = 500 + r1 * Math.Cos(rd)
y3 = 400 - r1 * Math.Sin(rd)

r2 = Math.Sqrt((x3 - x2) ^ 2 + (y3 - y2) ^ 2) ' r2=BC
r3 = Math.Sqrt((x3 - x1) ^ 2 + (y3 - y1) ^ 2) ' r3=AB

TextBox1.Text &= "x3=" & x3 & vbCrLf
TextBox1.Text &= "y3=" & y3 & vbCrLf
TextBox1.Text &= "r1=" & r1 & vbCrLf
TextBox1.Text &= "r2=" & r2 & vbCrLf
TextBox1.Text &= "r3=" & r3 & vbCrLf

End Sub
End Class

質問者からの補足コメント

  • 昔20年も前、vb6.0 を有償で買って参考書を頼りに勉強していたのですが
    回転の公式を思い出して2点を指定して正三角形を描くプログラム((?)を作ろうとしたのですが
    やはりできません。ここで再び挫折か!という心境です。見苦しい泣き言でした。

      補足日時:2015/02/25 17:04
  • それなりのコード(プログラムというのも恥ずかしいので)が、できたのですが
    点Aではなく、点Bの周りの回転になっているようです。(0,0)がformの右上にあることは知っているのですが、数学上公式とVBで使う定義式は違うのでしょうね。もうしばらく時間をください。

    No.1の回答に寄せられた補足コメントです。 補足日時:2015/02/28 17:11

A 回答 (3件)

ざっとコードを見ただけですが,回転する角度が間違っているようです。


X軸と直線ABの角度分だけ回転する角度から補正してやらないと,各頂点のなす角が60度になりません。

通常は,回転行列を掛けた式を展開ものを利用します。
http://ja.wikipedia.org/wiki/%E5%9B%9E%E8%BB%A2% …
この回答への補足あり
    • good
    • 0
この回答へのお礼

yune-kichi さんありがとうございました。張り付けて下さったwikipedia ページのおかげで思い出しました。ずーと昔の公式、行列の計算めんどうなですよね、掛け算、逆行列のあたり。回答者お二人のおかげでなんとか、それらしい三角形がかけましたが、三辺が等しくなりません許容範囲ですか?
こう結論してもいいですか? A(x1,y1),B(x2,y2)がある。線分ABを点Aの周りにラジアン角θだけ 回転したとき点B(x2,y2)は 点C(x3,y3)に移動する。
   x3=(x2-x1)*cosθ-(y2-y1)*sinθ+x1
   y3=(x2-x1)*sinθ+(y2--y1)*sinθ+y1 
残された問題はx2とx1,y2と,y1の大小関係でどう変わのかが私は理解できていません。
ご指導お願いします。お二人に感謝します。グラヒックスの最初の難関です。
今後ともよろしくお願い。

お礼日時:2015/02/26 18:09

(1)コンピュータの計算は有限の桁しか使えないので、どうしても誤差が出ます。


(特に√やπのような無理数)

(2)座標には整数型を使っているので、この時点で実数→整数の変換による誤差があります。
小数点以下を丸めるため、 |e|<1.0 の誤差があります。

例えば
r1 = Math.Sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2)  'r1=AB

中のSqrtの中の計算は、整数同士の加減乗算だけなので(桁溢れになるほどの大きな値でなければ)正確です。
ですが、 Sqrtで計算した段階で、 真の√((x2 - x1) ^ 2 + (y2 - y1) ^ 2) とは違います。(1)
これをIntegerの変数r1に代入するので、Single→Integerの型変換が行われます。このときに小数点以下が切り捨てられます(2)

x3 = 500 + r1 * Math.Cos(rd)
同様にrdは誤差を含みます。60π/360 を正確に表わすことはできません。
角度の誤差とCos(rd)自体の丸め誤差とが加わります。
その誤差を含むcos(rd)に、誤差を含むr1を掛けています。
これをx3に入れるので、また小数点以下が切り捨てられます。

と、たったこれだけの計算でも、誤差の発生が沢山あります。


詳しい対策は、「浮動小数点数 誤差 対策」とでも検索してみてください。


ひとまず、簡単なものは
○Singleではなく、有効数字の大きい Double型を使う。
 現在のPCでの計算なら、Singleを使う意味はありません(メモリサイズ以外)
 座標のx1,y1等もDoubleにします。
○内部の計算用と、画面座標とを分けて考える
 変数x1,y1をDoubleにしましたが、DrawLineでは整数です。
 このような場合は、DrawLineに指定するときだけCInt等を使って整数にします。
○定数は、用意されているがあったら使う
 πとして3.14159を使っていますが、これを 3.141592 とするだけで、cos,sinの値も結構変ってきます。なので、できるだけ誤差の少ないπを使いたいものです。
https://msdn.microsoft.com/ja-jp/library/system. …
そこで、Math.PIを使うと、Doubleで表現したときに最もPiに近い値が既に用意されています。
    • good
    • 1
この回答へのお礼

丁寧な説明ありがとうございます。integer,single,double,で何を使うか、いい加減にやっいぇきたの
が、いけなかっのです。

お礼日時:2015/02/28 17:30

x3 = 500 + r1 * Math.Cos(rd)


y3 = 400 - r1 * Math.Sin(rd)

これは、 (500,400)を中心に、(500+r1,400+0)の点から60度回転させた座標になります。
B点は(550,450)ですから、(500+r1,400+0)ではありません。

x4 = 500 + r1 * Math.Cos(0.0)
y4 = 400 - r1 * Math.Sin(0.0)
とでもして、0度の点がどこにあるのか、見てください
    • good
    • 0
この回答へのお礼

kmee さんありがとうございました。平行移動の事をきずきました。
二人のおかげで何とかそれらしい正三角形ができましたが、三3辺が微妙にちがうのです。
これはしかたないのでしょうか?あと、点Aと点Bの位置関係によって点Cの位置が違うのでは
という疑問です。このあたりについて、またご指導いただきたいのですが。
それらしくできたコードを投稿しますから、よろしくお願いします。
実は、kmee さんへのおれいを3時ごろかいて、そのあとno1の yune-kichi さんっへのお礼を
書いて全体を見るとkmee さんへのお礼が消えているのです。なんで?
数字おーばーだったということか?
今後ともよろしくお願いします。投稿はこの2月が初めてなのです。

お礼日時:2015/02/26 18:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!