3

この質問は私には説明するのが非常に難しいので、いくつかの画像とテキストで説明します。

鋼の彫刻機の場合、.NET の通常のグラフィックス フレームワークを使用して、彫刻機に送信される「ドキュメント」を作成する必要があります。これは、通常のプリンターと同じように処理されます。問題のマシンは次のマシンです。

http://www.rolanddga.com/products/impactprinters/mpx90/features.asp

これでC#でテキストアウトラインを印刷できます:

// ALL UNITS ARE SET IN MILIMETERS (MM)

Graphics g = <instantiated from my printers-printpage-event>;

// The following values are set as "constants" here for the purpose of my question
// they normally are passed as parameters
string s = "ABC";
float fontSize = 4.0F;
RectangleF r = new RectangleF(0, 30.0F, 100.0F, 40.0F);

StringFormat sfDraw = new StringFormat();
sfDraw.Alignment = StringAlignment.Center;
FontStyle fStyle = FontStyle.Regular;

using (var gpDraw = new GraphicsPath())
{
  gpDraw.AddString(text, fFamily, (int)fStyle, fSize, r, sfDraw);

  SolidBrush brushFG = new SolidBrush(Color.Black);
  Pen pen = new Pen(brushFG, 0.01F);

  g.DrawPath(pen, gpDraw);
}

次のような出力が得られます: http://i47.tinypic.com/mruu4j.jpg

私が今欲しいのは、このアウトラインを埋めることです。単純にブラシで塗りつぶすだけではありません (g.FillPath(brushFG, gpDraw) で簡単に実現できます)。

代わりに、この画像に示すように、より小さなアウトラインで「塗りつぶす」必要があります: http://i46.tinypic.com/b3kb29.png

(異なる線の色は、例をわかりやすくするためにのみ使用されています)。

Photoshop で例を作成したとき、私が実際にやろうとしているのは、Photoshop の選択/変更/契約にある機能を模倣することであることに気付きました。

しかし、これをどのように達成するかについては、頭が痛いところです。

何か助けはありますか?私は完全な解決策を探しているわけではありませんが、現時点では完全に立ち往生しています。私は単純なスケーリングを試みましたが、これはおそらく間違った方法です (正しい結果が得られないため...)

UPDATE 2012-07-16:私は現在、OffsetPolygonsと呼ばれる素晴らしい機能を持つClipper Library http://www.angusj.com/delphi/clipper.phpを使用しています。

私のテストコードはここに示されています: http://pastie.org/4264890

単一のポリゴンのみで構成されているため、「単一」のポリゴン (たとえば「C」) で問題なく動作します。「O」は、内側と外側の 2 つのポリゴンで構成されています。「あ」も同様。そして、これらは私にいくつかの問題を引き起こします。これらの画像を参照してください。

C: http://i46.tinypic.com/ap304.png O: http://i45.tinypic.com/35k60xg.jpg A: http://i50.tinypic.com/1zyaibm.png B: http:/ /i49.tinypic.com/5lbb40.png

あなたは写真を手に入れます(ふふふ... ;-)

問題は、GraphicsPath からすべてを単一のポリゴンとして抽出することだと思いますが、実際には 2 つ (A と O の場合)、B の場合は 3 つです。

Clipper の OffsetPolygons は実際にはポリゴンの配列を取るので、これを正しく行うことができると思います。しかし、GraphicsPath から別のポリゴンとしてパスを抽出する方法がわかりません。

UPDATE 2012-07-16 (後日):

さて、私は実際にそれをやってのけることができました。同様の問題を抱えている他の人に役立つことを期待して、回答で説明します。

そして、途中で助けてくれたすべての人に感謝します!私が自分の答えを受け入れる唯一の理由は、他の人がこの質問から完全な解決策で利益を得ることができるようにするためです.

4

2 に答える 2

2

An algorithm for inflating/deflating (offset, buffering) polygons を見てみましょう- 質問者は実際に逆の操作について尋ねていますが、そこの答えはあなたのケースにも当てはまります。それらの 1 つ (最高評価) には、C# バージョンのオープン ソース ライブラリへのポインターがあります。

ちなみに、あなたが説明する操作の通常の名前は「ポリゴンオフセット」です。

于 2012-07-13T08:09:44.740 に答える
1

Clipper ライブラリの使用は、戦いの半分に過ぎませんでした。

GraphicsPath からすべてのポイントを 1 つの配列で抽出したため、2 つの別々のポリゴン (「A」の場合) に基づいて誤って形の悪いポリゴンが作成されました。

代わりに、GraphicsPath の PointTypes 配列プロパティを調べる必要がありました。ポイントの PointType == 0 は常に、新しいポリゴンの始まりを意味します。したがって、抽出メソッドはこれを使用し、代わりに単一のポリゴンではなくポリゴンの配列を返す必要があります。

private ClipperPolygons graphicsPathToPolygons(GraphicsPath gp)
{
    ClipperPolygons polyList = new ClipperPolygons();
    ClipperPolygon poly = null;

    for (int i = 0; i < gp.PointCount; i++)
    {
        PointF p = gp.PathPoints[i];
        byte pType = gp.PathTypes[i];

        if (pType == 0)
        {
            if (poly != null)
                polyList.Add(poly);
            poly = new ClipperPolygon();
        }

        IntPoint ip = new IntPoint();
        ip.X = (int)(p.X * pointScale);
        ip.Y = (int)(p.Y * pointScale);
        poly.Add(ip);
    }
    if (poly != null)
        polyList.Add(poly);

    return polyList;
}

Clipper の OffsetPolygons は、実際にはポリゴンのリストを必要としているため、これは以前から明らかだったはずです。

コード全体はここで見ることができます: http://pastie.org/4265265

興味がある方は、テスト プロジェクト全体をここに圧縮して、Visual Studio で開いてコンパイルしてください。

http://gehling.dk/wp-content/uploads/2012/07/TestClipper.zip

速度に関しては最適化されていません。

/ カルステン

于 2012-07-16T10:24:50.107 に答える