だからそのジャギーを解消するのがアンチエイリアス処理だと思うのですが??
LineDDA()については,(今検索してみた結果からの想像ですが,)
このAPIを使う利点は単に
>アンチエイリアスをかけない場合の線を構成するピクセル群の座標
を次々にもとめるための方法(ブレゼンハムのアルゴリズムのようなもの)を
自前で実装せずにすむだけであって,
コールバック関数に渡されてきた
X,Y座標に基づいて何かしらの処理をするのはあなたです.
つまり,コールバック関数に渡されてきた位置(X,Y)の画素や
必要ならばさらにその隣接画素等に対して
ジャギーが目立たなくなるようにうまいこと描画処理を行う,ということです.
その描画処理の内容について私たちは今まで話をしていたはずなのですが…
で,LineDDAだのブレゼンハムだのいう話については
アンチエイリアス処理自体の達成に”必須ではなく”
「そこらへんの話で足踏みしているよりは,まずはアンチエイリアス処理の内容自体を実
装してみて効果を確認して
実際に採用する方法の選択などをするべきではないか?
なぜならば,その結果次第で,処理範囲等も変わってくるかもしれないから.」
ということを
1コ前の書き込み(2011/03/28)でご提案申し上げたわけです.
たとえば,100*100サイズのDIBがあったとして,そこに,式
Y = 3.14*X + 1.414
で表される直線を描きたいとしましょう.
今,処理効率を度外視して,(2重のforループか何かで)
DIB内の全ての画素
(X座標:0~99 , Y座標:0~99)
に対して,ためしに以下のような処理を行ってみることにします.
画素(x,y)に対して…
(1)座標(x,y)と直線との距離Lを計算する
(2)Lの値に基づいて,この画素に対して描画すべき濃度α(0~100%)を決定する.
L=0 のときα=100%とし,
Lが大きくなるほどαは小さくなるようにする.ただし,
L>一定値のときにはα=0%とする(そのような画素には描画しない)
(3)α>0であれば,この画素(x,y)に濃さαで描画する
ここで,処理ステップ(2)の内容,
すなわち Lからαを決定する具体的な方法 はあなたの裁量にゆだねられます.
αとLの関係は単純な線形?
あるいはαはLの2乗に比例して減衰?
α=0とするLの閾値はどれくらい?
…
仮に,いろいろ調整してみたら,それなりの結果が得られるようになったとしましょう.
しかし,全画素に対して処理したのに
実際に処理ステップ(3)で描画が行われた画素の数というのは,全画素数にくらべると
かなり少ないはずです.
「なんか効率わるいなぁ…全画素走査しなくて済む方法はないだろうか?」
そこで初めてLineDDA()とか何とかいう効率UPのための話が出てくるわけです.
線が通りそうな位置だけに処理してやればいいということですね.
しかし,実際に処理すべき範囲は,まさに処理ステップ(2)の調整内容次第であって,
この話の場合,最初から決めることはできないのです.
または,こんな処理内容ではそもそもあなたが求めるレベルに達しないかもしれず,
他の方法を採用することになるかもしれません.
その場合,処理自体が変更になるのだから,処理すべき範囲も変わってくるでしょう.
ホウジョウウサギさん、すみません。混乱しています。
アンチエイリアス処理はスーパーサンプリング法で成功しています。
しかしスーパーサンプリングの為には太い線を描画する必要があります。
>線を長方形とみなし、ドットが長方形内ならば点を打っていく方法
のほかにもっと良いアルゴリズムをお聞きしています。
その場合どうすれば良いのでしょうか?
>混乱しています
私もです.
ひょっとして,
表題である
>アンチエイリアスがかかった線の描画
のためのアルゴリズム を聞いているのではなくて,
すでに
”アンチエイリアス効果を得るための方法としては
スーパーサンプリングでやることは決定事項”
であって,
単に
>太い線を描画
する方法が知りたいだけ ということなのですか??
だとしたらあなたが実際の描画につかうAPIなりなんなりの機能で
いいようにやればいいだけなのでは…
(たとえばWin32APIなら太いペンで線を描けばいい)
しかしそれだと
>ジャギーが目立ちませんか
なんて話が出てくるのが全く解せない…
>ジャギーが目立ちませんか
に関しては、ホウジョウウサギさんと同意見です。
基本的な考え方は提示できると思いますけれど、
細かい調整に関してはご本人で行うしか無いと思います。
それこそトライアンドエラーの世界ではないかと思います。
で、この辺のさじ加減と言うのがある意味ノウハウかなと思うので
掲示板で聞いてポンと出てくる話では無いのではとも思います。
つまりこの通りにやれば誰でもうまく行きますと言う方法を
求めているのであれば、多分出てこないと思います。
考え方とか処理の方向性をヒント程度に得る事はできても
そこから先は自分でやってみるしか無いと思いますよ。
もうちょっと言うと、
アンチエイリアスは厳密な意味で1ドットの線を書くために方法論では
ないわけですから、あくまでも見た目でその太さに見えるように書くと言う
話です。実際には1ドットではなくてそれ以上の点が表示されています。
その上でドット毎のガンマ値等を調整する事で太さがさほど変わらない範囲で
線を綺麗に見せているわけです。
厳密に1ドットの線が必要なのであれば、表示をドットで行なっている以上
不可能だと思いますよ。太さが殆ど変わらないように見せる為に補間で
打つドットの色の調整をどうするのかがノウハウであり、
その部分をいかに軽い処理でうまい効果を出すかは自分で考えてください
と言う話だと思います。
すみません。線を書くアルゴリズムを探していまして、
長方形として描く方法を提示した上で他に線を描く方法を聞いています。
そこで、点をなんども打つという話と、
ホウジョウウサギさんの
>■■■□△
> △□■■■■□△
> △□■■■
補間のアルゴリズムを頂きました。
今質問しているのは、点を何度も打つ方法を用いた場合の実装方法でして、
点はどの位置にどの半径で打つべきなのでしょうか?
うーん。
一番単純な話で言えば、1ドットの点を座標計算しつつ打つと言う話かと。
これ以上は細かい点は打てないのでこれが基本ですね。
これだと解像度いっぱいの細かさですからこれ以上綺麗に打つのは無理です。
ですが、打つ店の数が増えるのでスピード的には不利になります。
逆に太さをある程度考えた上でドットではなくて塗潰した丸で書くと
関数呼出の回数は減らせそうですが、当然、線は汚くなりますね。
で、既に書いていますが、この辺の内容も含めてご自分で調整する内容だと
思います。基本的な考え方は既に提示されていますからこれを実際の
プログラムに落とし込む作業はご自身でやる必要があるでしょう。
一般論的は半径と言うのは私にもわかりません。
逆にこの部分をどう実装するかがノウハウなのではと思います。
というか、ドットを打つ座標計算の方法がそもそもわからないと
言われていますか?
通常の数学レベルの話で何とかなるはずです。
直線なのですから一次関数のグラフがわかっていれば、
一般化できるはずですよ。
>というか、ドットを打つ座標計算の方法がそもそもわからないと
>言われていますか?
わかります
とりあえず、PATIOさんのおっしゃるとおり、実際に実装してみます。
また問題が発生したら新たにスレたてます。
ホウジョウウサギさん、長らくお付き合いいただきありがとうございました。