4

MouseMove イベントに従って、かなり密な GraphicsPath を作成しています。移動中のフィルタリング以外に、事後に GraphicsPath を単純化するルーチンはありますか?

また、「ベクターベースの塗りつぶし」を実装したいと考えています。これにより、別の非常に密集したパスが作成されます。

限界を超えて変化するか、変化がこの限界に達するまで、各線の方向を比較する必要があると思います。または、他のすべてのポイントを単純に消去することもできます。むしろ粗雑。

ビルトイン ルーチンまたは標準アルゴリズムを期待していました。しかし、おそらく私は正しい検索語を使用していません..?

すべての提案に感謝します。

4

2 に答える 2

2

この質問を読んで、以前の投稿を思い出しました。そのため、最終的に単純な削減スキームを実装することにしました。

List<PointF> ReducePath(List<PointF> points, float epsilon)
{
    if (points.Count < 3) return points;
    var newPoints = new List<PointF>();
    newPoints.Add(points[0]);
    float delta = 0f;
    float prevAngle = (float)(Angle(points[0], points[1]) /10f);
    for (int i = 1; i < points.Count - 1; i++)
    {
        float ang = Angle(points[i-1], points[i])/10f;
        delta += ang - prevAngle; 
        prevAngle = ang;
        if (Math.Abs(delta) > epsilon)
        {
            delta = 0;
            newPoints.Add(points[i]);
        }
    }
    newPoints.Add(points[ points.Count -1]);
    return newPoints;
}

float Angle(PointF p1, PointF p2)
{
    if (p1.Y == p2.Y) return p1.X > p2.Y ? 0 : 180;
    else if (p1.X == p2.X) return p1.Y > p2.Y ? 90 : 270;
    else return (float)Math.Atan((p1.Y - p2.Y)/(p1.X - p2.X));
}

//float Slope(PointF p1, PointF p2)
//{
//    if (p1.Y == p2.Y) return 0;
//    else if (p1.X == p2.X) return 12345;
//    else return (p1.Y - p2.Y)/(p1.X - p2.X);
//}

イプシロン値が 1、0.1、および 0.01 の場合の結果を次に示します。

ここに画像の説明を入力

GraphicsPath.PathPointsは読み取り専用なので、新しいポイント リストからパスを再作成する必要があることに注意してください。

更新:勾配の代わりに 1°/10 で機能するように数学を更新し、Slope関数を関数に置き換えましたAngle..これにより、さまざまな方向でより均一な結果が得られるはずです..

更新 2:

エフライムに称賛を。適切な開始角度を使用するために提案された編集を追加しました..

于 2018-06-06T07:56:04.010 に答える
1

GraphicsPath.GetBoundsの使用を検討しましたか? そのページに良い例があります。

「返された外接する四角形のサイズは、エンド キャップの種類、ペンの幅、およびペン留め制限の影響を受けるため、境界パスに「緩い適合」を生成します。近似式は次のとおりです。最初の外接する四角形はによって膨張します。ペンの幅であり、この結果に留め継ぎの制限を掛けて、さらにエンド キャップを許可するための追加のマージンを加えます。」

于 2014-03-21T09:06:04.870 に答える