Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to efficiently draw a polygon with multiple holes?

Tags:

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.

like image 930
Rody Oldenhuis Avatar asked Aug 22 '17 17:08

Rody Oldenhuis


1 Answers

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.

like image 71
gnovice Avatar answered Sep 22 '22 14:09

gnovice