# Generating hatched filling using Region functionality

Before v.10 came out there were several Q&A on generating hatched filling for Plot, ListPlot etc.

In v.10 we have new Region functionality and I wonder: Does it allow a straightforward way to produce vector hatched filling for arbitrary 2D Polygon?

Here is my first attempt to use Region functionality which produces ugly result in extremely inefficient way:

GraphicsMeshMeshInit[];
blob = PolygonData["Blob", "Polygon"];
Show[DiscretizeRegion[
RegionIntersection[
RegionUnion @@
Table[InfiniteLine[{-3, y}, {1, 1}], {y, -7, 2, .2}],
blob], {{-3, 3}, {-3, 3}}], Prolog -> blob,
PlotRange -> {{-3, 3}, {-3, 3}}, Frame -> True]


Is it a good idea to use Region for such purposes? Can anyone suggest an efficient solution?

P.S. I think that raster texture is not appropriate for hatching filling because it is not scalable. The goal is to have vector hatching.

Update: Using MeshFunctions and Mesh in RegionPlot:

RegionPlot[Evaluate[RegionRegionProperty[Rationalize /@ blob, {x, y},
"FastDescription"][[1, 2]]], {x, -3, 3}, {y, -3, 3}, Mesh -> 50,
MeshFunctions -> {#1 + #2 &, #1 - #2 &}, MeshStyle -> White,
PlotStyle -> Directive[{Thick, Blue}]]


With settings MeshStyle -> GrayLevel[.3], PlotStyle -> Directive[{Thick, LightBlue}]

With settings Mesh -> {40, 20}, MeshFunctions -> {# #2 &, Norm[{#, #2}] &}, MeshStyle -> White, MeshShading -> Dynamic@{{Hue@RandomReal[], Hue@RandomReal[]}, {Hue@RandomReal[], Hue@RandomReal[]}}, we get

Update 2: Mesh specifications

rpF = RegionPlot[
Evaluate[RegionRegionProperty[Rationalize /@ blob, {x, y},
"FastDescription"][[1, 2]]], {x, -3, 3}, {y, -3, 3}, Mesh -> #,
MeshFunctions -> {#1 + #2 &, #1 - #2 &},
MeshStyle -> GrayLevel[.3],
PlotStyle -> Directive[{Thick, LightBlue}]] &;

rp1 = rpF@{20, 75};
rp2 = rpF@{List /@ {-5, -4, -2.5, -2., -1.9, -1.8, -1.7, -1., -.5, Sequence @@ Range[0, 5, .2]},
List /@ {Sequence @@ Range[-5., -1, .3], Sequence @@ Range[-1., 1, .1], 1.5, 2., 2.5, 3.}};
rp3 = rpF@RandomReal[{-5, 5}, {2, 50, 1}];
rp4 = rpF@{Transpose[{RandomReal[{-5, 5}, 25], Table[Hue[RandomReal[]], {25}]}],
Transpose[{RandomReal[{-5, 5}, 50], Table[Directive[{Thick, Hue[RandomReal[]]}], {50}]}]};

Grid[{{rp1, rp2}, {rp3, rp4}}]


Change the MeshFunctions specification to

MeshFunctions -> {#1 &, #2 &}


to get

Use the option

MeshShading -> Dynamic@{{Hue@RandomReal[], Hue@RandomReal[]},
{Hue@RandomReal[], Hue@RandomReal[]}}


to get

Original version:

GraphicsMeshMeshInit[];
blob = PolygonData["Blob", "Polygon"];

RegionPlot[Evaluate[RegionRegionProperty[Rationalize /@ blob, {x, y},
"FastDescription"][[1, 2]]], {x, -3, 3}, {y, -3, 3}, PlotStyle -> texturea]


RegionPlot[Evaluate[RegionRegionProperty[Rationalize /@ blob, {x, y},
"FastDescription"][[1, 2]]], {x, -3, 3}, {y, -3, 3}, PlotStyle -> textureb]


where hatched textures texturea and textureb

texturea = Texture[Rasterize@hatchingF["cross", {{1, 1}, {1, 1}}, 100]]


textureb = Texture@Rasterize@hatchingF["cross", {{1, 1}, {1, 1}}, 100,
Dynamic@Directive[{Thick, Hue[RandomReal[]]}]]


are obtained using the function

ClearAll[hatchingF];
hatchingF[dir : ("single" | "cross") : "single",
slope : ({{_, _} ..}) : {{1, 1}}, mesh_Integer: 100,
style_: GrayLevel[.5], pltstyle_: None, opts : OptionsPattern[]] :=
Module[{meshf = Switch[dir, "single", {slope[[1, 1]] #1 + slope[[1, -1]] #2 &},
"cross", {slope[[1, 1]] #1 - slope[[1, -1]] #2 &,
slope[[-1, 1]] #1 + slope[[-1, -1]] #2 &}]},
ParametricPlot[{x, y}, {x, 0, 1}, {y, 0, 1}, Mesh -> mesh,
MeshFunctions -> meshf, MeshStyle -> style, BoundaryStyle -> None,
Axes -> False, PlotStyle -> pltstyle]]


More examples:

hatchingF["cross", {{1, 0}, {0, 1}}, 50, Red]


hatchingF["single", {{1, 1}, {0, 1}}, 50, Directive[{Thick,Green}]]


texture2 = Texture[Rasterize@ hatchingF["cross", {{1, 1}, {1, 1}}, 50, Directive[{Thick, Red}]]];
Plot3D[Sin[x y], {x, 0, 3}, {y, 0, 3}, PlotStyle -> texture2, Mesh -> None, Lighting -> "Neutral"]


• I need vector hatching. – Alexey Popkov Oct 27 '14 at 2:18
• @Alexey, would something like Texture[ImportString[ ExportString[hatchingF["cross", {{1, 1}, {1, 1}}, 100], "PNG"]]] work? – kglr Oct 27 '14 at 2:30
• Texture works only with raster fills. I think that raster hatching is not appropriate for generating publication quality graphics. – Alexey Popkov Oct 27 '14 at 2:33
• @Alexey, so Texture is out; that still leaves Mesh/MeshFunctions/MeshShading? :) – kglr Oct 27 '14 at 2:50
• Yes, MeshFunctions is a solution. There is an extremely simple way to optimize the mesh: % /. Line[{{f_, __}, __, {__, l_}}] :> Line[{f, l}]. The only drawback is that Mesh does not allow to specify the distance between the hatches, only the number of hatches. Is there a way to generate completely customizable hatching? – Alexey Popkov Oct 27 '14 at 3:14

Here is a solution which combines kguler's and MichaelE2's approaches:

ParametricPlot[{x, y}, {x, y} ∈ blob, Mesh -> 20,
MeshFunctions -> {#1 - #2 &}, MeshStyle -> Black,
BoundaryStyle -> Black, PlotStyle -> None, Axes -> False]


Note however that the syntax form ParametricPlot[{x, y}, {x, y} ∈ region] seems to be undocumented.

It is worth to mention that in a usual situation when only the hatching is needed there is straightforward way to optimize it by joining the adjacent line segments:

simplifyHatches = # /. Line[{f_Integer, __, l_Integer}] :> Line[{f, l}] &;

ParametricPlot[{x, y}, {x, y} ∈ blob, Mesh -> 20,
MeshFunctions -> {#1 - #2 &}, MeshStyle -> Black,
BoundaryStyle -> None, PlotStyle -> None,
Axes -> False] // simplifyHatches


Edit 2: Updated with a non-convex polygon

reg = With[{pts = RandomReal[{-3, 3}, {15, 2}]},
Polygon@SortBy[pts, Apply[ArcTan, # - Mean[pts]] &]];


You could make a texture and use RegionPlot:

RegionPlot[
reg,
PlotStyle -> Texture[ExampleData[{"ColorTexture", "MultiSpiralsPattern"}]]]


Update

Vector graphics through ContourShading:

ClearAll[f];
f[x_, y_] := x - y;
ContourPlot[f[x, y], {x, y} ∈ reg,
Contours -> 20, ContourShading -> {Blue, LightRed},
ContourStyle -> None]


A self-intersecting polygon:

reg = Polygon[RandomReal[{-3, 3}, {15, 2}]];
ContourPlot[f[x, y], {x, y} ∈ reg,,
Contours -> Flatten[Table[{c, c + 0.05}, {c, -6, 6, 0.3}]],
ContourShading -> {Blue, LightRed}, ContourStyle -> None]]


• The goal is to have vector hatching, not raster. – Alexey Popkov Oct 27 '14 at 2:13
• @AlexeyPopkov Perhaps that should be specified in the Q? – Michael E2 Oct 27 '14 at 2:29
• I have updated the Q. – Alexey Popkov Oct 27 '14 at 2:31
• It seems that you have accidentally deleted your ContourPlot-based solution. – Alexey Popkov Oct 27 '14 at 7:58
• @AlexeyPopkov I was going to think about it, but I seem to have really deleted it. It was late and I couldn't figure out the difference between hatching and stripes. Also, I was running out of energy to address the main question of how to use the new Region functionality to make hatching. The answers so far don't really use it in the way you were trying. – Michael E2 Oct 27 '14 at 10:42