2

I'm using v6.4.2 of the C# version of the ClipperLib. I have a lot of squares making up a fishnet. I also have a rectangle. I want to get a result where only the squares that are inside the rectangle are returned and partially overlapped get clipped. The subjects are in green and the clip is in red: enter image description here

The result I get is the brown/gray rectangle, which is only one polygon: enter image description here

I would have expected to have 15 full squares and 13 clipped squares as a result.

This is the code I'm using:

var startX = 100;
var startY = 250;
const int numPolygons = 10;

var subj = new Polygons(numPolygons * numPolygons);
for (var i = 0; i < numPolygons; i++)
{
    for (var j = 0; j < numPolygons; j++)
    {
        var square = new Polygon(4)
        {
            new IntPoint(startX, startY),
            new IntPoint(startX + 10, startY),
            new IntPoint(startX + 10, startY - 10),
            new IntPoint(startX, startY - 10)
        };
        subj.Add(square);
        // Moving to the right
        startX = startX + 10;
    }
    // Moving down
    startY = startY - 10;
    startX = 100;
}

var clip = new Polygons(1);
clip.Add(new Polygon(4));
clip[0].Add(new IntPoint(165, 215));
clip[0].Add(new IntPoint(255, 215));
clip[0].Add(new IntPoint(255, 155));
clip[0].Add(new IntPoint(165, 155));

var solution = new Polygons();
var c = new Clipper.Clipper();
c.AddPaths(subj, PolyType.ptSubject, true);
c.AddPaths(clip, PolyType.ptClip, true);
c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
Debug.WriteLine("solution.Count: " + solution.Count);

When running the above code is takes about 0.5 seconds. Because the result looks like the clip and subject are switched I've switched them. The result is the same, but now it only takes 0.1 seconds. So something extra is done. I think it is the merging of the resulting squares.

I don't want the result to merge. How can I prevent that? Or perhaps my code is faulty?

Paul Meems
  • 3,002
  • 4
  • 35
  • 66

2 Answers2

2

According to Clipper documentation of the Execute method:

There are several things to note about the solution paths returned:

... polygons may rarely share a common edge (though this is now very rare as of version 6)

which I think means that paths get merged when performing any clipping operations.

I've tried to do the same thing with different PolyFillType`s with no success either.

You might want to try running the Execute method on each square individually (subject) against the clipping area on each iteration which should do the job, though performance may suffer as a result.

Xrayez
  • 73
  • 6
  • In reality, I'm using geo-referenced files. One of them has 2.2 million squares which can be rotated but this next to each other. The border is a parcel border with lots of points. Doing the clipping with GDAL/GEOS doesn't work. After 40 min. I cancel it. Doing it with clipper and one subject (square) at a time takes only 3 min. So the performance is good enough. I'll accept your answer. – Paul Meems Sep 17 '17 at 13:45
  • 1
    A small addition: I changed the `foreach subject` to a `Parallel.ForEach` and use `System.Collections.Concurrent.ConcurrentBag()` to store all solutions and now the time is just 52 seconds! – Paul Meems Sep 18 '17 at 06:55
  • 2
    Paul, the latest version of Clipper (still in development but solid and faster and unlikely to change much now before formal release) doesn't have any polygon merging so should do what you want ... https://sourceforge.net/p/polyclipping/code/HEAD/tree/sandbox/Clipper2/ . Alternatively you could comment out the the JoinCommonEdges() statement in the ExecuteInternal method in the old Clipper. – Angus Johnson Oct 11 '17 at 00:44
1

In this precise case you can easily compute the result by hand, without clipper lib.

The fact that all rectangles are axis-aligned objects makes it possible to speed up computations, so it could even be faster performing the operation yourself.

arthur.sw
  • 11,052
  • 9
  • 47
  • 104