import importlib.util import unittest from pathlib import Path import numpy as np spec = importlib.util.spec_from_file_location("alignment", Path(__file__).with_name("alignment.py")) alignment = importlib.util.module_from_spec(spec) spec.loader.exec_module(alignment) def straight(ch): """Alignment along +e from (0, 0); chainage == e.""" return np.array([float(ch), 0.0]), np.array([1.0, 0.0]) def area(ring): a = 0.0 for i in range(len(ring)): x1, y1 = ring[i]; x2, y2 = ring[(i + 1) % len(ring)] a += x1 * y2 - x2 * y1 return abs(a) / 2 class AlignmentTests(unittest.TestCase): def test_band_key(self): self.assertEqual(alignment.band_key(240, 260), "ch240-260") def test_bands_cover_range_in_20m_steps(self): self.assertEqual(alignment.bands(235.0, 281.0), [(220, 240), (240, 260), (260, 280), (280, 300)]) def test_clip_square_into_bands(self): ring = [(0, -5), (50, -5), (50, 5), (0, 5)] # 50 m long, 10 m wide parts = [alignment.clip_ring_to_band(ring, straight, lo, hi, lo == 0, hi == 60) for lo, hi in [(0, 20), (20, 40), (40, 60)]] self.assertAlmostEqual(area(parts[0]), 200) self.assertAlmostEqual(area(parts[1]), 200) self.assertAlmostEqual(area(parts[2]), 100) def test_first_band_keeps_area_before_alignment_start(self): ring = [(-10, -5), (10, -5), (10, 5), (-10, 5)] part = alignment.clip_ring_to_band(ring, straight, 0, 20, True, False) self.assertAlmostEqual(area(part), 200) # nothing lost before ch 0 def test_last_band_keeps_area_after_alignment_end(self): ring = [(30, -5), (70, -5), (70, 5), (30, 5)] part = alignment.clip_ring_to_band(ring, straight, 20, 40, False, True) self.assertAlmostEqual(area(part), 400) # 30..70 all kept if __name__ == "__main__": unittest.main()