3

手書きのストロークを描画するアプリケーションに取り組んでいます。ストロークはポイントのベクトルとして内部的に保存され、 に変換できますstd::vector<Gdiplus::Point>。点は互いに非常に接近しているため、各点を単純に描画すると、連続したストロークのイメージが得られます。

Graphics.DrawEllipseこれらのポイントを描画するために (GDI+) メソッドを使用しています。コードは次のとおりです。

// prepare bitmap:
Bitmap *bitmap = new Gdiplus::Bitmap(w, h, PixelFormat32bppRGB);
Graphics graphics(bitmap);

// draw the white background:
SolidBrush myBrush(Color::White);
graphics.FillRectangle(&myBrush, 0, 0, w, h);

Pen blackPen(Color::Black);
blackPen.SetWidth(1.4f);

// draw stroke:
std::vector<Gdiplus::Point> stroke = getStroke();
for (UINT i = 0; i < stroke.size(); ++i)
{
    // draw point:
    graphics.DrawEllipse(&blackPen, stroke[i].X, stroke[i].Y, 2, 2);
}

最後に、これbitmapを PNG 画像として保存するだけで、次の問題が発生することがあります。

問題

ストロークでこの「穴」を見たとき、もう一度ポイントを描画することにしましたが、今回は、幅と高さを に設定した楕円を1使用redPenして、幅を に設定しました0.1f。上記のコードの直後に、次のコードを追加しました。

Pen redPen(Color::Red);
redPen.SetWidth(0.1f);

for (UINT i = 0; i < stroke.size(); ++i)
{
    // draw point:
    graphics.DrawEllipse(&redPen, stroke[i].X, stroke[i].Y, 1, 1);
}

そして、私が手に入れた新しいストークは次のように見えました: 問題2

Graphics.DrawRectangleこの新しい赤いストロークを描画する代わりに使用するDrawEllipseと、このストローク (長方形を描画して描画) に異なる幅や穴ができることはありません。

長方形

円を描くとこの奇妙な動作が発生する理由は考えられません。を使用すると、ストロークが常に継続的で、決して変形しないのはGraphics.DrawRectangleなぜですか? ここで何が起こっているのか、誰か説明してもらえますか? 何か不足していますか?

ところで、私は Windows XP を使用しています (たとえば、既知のバグの場合)。どんな助けでも大歓迎です。

4

1 に答える 1

2

Graphics.DrawEllipse幅約 2px のペンで半径 2px の円を描画すると、直径約 4 ~ 5 px の塗りつぶされた円が描画されるという誤った仮定をしました。
しかし、このように円を描くとき、​​実際にはペンの幅に頼ることができないことがわかりました。このメソッドは、この形状の境界線の描画のみを目的としているため、塗りつぶされた楕円を描画するには、 を使用する方がはるかに優れていますGraphics.FillEllipse

考慮すべきもう1つの非常に重要な事実は、言及された両方の関数が「楕円の境界を指定する長方形の左上隅」を指定する座標をパラメーターとして取ることです。したがって、両方の座標から半径の半分を差し引いて、元の座標は、この円の中心を指定します。

新しいコードは次のとおりです。

// draw the white background:
SolidBrush whiteBrush(Color::White);
graphics.FillRectangle(&whiteBrush, 0, 0, w, h);

// draw stroke:
Pen blackBrush(Color::Black);
std::vector<Gdiplus::Point> stroke = getStroke();
for (UINT i = 0; i < stroke.size(); ++i)
    graphics.FillEllipse(&blackBrush, stroke[i].X - 2, stroke[i].Y - 2, 4, 4);

// draw original points:
Pen redBrush(Color::Red);
std::vector<Gdiplus::Point> origStroke = getOriginalStroke();
for (UINT i = 0; i < origStroke.size(); ++i)
    graphics.FillRectangle(&redBrush, origStroke[i].X, origStroke[i].Y, 1, 1);

次の結果が得られます。

正しいストローク

したがって、誰かが私と同じ問題に直面する場合の解決策は次のとおりです。

ここに画像の説明を入力

于 2013-02-07T16:17:27.093 に答える