等間隔で線をかいたのに、間隔が等しくならない

解決


おーどりー  2004-12-08 04:27:34  No: 87225

ピクチャーボックス(pctBar)
に以下のようなコードで直線を書こうとしました。

等間隔で、線をひくはずなのに実行してみると
どうみても不均等な線がひけてしまっています。

特に間隔の値を太さに近づけたときに不均衡さが
顕著になるようです。

この現象が生じる理由、回避する手段をおわかりの方が
いらっしゃいましたらご教授お願いします。

よろしくお願いします。

Private Sub cmdDraw_Click()

Dim i, 間隔, 太さ, 最大値 As Integer

間隔 = 20
太さ = 15
最大値 = 1000 / 間隔

pctBar.ScaleWidth = 1000
pctBar.ScaleHeight = 1000

pctBar.Cls

For i = 1 To 最大値
pctBar.Line (間隔 * i, 100)-(間隔 * i + 太さ, 900), , BF
Next

End Sub


Say  2004-12-08 06:21:11  No: 87226

誤差を小さくしたかったら、
ScaleModeをvbPixelにして、整数で座標指定して
縦横線のみを描画してください。

同じ幅でひいたはずの縦線と横線の幅が異なって見えたり、
斜め線に見えたり、ゆがんで見えるときは、
ディスプレイを調整してください。


LESIA  2004-12-08 06:51:34  No: 87227

恐らく、ScaleWidthとScaleHeightに値を代入しているからだと思います。
ScaleWidthとScaleHeightに値を入れると、例えば、pctBarが800×800ドット
だとしても、サイズが1000×1000になってしまいます。
画面に表示するときの最小単位はドットですので、実際の座標は
Int(800/(間隔 * i))となり誤差が生じるので不均等になります。

> pctBar.ScaleWidth = 1000
> pctBar.ScaleHeight = 1000

じゃなくて
pctBar.Width = 1000 + pctBar.Width - pctBar.ScaleWidth
pctBar.Height = 1000 + pctBar.Height - pctBar.ScaleHeight
とすれば、うまくいくと思います。


おーどりー  2004-12-08 23:21:49  No: 87228

すばやいお返事ありがとうございます。質問者です。

LESIAさんのご回答をみてなるほどと思い
どれだけの誤差が生じるか確かめてみました。

テストしたピクチャーボックスのピクセルサイズ(x方向)は6735だったので、
int(6735*間隔 / 1000) とint((6735*間隔 +太さ) / 1000)の
(実ピクセルへの変換式はこうですよね?)
差をとってみたのですが、線の間隔に対しては誤差3%程度、線の太さにいたっては1%もありませんでした。
実際に画面に出ている差はそれどころではないので、別の原因があると
思うのですが、他に考えられないでしょうか?

また、pctBar.Width = はピクチャーボックスの幅自体が変わってしまうので
できれば避けたいです。

Sayさんのディスプレイの調節に関しては、ピクチャーボックスが画面上の
どこにある場合も結果はかわらないので、大丈夫だと思います。

ScaleModeをピクセルにしても同じ結果が生じてしまいます。

もしここまでの情報でなにかわかる方いらっしゃいましたら
どうかよろしくお願いいたします。


L/D  2004-12-09 00:29:50  No: 87229

画面上で表示できる最小単位は1Pixelです。
VBの標準単位TwipはWindowsの画面プロパティーで変更がなければ、
1Pixelあたり15Twipです。(Screen.TwipsPerPixelX、TwipsPerPixelY)
座標(0, 0)と座標(14, 14)は同一Pixelです。

20Twip=1.3333333333333....Pixel
Twip=Pixel*TwipsPerPixel?
Pixel=Twip/TwipPerPixel?

# この辺の事はVBでグラフィックを書く人には基本知識だと思うけど?
# 入門書に書いてないのかな?


punto  2004-12-09 01:53:23  No: 87230

“座標(0, 0)と座標(14, 14)は同一Pixelです”
はちょっと違う.座標の受け口は大概 Sigle で,TwipsPerPixel? が15 なら,丸められて,(14, 14) は (15, 15) になってしまうだろう.
    “座標(0, 0)と座標(7, 7)は同一Pixelです”
のほうがいい.
“基本知識だと思うけど?”,“入門書に書いてないのかな?” は言わずもがなか….


punto  2004-12-09 01:57:51  No: 87231

訂正:  Sigle -> Single  です.すみません.


batchman  2004-12-09 18:38:28  No: 87232

そんな誤差が出る面倒な計算しなくても、
均等に線を引くだけならこれだけでいいんじゃないの?

Private Sub cmdDraw_Click()

    Dim i As Single, 間隔 As Single, 太さ As Single

    間隔 = 10
    太さ = 5

    pctBar.Cls
    pctBar.ScaleMode = vbPixels
    For i = 0 To pctBar.ScaleWidth Step 間隔
        
        pctBar.Line (i, 0)-(i + 太さ, pctBar.ScaleHeight), , BF
    Next

End Sub

>Dim i, 間隔, 太さ, 最大値 As Integer
それと、
この変数の宣言の仕方だと最大値以外は全部Variantになるよ


おーどりー  2004-12-10 05:59:05  No: 87233

質問者です。
みなさま、ありがとうございました。

普段VBでは組まないのに、都合でVBを使わざるをえなくなりまして・・・
おかげさまでよくわかりました。Twipsなんてあるんですね。

特にbatchmanさん、ありがとうございます。

>この変数の宣言の仕方だと最大値以外は全部Variantになるよ
これも知りませんでした!

どうも、ありがとうございました。
入門書も参考書もまったく手元にない状態なので助かりました。

おかげさまで作りたかったプログラムが完成しました。


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

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






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