# How can we stop ListDensityPlot to show results outside data range when using InterpolationOrder -> 0?

I have this data

b = .1 {{1, 1}, {0, 1}};
pts = Tuples[Range[-20, 20], 2] . b;
data = {#[[1]], #[[2]], Sin[#[[1]] #[[2]]]} & /@ pts;


I would like to use ListDensityPlot with InterpolationOrder -> 0

ListDensityPlot[data, InterpolationOrder -> 0]


There are some data points outside the data range! the date range should be like this

ListDensityPlot[data, InterpolationOrder -> 1]


• Noteworthy (I think): ListDensityPlot[data] is identical to ListDensityPlot[data,InterpolationOrder -> 1]
– bmf
Feb 23, 2023 at 9:44

# Background

Look into RegionFunction.

RegionFunction is an option for plotting functions that specifies the region to include in the plot drawn.

If you know how to define the region analytically, that could be faster (Solution 2). Here I first take the more general route of using ConvexHullRegion

ConvexHullRegion is also known as convex envelope or convex closure. The convex hull mesh is the smallest convex set that includes the points $$p_i$$.

Region check happens using RegionMember

# Solution 1

With[
{reg = ConvexHullRegion[pts]},
ListDensityPlot[
data,
InterpolationOrder -> 0,
RegionFunction -> Function[{x, y, z},RegionMember[reg, {x,y}]]
]
]


# Solution 2

Defining the RegionFunction by hand

ListDensityPlot[
data,
InterpolationOrder -> 0,
RegionFunction -> Function[{x, y, z}, x-2 < y  < x + 2]
]
]


# Solution 3

See solution by @valarmorghulis, they figured out that pre-defining the RegionFunction makes all the difference and has the best performance. Replicating my version of his solution here for completeness.

With[
{regfunc = RegionMember[ ConvexHullRegion[pts]]},
ListDensityPlot[
data,
InterpolationOrder -> 0,
RegionFunction ->(regfunc[{#1,#2}]&)
]
]


# Performance

Using RegionMember[ ConvexHullRegion[pts], {x,y}] much slower than Function[{x, y, z}, x-2 < y < x + 2].

Using AbsoluteTiming I compare the two solutions.

### Sol 3

• (+1) and very nicely done. Perhaps you could demonstrate the result from reg = ConicHullRegion[pts]
– bmf
Feb 23, 2023 at 9:55
• @bmf ConicHullRegion doesn't help here. Does it? Feb 23, 2023 at 11:54
• it is exactly the result from InterpolationOrder->0. So yes, you are right. It is not a solution, but I think it's a nice and illustrative connection. This is what I meant.
– bmf
Feb 23, 2023 at 11:59
• I don't understand why RegionFunction -> Composition[regfunc, Most, List] doesn't work. Mar 3, 2023 at 14:16

in light of the Answer by @rhermans, the performance can be boosted like the one below, but it would be nice to boost it without using two superimposed graphics and directly obtain using ListDensityPlot

reg = ConvexHullRegion[pts];


then

Show[ListDensityPlot[data, InterpolationOrder -> 0],
Graphics[{White,
Polygon[{{-4, -4}, {-4, 4}, {4, 4}, {4, -4}} ->
reg[[1]]]}]] // AbsoluteTiming


Update

For arbitrarily shaped data, we can predefine the RegionMember and results much faster though don't know why

Block[{RegFun = RegionMember[ConvexHullRegion[pts]]},
ListDensityPlot[data, InterpolationOrder -> 0,
RegionFunction -> (RegFun[{#1, #2}] &)]] // AbsoluteTiming


Adding it in the RegionFunction makes it 20 times slow

Block[{reg = ConvexHullRegion[pts]},
ListDensityPlot[data, InterpolationOrder -> 0,
RegionFunction ->
Function[{x, y, z}, RegionMember[reg, {x, y}]]]] // AbsoluteTiming


• I have updated my answer with similar performance as yours, but you need to define the function by hand. Feb 23, 2023 at 11:56
• That is great, but what if the data are hexagon shaped or other nonunform shape? Feb 23, 2023 at 12:05
• Another interesting question to ask, how to make RegionMember[ConvexHullRegion[pnts], {x,y}] fast, or something equivalent. Feb 24, 2023 at 7:31
• @rhermans check my update! Feb 25, 2023 at 12:30
• Using RegionFunction -> Function[{x, y, z}, Evaluate@RegionMember[reg, {x, y}]]] achieves the same speedup as predefining the region. Mar 3, 2023 at 21:01