Skip to main content
4 of 4
Address 1D possibility
Carl Woll
  • 131.7k
  • 6
  • 246
  • 359

Fast function to do multiple rectangle region checks

Suppose I have a set of "rectangles" and a set of "points":

SeedRandom[5]
rects = RandomReal[10, {5, 2, 2}]
pts = RandomReal[10, {5, 2}]

{{{0.00790584, 0.650192}, {9.89555, 9.68768}}, {{2.00866, 8.19521}, {0.897634, 9.70701}}, {{2.2991, 6.12503}, {0.96816, 5.48855}}, {{1.32548, 2.32332}, {7.76135, 5.50949}}, {{0.586896, 9.60602}, {0.982487, 0.343521}}}

{{8.06562, 4.39186}, {1.42284, 0.27687}, {0.794711, 8.59505}, {2.42136, 8.42835}, {5.54556, 7.21645}}

I want to find out which points are members of their associated rectangles. One slow possibility is to use RegionMember:

MapThread[RegionMember[Rectangle@@#1, #2]&, {rects, pts}]

{True, RegionMember[ Rectangle[{2.00866, 8.19521}, {0.897634, 9.70701}], {1.42284, 0.27687}], RegionMember[ Rectangle[{2.2991, 6.12503}, {0.96816, 5.48855}], {0.794711, 8.59505}], False, RegionMember[ Rectangle[{0.586896, 9.60602}, {0.982487, 0.343521}], {5.54556, 7.21645}]}

This approach doesn't work because RegionMember needs the first Rectangle coordinate to be strictly smaller than the second Rectangle coordinate. It also unpacks the rects variable. I would like a function inRange that returns 1 if the point is in the rectangle, and 0 otherwise, and I want to avoid unpacking. For the above example:

inRange[rects, pts]

should return:

{1, 0, 0, 0, 0}

A compiled solution is acceptable, but I would prefer a version that works for both packed arrays and mixed data types.

An alternate version using vectors only is fine, e.g.:

inRange[x1, y1, x2, y2, x, y]

A 1D version would also be interesting, with intervals instead of rectangles. The simplest approach in that case would be to use IntervalMemberQ, but that would cause unpacking.

Carl Woll
  • 131.7k
  • 6
  • 246
  • 359