Home > Net >  Are all points within a rectangle?
Are all points within a rectangle?

Time:06-20

So I am trying to write a piece of code so it takes a list of points rather than a single point and returns boolean True only if all points in the list are in the rectangle.

For example,

allIn((0,0), (5,5), [(1,1), (0,0), (5,5)]) should return True
but allIn((0,0), (5,5), [(1,1), (0,0), (5,6)]) should return False
empty list of points allIn((0,0), (5,5), []) should return False

I can't seem to get the return to match the above example for both false returns.The empty list should return false. Any idea where I am going wrong?

    def allIn(firstCorner=(0,0), secondCorner=(0,0), pointList=[]):  
       x1 = firstCorner[0]     
       y1 = firstCorner[1]
       x2 = secondCorner[0] 
       y2 = secondCorner[1] 

       for i in range(len(pointList)):

           p_x = pointList[i][0] 
           p_y = pointList[i][1] 

      if not ((p_x >= x1 and p_x < x2) and (p_y >= y1 and p_y < y2)):
          return False

      return True
   print(allIn((0,0), (5,5), [(1,1), (0,0), (5,5)]))
   print(allIn((0,0), (5,5), [(1,1), (0,0), (5,6)]))
   print(allIn((0,0), (5,5), []))

CodePudding user response:

In order to fix the issue, you have to change the if statement to be nested in the for loop you have above. Otherwise, the statement doesn't check every single point of the list but only the last one.

Moreover, if you want your first example of yours to be true you have to check whether the point is less or equal to the secondCorner.

You can also add one more if statement in order to check if the list is empty in order to return false as you would like in the last example of yours.

if not(pointList):
    return False

for i in range(len(pointList)):

    p_x = pointList[i][0] 
    p_y = pointList[i][1] 

    if not ((p_x >= x1 and p_x <= x2) and (p_y >= y1 and p_y <= y2)):
        return False

 return True

CodePudding user response:

Two things:

  • You only return False inside the loop. If the loop never runs (which is the case if the list of points is empty), you will always return true.
  • ((p_x >= x1 and p_x < x2) and (p_y >= y1 and p_y < y2)) should be ((p_x >= x1 and p_x <= x2) and (p_y >= y1 and p_y <= y2)) (end coordinates of rectangle should be inclusive, rather than exclusive.)

I would recommend defining one function that determines whether a single point is within a rectangle, then reuse that function to check if all points are within a rectangle:

from collections import namedtuple


def point_in_rect(point, rect):
    return (rect.first.x <= point.x <= rect.second.x) and (rect.first.y <= point.y <= rect.second.y)

def points_in_rect(points, rect):
    return bool(points) and all(point_in_rect(point, rect) for point in points)


Point = namedtuple("Point", "x y")
Rectangle = namedtuple("Rectangle", "first second")


rect = Rectangle(Point(0, 0), Point(5, 5))

print(points_in_rect([Point(1, 1), Point(0, 0), Point(5, 5)], rect)) # True
print(points_in_rect([Point(1, 1), Point(0, 0), Point(5, 6)], rect)) # False
print(points_in_rect([], rect)) # False

CodePudding user response:

Just adding another option to the list. You could use numpy here as well, avoiding a for loop.

import numpy as np
   
def allIn(firstCorner=(0,0), secondCorner=(0,0), pointList=[]):  
    
    # list is empty, return False
    if not pointList:
        return False
    
    arr = np.array(pointList)
    return False not in (arr >= firstCorner) & (arr <= secondCorner)

print(allIn((0,0), (5,5), [(1,1), (0,0), (5,5)])) # True
print(allIn((0,0), (5,5), [(1,1), (0,0), (5,6)])) # False
print(allIn((0,0), (5,5), [])) # False

E.g. for [(1,1), (0,0), (5,6)], the array becomes:

[[1 1]
 [0 0]
 [5 6]]

which is turned into:

[[ True  True]
 [ True  True]
 [ True False]] 

# i.e. 6 is out of bounds, creating 1 False in the array, returning False for the function.
  • Related