: [outpol, npol] = clipPolygon_clipper (inpol, clippol)
: [outpol, npol] = clipPolygon_clipper (inpol, clippol, op)
: [outpol, npol] = clipPolygon_clipper (inpol, clippol, op, rules, rulec)

Perform boolean operation on polygon(s) using the Clipper library.

inpol = Nx2 matrix of (X, Y) coordinates constituting the polygons(s) to be clipped. Polygons are separated by [NaN NaN] rows. clippol = another Nx2 matrix of (X, Y) coordinates representing the clip polygon(s).

Optional argument op, the boolean operation, can be:

  • 0: difference inpol - clippol
  • 1: intersection ("AND") of inpol and clippol (= default)
  • 2: exclusiveOR ("XOR") of inpol and clippol
  • 3: union ("OR") of inpol and clippol

In addition a rule can be specified to instruct polyclip how to assess holes, or rather, how to assess polygon fill. This works as follows: start with a winding number of zero (0). From a point outside all polygons specified in INPOL, go to the center of the innermost polygon and note which polygons are crossed. For each polygon boundary crossing from right to left, increase the winding number, while for each polygon crossing from left to right, decrement it, and then assign it to the crossed polygon. rules and rulec can be set individually for subject and clip polygons, respectively, as follows:

  • 0 Even-Odd, also called Alternate (= default): The first polygon crossed specifies the outer boundary of a filled polygon, the next polygon (if present) specifies the inner boundary of that filled polygon, and so on. Winding direction (clockwise or counterclockwise) is irrelevant here.
  • 1 Non-Zero: All polygons with a non-zero winding number are filled.
  • 2 Positive: All polygons with a winding number > 0 are filled. This is the usual setting for counterclockwise polygons to be the outer, and clockwise polygons to be the inner boundary ("holes") of complex polygons.
  • 3 Negative: All polygons with a winding number < 0 are filled.

(for details see [1])

Output array outpol will be an Nx2 array of polygons resulting from the requested boolean operation, or in case of just one input argument an Nx1 array indicating winding direction of each subpolygon in input argument inpol.

[1]: http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/PolyFillType.htm

See also: clipPolygon_mrf,clipPolygon.

Demonstration 1

The following code

 pol1 = [2 2; 6 2; 6 6; 2 6; 2 2; NaN NaN; 3 3; 3 5; 5 5; 5 3; 3 3];
 pol2 = [1 2; 7 4; 4 7; 1 2; NaN NaN; 2.5 3; 5.5 4; 4 5.5; 2.5 3];
 lw   = 2;

 subplot (2, 7, [1 2])
 pol1a = polygon2patch (pol1);
 patch (pol1a(:, 1), pol1a(:, 2), 'facecolor', 'c', 'edgecolor', 'k', 'linewidth', lw);
 axis image
 title ("1. Subject polygon")
 axis off

 subplot (2, 7, [3 4])
 patch (pol1a(:, 1), pol1a(:, 2), 'facecolor', 'c', 'edgecolor', 'none');
 hold on
 pol2a = polygon2patch (pol2);
 patch (pol2a(:, 1), pol2a(:, 2), 'facecolor', 'y', 'edgecolor', 'b', 'linewidth', lw);
 axis image
 title "2. Clip polygon"
 axis off

 op   = {"Sub - clip", "AND / Intersection", "Exclusive OR", "OR / Union"};
 for i=1:numel(op)
   subplot (6, 4, [12 16]+i);
   [opol, npol] = clipPolygon_clipper (pol1, pol2, i-1);
   opol = polygon2patch (opol);
   patch (pol1a(:, 1), pol1a(:, 2), 'facecolor', 'c', 'edgecolor', 'none');
   hold on
   patch (pol2a(:, 1), pol2a(:, 2), 'facecolor', 'y', 'edgecolor', 'none');
   patch (opol(:,1),opol(:,2), 'facecolor', 'g', 'edgecolor', 'r', ...
         'linewidth', lw);
   axis image
   grid on
   title (sprintf("%d. %s", i+3, op{i}));
   axis off
 endfor

 subplot (2, 7, [6 7]);
   [opol, npol] = clipPolygon_clipper (pol2, pol1, 0);
   opol = polygon2patch (opol);
   patch (pol1a(:, 1), pol1a(:, 2), 'facecolor', 'c', 'edgecolor', 'none');
   hold on
   patch (pol2a(:, 1), pol2a(:, 2), 'facecolor', 'y', 'edgecolor', 'none');
   patch (opol(:,1),opol(:,2), 'facecolor', 'g', 'edgecolor', 'r', ...
         'linewidth', lw);
   axis image
   grid on
   axis off
   title "3. Clip - sub";

Produces the following figure

Figure 1

Package: geometry