geometry.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. from config import TOLERANCE
  2. from .models import XLevel, Area, HorizontalLine, TimeSlot, YLevel
  3. def is_vertical_match(y1: float, y2: float, tolerance: float = TOLERANCE) -> bool:
  4. """
  5. Checks if two Y coordinates are located within a specified tolerance.
  6. """
  7. return abs(y1 - y2) <= tolerance
  8. def has_horizontal_overlap(a: XLevel, b: XLevel) -> bool:
  9. """
  10. Checks if the X coordinates of two objects overlap.
  11. """
  12. return (a.x1 < b.x2) and (a.x2 > b.x1)
  13. def is_line_at_bottom(
  14. area: Area, line: HorizontalLine, tolerance: float = TOLERANCE
  15. ) -> bool:
  16. """
  17. Checks if a HorizontalLine is located at the bottom (y2) of an Area
  18. within a specified tolerance.
  19. """
  20. if not is_vertical_match(line.y, area.y2, tolerance):
  21. return False
  22. return has_horizontal_overlap(XLevel(line.x1, line.x2), XLevel(area.x1, area.x2))
  23. def is_area_below(area1: Area, area2: Area, tolerance: float = TOLERANCE) -> bool:
  24. """
  25. Checks if an Area (area1) is located at the bottom (y2) of an Area
  26. (area2) within a specified tolerance.
  27. """
  28. if not is_vertical_match(area1.y1, area2.y2, tolerance):
  29. return False
  30. return has_horizontal_overlap(
  31. XLevel(area1.x1, area1.x2), XLevel(area2.x1, area2.x2)
  32. )
  33. def get_timeslot_for_area(
  34. area: Area, timeslot_y_levels: dict[TimeSlot, YLevel]
  35. ) -> TimeSlot | None:
  36. """
  37. Gets the TimeSlot for an Area. Returns None if no TimeSlot was matched.
  38. """
  39. for key in timeslot_y_levels.keys():
  40. if timeslot_y_levels[key].y1 < area.y2 <= timeslot_y_levels[key].y2:
  41. return key
  42. return None