File Exchange

image thumbnail

Hatchfill

version 1.11.0.0 (55.1 KB) by Neil Tandon
Fills an area with hatching or speckling.

95 Downloads

Updated 19 Dec 2012

View Version History

View License

Editor's Note: This file was selected as MATLAB Central Pick of the Week

In MATLAB, there are many functions that create regions filled with solid colors (e.g. contourf, area, bar). To do this, a function creates "patch objects" and assigns a single color to each one. Instead of a solid fill, one often wants to fill a patch with a hatch or speckle pattern instead. MATLAB has no built-in way to do this.

The hatchfill function fills patch objects with hatching or speckling. In most cases, adding hatching to a 2D plot requires only three lines of code. For example:

[c,h] = contourf(x,y,z,[0 0]);
hp = findobj(h,'type','patch');
hatchfill(hp);

This fills the zero contour with hatching. Hatchfill takes additional parameters if custom patterns are desired. This package incorporates code from Rich Pawlowicz, Iram Weinstein, and Kirill Pankratov.

Cite As

Neil Tandon (2021). Hatchfill (https://www.mathworks.com/matlabcentral/fileexchange/30733-hatchfill), MATLAB Central File Exchange. Retrieved .

Comments and Ratings (49)

Jingli Xie

Index exceeds the number of array elements (0).

How to fix it?

Simon Lind

does anyone knows how to fixed this code?

Tri Nguyen

This is exactly what I am looking for to visualize 2 overlapping patches. Thank you so much!

Harley Day

Had to modify the code a bit to make it work with MATLAB R2019a (I converted it to use Polygon objects rather than "patches"), but after that, it worked like a charm!

I'll try to work out a proper way to add my modifications to this FileExchange submission, but in the meantime, here's a quick patch:

In the file "hatchfill.m", replace line 144 ( v = get(A(k),'vertices'); ) with the following:

%%%% start of patch %%%%
% modification by Harley to allow polyshapes to be plotted
if class(A(k))=='matlab.graphics.primitive.Polygon'
v = A(k).Shape.Vertices;
else
error('We need a polygon to work with. Please ensure A is a polygon.');
%
% v = get(A(k),'vertices'); % original code
%
end

%%%% end of patch %%%%

Note that this patch will also break the examples provided in this submission, so here's a fresh example:

%%%% start of example %%%%
polys = [polyshape([0 0 0.5 0.5],[1 0 0 1]); polyshape([0.75 1.25 1.25 0.75],[0.25 0.25 0.75 0.75])];
h = plot(polys);
hatchfill(h(1));
hatchfill(h(2), 'cross', 120, 6);
%%%% end of example %%%%

Hope this helps!

Behrend Bode

Example does not work in Version R2018b
hatchfill (line 96)
hax = get(A(1),'parent');

Tamas Bodai

The example.m file cannot be run successfully. The problem is mentioned here: https://ch.mathworks.com/matlabcentral/answers/169706-the-woes-of-contourf-patches-findobj-and-matlab-2014b

Vinay Sewdien

lauren

JJ Yan

Adam Kiczko

tanfeng

索引超出数组元素的数目(0)。

出错 hatchfill (line 96)
hax = get(A(1),'parent');

savvasgk

Andrea

In Matlab R2018a, I get an error when running the example:
Error in hatchfill (line 96)
hax = get(A(1),'parent');

Does anyone have a solution?

Jiangpeng Cui

A very powerful tool. But how to add hatching on a geo map? The code below does work.
R=georasterref(......);
[~,h] = contourfm(significant,R,[1 1]);
hp = findobj(h,'type','patch');
h1=hatchfill2(hp);

erye tfot

Allank

Do i need to have a library to create hatch plots in my matlab code? If so where is it? Could you also demonstrate with a minimum working example?

Martin Foltin

Does it work in R2017b?

Benjamin I

This looks really useful but in 2017b no patch is created from contourf and the method breaks. Can anyone demo how to convert a binary image into a hatched region in 2017b.

Schwamm's message below partly explains the issue but doesn't explain how to create the XData and YData. XData and YData are stored in the contourf object but are not in the correct format to create a patch.

Schwamm Witali

in 2017a hp = findobj(h2,'type','patch') gives an empty handle !
So you have to create the patch like this
hp=patch('XData',[0 1 1 0],'YData',[0 1 1 0]) and then pass it to hatchfill:
H=hatchfill(hp);

Willibald Brems

Yan Jiang

Lao Li

Mona Mahboob Kanafi

Kesh Ikuma

I just upped hatchfill2, which updates hatchfill with post-R2014b support (adds bar and surface objects) for anyone interested. The input arguments are a bit different than the original but all features are still fully intact. Linked above under Acknowledgements.

BC

Has anyone come across this issue and found a fix:

I can fill, speckle, and outspeckle but single and cross don't work and are accompanied by the below error message:

Improper assignment with rectangular empty matrix.
Error in hatchfill (line 176)
H(j) = line(xhatch,yhatch);

All help is greatly appreciated!

Drecalde

For those who have problems using this for legends after 2014b update. Please consider legendflex(http://www.mathworks.com/matlabcentral/fileexchange/31092-legendflex-m--a-more-flexible--customizable-legend) for plotting.
Works like a charm.

Linus

How can I make this work in R2014b?
"findobj(h1, 'Type', 'patch')" does not see work on handles created by contourf (it returns an empty handle)

dpb

ADDENDUM/ERRATUM -- Spoke slightly too soon...
The fixup given below _does_ solve the legend handle; it for some reason I don't yet full understand trashes the patch regions in the figure, however. Best I've done to date is to add yet another conditional...replace the calls to line() w/ the conditional

if gca==hax
H(j) = line(xhatch,yhatch);
else
H(j) = plot(hax,xhatch,yhatch);
end

Also, to prevent changes in y-scale found it necessary to clip the yhatch array returned from hatch_xy(). I put it after the call in the calling routine rather than take the time/trouble to pass the limits or handle to hatch_xy()

[xhatch,yhatch] = hatch_xy(x,y,STYL,ANGLE,SPACING);
% clip limits within the axes limits
ylm=ylim(hax);
yhatch(yhatch<ylm(1))=ylm(1);
yhatch(yhatch>ylm(2))=ylm(2);

This was necessary in my case as there were -eps or thereabouts values returned and with the lower axis at 0 for the bar chart it turned the lower axis limit to -1 instead. That's just rude... :)

Don't think it can hurt in general altho is only needed for cases like this of hatching the boundary region.

dpb

R2012b doesn't draw legends correctly; not sure about earlier releases or later.

Fails owing to use of line() primitive which can't take an axis object and uses current axes by default. Can't force legend object to be current axes.

Fixup is to turn the two line() calls

H(j) = line(xhatch,yhatch,'marker','.','linest','none', ... 'markersize',specksize,'color',linec);

with

H(j) = plot(hax,xhatch,yhatch,'marker','.','linest','none', ...
'markersize',specksize,'color',linec);

Still needs the fixup of twimmeh as well, of course.

Ben

It would be great if there was a mapping version of Hatchfill, perhaps "Hatchfillm" for hatching "patchm" objects? Hatchfill doesn't appear to work on map axes.

Edward Byers

Modifications that twimmeh describes are highly recommended - thanks!

David

Very useful file, but I'm having some trouble with the speckling. I'd like to be able to fill a contour with dots, not just outline it. It would be nice if the function were able to do this by itself instead of the user having to, through trial and error.

David

Taylor Sansom

After a little more editing to hatch_xy as twimmeh described, the legend looks great and the angles work fine.

Cheers!

Taylor Sansom

Thank you very much for this, seems to work like a charm in most applications except for the legend.

I can get the hatching in the legend by doing what twimmeh said (May 2), however the angle doesn't work when hatching in the legend. I can only get horizontal or vertical lines instead of the 45 degree angle that is on my bars.

leg=legend('1-Month','1-Year','5-Year');
legpatch=findobj(leg,'type','patch');
hatchfill(legpatch(3),'single',45,1,'blue')
hatchfill(legpatch(2),'single',45,1,'green')
hatchfill(legpatch(1),'single',45,1,'red')

Any idea how to get the 45 degree angle in the legend?

Bendix

Seems like a really great tool but unfortunately I don't manage to get it working for the problem I needed it for:

I have a 2D-matrix of linear trends (slopes) and a logical 2D-matrix of the same size telling whether the trend is significant at position xy. Now I'd like to hatch the regions of (no) significance in a contourf or pcolor plot.
Has anyone any hint why it does not work in this case although I get it working in other cases?

Would be very grateful for help.
Cheers

twimmeh

aaaand if you want the aspect ratio of the hatch pattern to be correct you need to pass the axes handle to the hatch_xy function and replace calls to gca.

nasty, but works:

function [xi,yi,x,y]=hatch_xy(hax,x,y,varargin);
gca = hax;

(and of course updating the relevant hatch_xy call line)

twimmeh

I _believe_ the problem with legend hatching is that the lines are being drawn on the wrong axes.

If you adjust the calls to 'line' in the function to specify the axes parent then it seems to work... at least for me (R2011b).

-----------------------------------------

H(j) = line(xhatch,yhatch,'marker','.','linest','none', ...
'markersize',specksize,'color',linec,'parent',hax);

and

H(j) = line(xhatch,yhatch,'parent',hax);

-----------------------------------------

%My legend code:

hLegend = legend(...);
hp = findobj(hLegend, 'Type', 'patch');
hatchfill(hp)

This assumes you have only one patch; you need to specify hp(i) in the hatchfill call when there are multiple patches. Also, I've found you need to increase the SPACING parameter for it to look good.

Grey Nearing

I am also curious whether it is possible to get a hatch symbol in the legend. The fix Neil suggested on Jul 17 is not working for me.

Neil Tandon

Thank you Dan, I added an additional check for axes that are only one level up.

Dan K

In order for this to work for my patches (created using jbfill.m, a FileExchange script), I needed to modify line 95 because the axis handle was only one level up from the patch handle. Perhaps there should be a warning issued or some kind of additional handling if the handle two levels up is not an axis (in my case it was the figure handle).

Then this worked great! Thank you for a terrific m file!

Bruno

How do I use this for 'bar'?

Bruno

@Neil and Matt: It still does not work! How do I get a hatched patch symbol in the legend?

Neil Tandon

Matt - you could try something like...
h = legend('patch1','patch2');
hp = findobj(h,'type','patch');
hatchfill(hp(1));
hatchfill(hp(2));

Matt

The legend doesn't work they way i'd like. for example:

figure;hold on;patch([rand(4,1)],[rand(4,1)],'r','facealpha',.2)
h = patch(rand(4,1),rand(4,1),'b');
hatchfill(h);
legend('patch1','patch2')

can you get a little hatched patch symbol in the legend?

Andrew

Great script, the latest update functions perfectly for my needs. Thank you.

Neil Tandon

Thanks Dmytro. I fixed this bug.

Dmytro Lituiev

I tried:
% =============================
f = figure;
MyColor2fade = 0.6*[1 1 1];
x0d = 3;
ulims = [1 2];
p(1) = patch([x0d,x0d,1,1],[ulims(1),ulims(2),ulims(2), ulims(1)], MyColor2fade,'EdgeColor', 'none','Parent',gca);
hatchfill(p(1))
% =============================
Result: only the left top part of the patch is hatched

MATLAB Release Compatibility
Created with R2010b
Compatible with any release
Platform Compatibility
Windows macOS Linux
Acknowledgements

Inspired by: hatch.m

Inspired: kristinbranson/JAABA, stipple, Hatchfill2

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!