5

次のような PathGeometry.Combine を使用して比較する必要がある PathGeometry の 2 つの巨大な (>100000 アイテム) コレクションがあります。

List<PathGeometry> firstList;
List<PathGeometry> secondList;
[...]

foreach (PathGeometry pg1 in firstList)
  foreach (PathGeometry pg2 in secondList)
  {
    PathGeometry intergeo = PathGeometry.Combine(pg1, pg2, GeometryCombineMode.Intersect, null);
    if (intergeo.GetArea() > 0)
    {
      // do whatever with intergeo.GetArea()
    }
  }

驚いたことに、PathGeometry は GUI の一部であり、ディスパッチャーを使用します。これは、Parallel.ForEach() を使用して GUI を使用せずにバックグラウンド スレッドで計算を実行するため、問題を引き起こすことがあります。

そのため、GUI に接続されていない PathGeometry の代替を探しています。
私の図は非常に複雑で、多数の PathFigures を PathGeometry.Figures に追加しています。

肥大化した政府の xml ファイルからこれらの PathGeometry を自分で作成しているので、代わりに別のものを作成しても問題ありません。しかし、この図の赤い領域など、両方のジオメトリがカバーする領域を取得するために、これらのジオメトリの 2 つの交差を作成する関数が必要です (それらを相互に追加するのではありません)。

ここに画像の説明を入力

4

3 に答える 3

3

オブジェクトを使用する代わりに、ジオメトリ「mini-langauge」Path.Dataを使用して文字列に解析するのはどうですか?PathGeometry

たとえば、次のようなものを作成する代わりに、次のようにします。

<Path Stroke="Black">
    <Path.Data>
        <PathGeometry>
            <PathFigure IsClosed="true" StartPoint="10,100">
                <LineSegment Point="100,100" />
                <LineSegment Point="100,50" />
            </PathFigure>
        </PathGeometry>
    </Path.Data>
</Data>

あなたが作成することができます

<Path Stroke="Black" Data="M 10 100 L 100 100 L 100 50 Z" />

または、あなたの場合、XAMLはおそらく次のようになります。

<Path Stroke="Black" Data="{Binding MyPathProperty}" />

Path.Dataは、特定の形式であることが期待される文字列であり、パスのジオメトリを描画するためのより短い方法です

上記のリンクから取得した、文字の意味と予想されるパラメータのリストを次に示します。

  • F値-Geometry.FillRuleプロパティを設定します。EvenOddの場合は0を使用し、NonZeroの場合は1を使用します。このコマンドは、文字列の先頭に表示する必要があります(使用する場合)。

  • M x、y-ジオメトリの新しいPathFigureを作成し、その開始点を設定します。このコマンドは、F以外の他のコマンドの前に使用する必要があります。ただし、描画シーケンス中にこのコマンドを使用して、座標系の原点を移動することもできます。(Mは移動を表します)。

  • L x、y –指定されたポイントにLineSegmentを作成します。

  • H x –指定されたX値を使用し、Y値を一定に保ちながら、水平線分を作成します。

  • V y-指定されたY値を使用し、X値を一定に保ちながら、垂直線分を作成します。

  • radiusx、radiusY、degrees isLargeArch、isClockwise x、y –指定されたポイントにArcSegmentを作成します。円弧を表す楕円の半径、円弧が回転する度数、およびIsLargeArcプロパティとSweepDirectionプロパティを設定するブールフラグを指定します。

  • C x1、y1 x2、y2 x、y-(x1、y1)および(x2、y2)の制御点を使用して、指定された点にBezierSegmentを作成します。

  • Q x1、y1 x、y-(x1、y1)に1つのコントロールポイントを使用して、指定されたポイントにQuadraticBezierSegmentを作成します。

  • S x2、y2 x、y-前のBezierSegmentの2番目の制御点を新しいBezierSegmentの最初の制御点として使用して、滑らかなBezierSegmentを作成します。

  • Z-現在のPathFigureを終了し、IsClosedをtrueに設定します。IsClosedをtrueに設定したくない場合は、このコマンドを使用する必要はありません。代わりに、新しいPathFigureを開始したり、文字列を終了したりする場合は、Mを使用してください。

たとえば、上記のサンプル(M 10 100 L 100 100 L 100 50 Z)で使用されている文字列は、次のように分類できます。

  • M10100-10,100でパスを開始
  • L100100-100,100まで線を引きます
  • L10050-100,50まで線を引きます
  • Z-終了文字列

Path.Dataデータベースから読み取りを行う場合は、パスのx、y開始位置を含む文字列を作成することからM x y始め、x y次にセグメントを1つずつ読み取り、上記の省略形を使用して文字列に追加します。 、次に文字列をで終了しますZ

大文字と小文字の意味が異なることに注意してください。大文字はパスセグメントに絶対値を指定していることを意味し、小文字は最後のセグメントを基準にしていることを意味します。

たとえば、セグメントに「」と表示されている場合は"L 10 10"、グリッド上の位置10,10に線を引くことを"l 10 10"意味し、現在の位置から上に10、右に10の線を引くことを意味します。

PathGeometryデータベースから読み取られる場合は、それぞれPathGeometryを文字列に変換してから、文字列を結合する必要があります。

例として、いくつかの大まかなコードを示します。私はそれがうまくいかないことを知っています、しかしうまくいけばそれはあなたを正しい方向に向けることができます

編集

編集した質問に基づくと、データ項目はとして保存されているようです。そのため、オブジェクトを文字列に変換してから、文字列を組み合わせるPathGeometry必要がある場合があります。PathGeometry

これは非常に大まかな例です。私はPathGeometryオブジェクトにあまり精通していないので、構文が間違っていて、ロジックも少しあると確信していますが、正しい方向に向けることができれば幸いです。

foreach (PathGeometry pg1 in firstList)
    foreach (PathGeometry pg2 in secondList)
    {
        var s1 = ConvertGeometryToString(pg);
        var s2 = ConvertGeometryToString(pg2);

        // Ideally you probably wouldn't want this until you have your 
        // full PathGeometry string built, but I'm not sure what you're doing
        // with the object so left it in anyways
        PathGeometry intergeo = Geometry.Parse(s1 + s2);

    }
}


string ConvertGeometryToString(PathGeometry pg)
{
    StringBuilder sb = new StringBuilder();

    foreach(var figure in pg.PathFigures)
    {
        sb.Append("M " + figure.StartPoint);

        foreach(var seg in figure.Segments)
        {
            if (seg is LineSegment)
                sb.Append(" L " + ((LineSegment)seg).Point);

            else if (seg is ArcSegment)
            ... etc

        }

        if (figure.IsClosed)
            sb.Append(" Z");
    }

    return sb.ToString();
}
于 2012-09-25T16:08:25.437 に答える
3

System.Windows.MediaStreamGeometryの「軽量な代替」である class も含まれていPathGeometryます。データバインディング、アニメーション、または変更はサポートされていませんが、派生しGeometryているため、Combineメソッドが必要です。

StreamGeometry @ MSDNを参照してください

于 2012-09-27T15:01:15.303 に答える
0

私はちょうどそれで遊んだだけですが、NetTopologySuiteはあなたが望むことをするように見えます.

以下のコードは、2 つのポリゴンを作成し、それらが交差するかどうかをチェックし、それらの面積を見つけて、それらの交差を計算します。

var gf = new GeometryFactory();

var c1 = new[] { new Coordinate(0, 0), new Coordinate(2, 0),
                 new Coordinate(2, 2), new Coordinate(0, 2),
                 new Coordinate(0, 0) };
var lr1 = gf.CreateLinearRing(c1);
var p1 = gf.CreatePolygon(lr1, new ILinearRing[0]);

var c2 = c1.Select(c => new Coordinate(c.X + 1, c.Y + 1)).ToArray();
var lr2 = gf.CreateLinearRing(c2);
var p2 = gf.CreatePolygon(lr2, new ILinearRing[0]);

var intersects = p1.Intersects(p2);        // true
var intersection = p1.Intersection(p2);    // another polygon
var area = intersection.Area;              // 1.0
于 2012-09-27T12:51:48.123 に答える