5

I would like to plot a polygon with multiple holes in it, like this:

P = [
    0.5,    0.8;
    1.0,    0.0; % outer boundary
    0.0,    0.0;
    0.5,    0.8;
    %{
    %}
    0.5,    0.3;
    0.3,    0.1; % inner boundary I 
    0.7,    0.1; % (hole)
    0.5,    0.3;
    %{
    %}
    0.5,    0.6;
    0.3,    0.4; % inner boundary II 
    0.7,    0.4; % (hole)
    0.5,    0.6;
    ];

figure, clf, hold on
patch(P(:,1),P(:,2), 'r', 'linestyle', 'none')

two holes, as expected

However, patch doesn't quite work the way I expected it to. When I change the last hole to this:

% ...
0.45,   0.6; % <- slightly offset in X-direction 
0.3,    0.4; 
0.7,    0.4; 
0.45,   0.6; % <- slightly offset in X-direction 
% ...

this happens:

too many holes!

This technique works nicely with a single hole, but can I also apply the same technique for multiple holes? Or do I have to resort to splitting it up, as shown here?

NOTE: Eventually, I'll be plotting hundreds of (possibly partially transparent) polygons in 3D space, and I want to be able to "look through" the holes. Therefore, solutions with a "white overlay" polygon are not what I'm looking for.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96

1 Answers1

4

The best way to handle this may be to break your polygons up into a Delaunay triangulation with constrained edges, extract only the triangles that are on the interior of the constrained edges, then create a set of face/vertex data from that to use with patch. Given the second matrix P from your example, here's how to do it:

C = [1:3 5:7 9:11; 2:4 6:8 10:12].';
DT = delaunayTriangulation(P, C);
vertices = DT.Points;
faces = DT.ConnectivityList(isInterior(DT), :);
patch('Faces', faces, 'Vertices', vertices, 'FaceColor', 'r', 'EdgeColor', 'none');

And the resulting figure:

enter image description here

You'll get a warning when creating the triangulation that "duplicate data points have been detected and removed", which is nothing to worry about. You could potentially even put all of your polygon and constraint data together into one set of matrices and do the triangulation once to create one big set of face/vertex data for multiple polygons.

gnovice
  • 125,304
  • 15
  • 256
  • 359
  • Thanks. I was afraid I'd have to split up the polygon, seems like my fear was justified. Oh, to add to the fun, this is to fix some legacy code in R2010a, which doesn't have the `delaunayTriangulation` class; do you know if there is an equivalent in older MATLAB? – Rody Oldenhuis Aug 22 '17 at 18:48
  • 2
    @RodyOldenhuis: Take a look at [this older question](https://stackoverflow.com/q/1700522/52738), which has an example of constrained Delaunay triangulation for prior versions. It's pretty similar, but the way you build face/vertex data from the triangulation may be different. – gnovice Aug 22 '17 at 18:54