geometry.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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(
  23. XLevel(x1=line.x1, x2=line.x2), XLevel(x1=area.x1, x2=area.x2)
  24. )
  25. def is_area_below(area1: Area, area2: Area, tolerance: float = TOLERANCE) -> bool:
  26. """
  27. Checks if an Area (area1) is located at the bottom (y2) of an Area
  28. (area2) within a specified tolerance.
  29. """
  30. if not is_vertical_match(area1.y1, area2.y2, tolerance):
  31. return False
  32. return has_horizontal_overlap(
  33. XLevel(x1=area1.x1, x2=area1.x2), XLevel(x1=area2.x1, x2=area2.x2)
  34. )
  35. def get_timeslot_for_area(
  36. area: Area, timeslot_y_levels: dict[TimeSlot, YLevel]
  37. ) -> TimeSlot | None:
  38. """
  39. Gets the TimeSlot for an Area. Returns None if no TimeSlot was matched.
  40. """
  41. for key in timeslot_y_levels.keys():
  42. if timeslot_y_levels[key].y1 < area.y2 <= timeslot_y_levels[key].y2:
  43. return key
  44. return None