from __future__ import annotations import importlib.util import json import sys import tempfile import unittest from pathlib import Path SCRIPT = Path(__file__).parents[1] / "prepare_odx_reconstruction_inputs.py" SPEC = importlib.util.spec_from_file_location("prepare_odx_reconstruction_inputs", SCRIPT) MODULE = importlib.util.module_from_spec(SPEC) assert SPEC.loader is not None sys.modules[SPEC.name] = MODULE SPEC.loader.exec_module(MODULE) class OdxInputPreparationTests(unittest.TestCase): def test_dji_orientation_matches_referenced_odx_normalization(self) -> None: self.assertEqual(MODULE.odx_orientation_from_dji(-25.9, -37.7, 0.0), (-25.9, 52.3, 0.0)) def test_geo_txt_uses_webodm_epsg4326_field_order(self) -> None: record = MODULE.OdxPhoto( image="DJI_0001.JPG", longitude=113.317951157, latitude=25.660699129, altitude_m=1201.372, yaw_deg=-25.9, pitch_deg=52.3, roll_deg=0.0, horizontal_accuracy_m=0.0046, vertical_accuracy_m=0.0112, width=4000, height=3000, sha256="a" * 64, rtk_std_lat_raw=0.0023, rtk_std_lon_raw=0.00201, rtk_std_hgt_raw=0.0056, ) with tempfile.TemporaryDirectory() as temporary: path = Path(temporary) / "geo.txt" MODULE.write_geo_txt([record], path) lines = path.read_text(encoding="utf-8").splitlines() self.assertEqual(lines[0], "EPSG:4326") fields = lines[1].split() self.assertEqual(fields[0], "DJI_0001.JPG") self.assertEqual(len(fields), 9) self.assertEqual(float(fields[1]), record.longitude) self.assertEqual(float(fields[2]), record.latitude) self.assertEqual(float(fields[5]), record.pitch_deg) def test_camera_positions_are_valid_geojson(self) -> None: record = MODULE.OdxPhoto( image="DJI_0001.JPG", longitude=113.0, latitude=25.0, altitude_m=100.0, yaw_deg=0.0, pitch_deg=90.0, roll_deg=0.0, horizontal_accuracy_m=0.02, vertical_accuracy_m=0.03, width=1, height=1, sha256="b" * 64, rtk_std_lat_raw=0.01, rtk_std_lon_raw=0.01, rtk_std_hgt_raw=0.015, ) with tempfile.TemporaryDirectory() as temporary: path = Path(temporary) / "positions.geojson" MODULE.write_camera_positions_geojson([record], path) payload = json.loads(path.read_text(encoding="utf-8")) self.assertEqual(payload["type"], "FeatureCollection") self.assertEqual(payload["features"][0]["geometry"]["coordinates"], [113.0, 25.0, 100.0]) def test_recommendations_do_not_override_per_photo_accuracy(self) -> None: record = MODULE.OdxPhoto( image="DJI_0001.JPG", longitude=113.0, latitude=25.0, altitude_m=100.0, yaw_deg=0.0, pitch_deg=90.0, roll_deg=0.0, horizontal_accuracy_m=0.02, vertical_accuracy_m=0.03, width=1, height=1, sha256="c" * 64, rtk_std_lat_raw=0.01, rtk_std_lon_raw=0.01, rtk_std_hgt_raw=0.015, ) options = MODULE.odx_option_recommendations([record]) self.assertNotIn("gps-accuracy-m", options["recommendations"]) self.assertIn("Leave unset", options["conditional_options"]["gps-accuracy"]) if __name__ == "__main__": unittest.main()