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

解決


おーどりー  2004-12-07 19:27:34  No: 87225  IP: [192.*.*.*]

ピクチャーボックス(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-07 21:21:11  No: 87226  IP: [192.*.*.*]

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

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

編集 削除
LESIA  2004-12-07 21:51:34  No: 87227  IP: [192.*.*.*]

恐らく、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 14:21:49  No: 87228  IP: [192.*.*.*]

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

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

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

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

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

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


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

編集 削除
L/D  2004-12-08 15:29:50  No: 87229  IP: [192.*.*.*]

画面上で表示できる最小単位は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-08 16:53:23  No: 87230  IP: [192.*.*.*]

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

編集 削除
punto  2004-12-08 16:57:51  No: 87231  IP: [192.*.*.*]

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

編集 削除
batchman  2004-12-09 09:38:28  No: 87232  IP: [192.*.*.*]

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

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-09 20:59:05  No: 87233  IP: [192.*.*.*]

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

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

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

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

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

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

編集 削除