直線と曲線で閉じられた範囲を塗りつぶしたい – プログラミング – Home

直線と曲線で閉じられた範囲を塗りつぶし...
 
通知
すべてクリア

[解決済] 直線と曲線で閉じられた範囲を塗りつぶしたい


あお
 あお
(@あお)
ゲスト
結合: 21年前
投稿: 45
Topic starter  

いつも参考にさせていただいています。
早速ですが、質問させていただきます。

曲線と直線で閉じらた図形を描画しながら中身を塗りたいのですが、
どのようにしたらいいのか分かりません。

たとえば
____
(____)
こんな感じの図形を描画して塗りたいのですが、
そんなことができるAPIはあるのでしょうか?
描画するだけならPolyBezierToとかで何とかなりそうですが、
塗りつぶしを実行してくれません。
何か方法はないでしょうか?

それとも、半円を描画して塗りつぶして、四角を描画して塗りつぶして
としていかなくてはならないのでしょうか?


引用未解決
トピックタグ
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

こんな関数があるみたいですが、これでは駄目ですか?

BOOL ExtFloodFill(
HDC hdc, // handle to device context
int nXStart, // x-coordinate where filling begins
int nYStart, // y-coordinate where filling begins
COLORREF crColor, // fill color
UINT fuFillType // fill type
);

ちなみに私がこの関数を探し当てた経路。
1.たぶん、あるとしたらCDCクラスのメッソドだろう。
2.CDCクラスのメッソドを見ていたらFloodFillと言うメソッドがある。
3.説明を見るとどうやら使えそう。
4.説明の下のほうに::FloodFillがあるからAPIではこれだろう。
5.FloodFillのところにExtFloodFillを使えと書いてある。
6.ExtFloodFillを見つけてめでたしめでたし。

参考までに。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

蛇足ですが、ExtFloodFillは塗り潰しが早いかと言うと
多分原理的に早いとは考えにくいです。
指定した点を基点に境界にたどり着くまで全方向塗り潰すと言うのは
実は効率が悪いから。

EllipseとRectangleでも使って書いたほうが早いかもしれません。
あと、形状が
____
(____)

だからと言って半円である必要はないです。
どうせ矩形が乗っかるなら円で書いても同じ事です。

この辺は、実験した結果で書いているわけではなので
実際に自分で確認してみた方がいいと思います。


返信引用
PIP
 PIP
(@PIP)
ゲスト
結合: 22年前
投稿: 16
 

リージョンを使う、とかどうですか?


返信引用
あお
 あお
(@あお)
ゲスト
結合: 21年前
投稿: 45
Topic starter  

PATIO 様お返事ありがとうございます

ExtFloodFillを調べてみて実行してみたのですが、
以下のプログラムを実行したのですが
うまく塗ることができません。
単純に円を描画して円の中を塗ろうと思ったんですが、
円しか描画されません。関数自体は1を返すので成功しているはずです。
何が悪いのかよろしければ教えてください。

----------プログラム--------------------
hPen = CreatePen(PenStyle, 1, RGB(0,0,255));
oldPen = SelectObject(hDC, hPen);
hBrush = GetStockObject(NULL_BRUSH);
oldBrush = SelectObject(hDC, hBrush);

Ellipse(hDC, x1, y1, x2, y2);// 円の描画
// 円の中心を指定して塗りつぶす
rst = ExtFloodFill(hDC, x0, y0, RGB(0,0,255), FLOODFILLBORDER);

SelectObject(hDC, oldBrush);
DeleteObject(hBrush);
SelectObject(hDC, oldPen);
DeleteObject(hPen);
----------ここまで--------------------

PIP 様お返事ありがとうございます。
初心者でよく分からないのですが、リージョンで曲線混じりの
閉じられた範囲を指定できるのでしょうか。
CreatePolyPolygonRgnを使っても無理なようなんですが。
よろしければ教えてください。


返信引用
FrozenAquarium
 FrozenAquarium
(@FrozenAquarium)
ゲスト
結合: 22年前
投稿: 22
 

CreatePolyPolygonRgn
を使うのならば
普通にPolygon(省略)
で描画できると思います。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

> hBrush = GetStockObject(NULL_BRUSH);

問題はここでしょ。
普通のブラシを使わないのに特別な理由があるのでないなら、
GRAY_BRUSHとかで動作確認ができます。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

まず、リージョンを使うのであれば、
円のリージョンと矩形のリージョンを作成し、CombineRgnで合成すれば作成できます。
Polygonでも表現可能ですが、円弧の部分をPolygon表現するのって結構面倒ですよ。
大きさが同じなら後はOffsetRgnで移動させれば、複数個処理も可能ですね。
リージョンは複雑な形のクリッピングとか描画に使うにはいい機能ですね。
ただ、生成、破棄を繰り返す必要はあるような場合はそのオーバーヘッドが気になるので
その辺は便利さとのトレードオフで考えた方がいいと思います。
決まった形を継続して使う場合には、最初に作っておいて使いまわしとかも
可能だと思うのでその場合はかえって効率が良いでしょう。

塗り潰しがうまく行かないのはたいちうさんの指摘どおりです。
NULL_BRUSHにして塗り潰されるわけがありません。
ExtFloodFillは指定されているBrushで塗り潰すのですから
ExtFloodFillを実行する前にBrushを自分が塗り潰しを行いたい色とスタイルのBrushに
変更するようにしてください。


返信引用
あお
 あお
(@あお)
ゲスト
結合: 21年前
投稿: 45
Topic starter  

FrozenAquarium さまお返事ありがとうございます。
Polygonだと直線(斜線含む)でしか描画できないと思うのですが、
曲線を含んだ範囲の指定は可能なのでしょうか?
ヘルプを見ても多角形としか説明されていないのですが、
曲線は扱えるのでしょうか?

たいちう さまお返事ありがとうございます。
hBrush = GetStockObject(NULL_BRUSH);
を修正することで塗りつぶすことができました。
空のブラシで塗っていただけだったんですね。
ありがとうございました。

hBrush =CreateHatchBrush(HS_BDIAGONAL,RGB(0,0,255));
oldBrush = (HBRUSH)SelectObject(hDC, hBrush);
することで斜線で塗りつぶすこともできました。

ExtFloodFillでの質問なんですが、
ExtFloodFillを使用すると前回書いた図形の中身も塗られてしまいます。
たとえば、
1.青で四角を描画
2.青で円を描画
3.円を塗りつぶしために円の中心を指定してExtFloodFillを実行
すると結果、円と四角が塗りつぶされます。
円だけ塗りつぶす方法はないのでしょうか?


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

蛇足。
GetStockObjectで取得したハンドルは、DeleteObjectして無くても大丈夫です。
しても問題ないそうですけれど。
まあ、GetStockObjectで取ったとか、Createしたとかで判断ミスをするより、
一律でDeleteObjectってのも悪い手じゃないですけれどね。


返信引用
あお
 あお
(@あお)
ゲスト
結合: 21年前
投稿: 45
Topic starter  

PATIO 様お返事ありがとうございます。

リージョンでCombineRgnとFillRgnを使用して何とかなりそうな感じです。
ありがとうございました。

GetStockObjectってDeleteObjectが必要ないんですね。
取り出したからには消さないといけないのだと思ってました。
ありがとうございます。一つ賢くなりました。

ExtFloodFillの疑問は残りますが、
一応、曲線と直線で閉じられた範囲の塗りつぶし方は分かりましたので
解決とさせていただきます。
PATIO様 PIP様 FrozenAquarium様 たいちう様お返事ありがとうございました。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

問題自体は解決したそうですが。。。

> すると結果、円と四角が塗りつぶされます。
> 円だけ塗りつぶす方法はないのでしょうか?

もしかしてExtFloodFillをコメントアウトしても
塗りつぶされていませんか?
塗りつぶされたのは、NULL_BRUSHを選択して
いないから、というわけでは?

1.NULL_BRUSH、青線で四角と円を描画。
2.ブラシを青に変更。
3.ExtFloodFill

でできましたが。
もしできないなら、四角と円の位置関係等を説明するか
ソースを載せてください。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

多分、たいちうさんのがビンゴかと私も思います。

>hBrush = GetStockObject(NULL_BRUSH);
>を修正することで塗りつぶすことができました。

と書かれていますから、元の行をそのまま変更しちゃったんでしょう。

EllipseもBrushに依存すると言うところを失念しているのか、
それともサンプルソース通りに書いただけでNULL_BRUSHにしている意味を
理解できていなかったのかですね。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

> EllipseもBrushに依存すると言うところを失念しているのか、
> それともサンプルソース通りに書いただけでNULL_BRUSHにしている意味を
> 理解できていなかったのかですね。

実は私もNULL_BRUSHをGRAY_BRUSHに変えただけだったから、
2004/02/26(木) 10:16:33
の投稿のときに塗られてたのは、Ellipseのおかげであり、
その後のあおさんの質問でやっと気づいたということは誰にも言えない。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました