1

重なり合う形状がいくつかあります。すべての小さな形状を含む最大の形状に穴を開けられるようにしたいです。穴は、大きな形状内の小さな形状を表します。

サンプル画像: ここに画像の説明を入力

ClipperLib の C# バージョンを使用しています。

const double precisionFactor = 1000000000000000.0;

            //precondition: all your polygons have the same orientation 
            //(ie either clockwise or counter clockwise)
            Polygons polys = new Polygons();

            multiPolygon.ForEach(x =>
            {
                Polygon polygon = x.First().Select( y => new IntPoint()
                {
                    X = (long)(y[0] * precisionFactor),
                    Y = (long)(y[1] * precisionFactor)
                }).ToList();

                polys.Add(polygon);
            });

            Polygons solution = new Polygons();
            Clipper c = new Clipper();
            c.AddPaths(polys, PolyType.ptSubject,true);
            c.Execute(ClipType.ctDifference, solution,
                PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            var coordinates = solution.SelectMany(x => x.Select(y=> (IList<double>)new List<double>()
            {
                y.X / precisionFactor,
                y.Y / precisionFactor
            }).ToList()) .ToList();

            return coordinates;

返される形状は、上の図の最大の形状です。

GeoJson ファイル: http://s000.tinyupload.com/download.php?file_id=62259172894067221043&t=6225917289406722104327028

4

1 に答える 1

2

あなたが「一番大きな形に穴を開けたい」と言うのは、Clipper ライブラリがポリゴン領域を管理/定義する方法を誤解していると思います。Clipper では、ポリゴンは指定されたポリゴン塗りつぶし規則(最も一般的には EvenOdd または NonZero 塗りつぶし)と共に一連の閉じたパスによって定義されます。(ポリゴンは、ほとんどの場合、グラフィック表示ライブラリでこの方法で定義されます。)

したがって、上記のデータでは、NonZero の塗りつぶしを使用しているため、「穴」のパスは、コンテナーの外側のパスの向きと反対方向に向ける必要があります。内側のパスが外側のコンテナーと同じ向きである場合、NonZero の塗りつぶしを使用して「差分」クリッピング操作を実行すると、内側のパスが正しく無視されます。

補足として、単一のポリゴン セットに対してクリッピング操作を実行する場合 (つまり、クリッピング パスがない場合)、サブジェクト パスは (クリップ パスと同様に) 「結合」されるため、「結合」操作を実行する方がより直感的です。サブジェクト領域とクリップ領域の間のクリッピング操作の前。

于 2015-10-24T21:21:25.350 に答える