One directory with sixty scripts stopped being navigable, and the grouping is also the sandbox boundary:
Tools/unreal/ commandlets and the two map builders, with ue_common.py and ue_placement.py as the
shared imports (they need the engine)
Tools/blender/ builders, exporters, the FBX preset, the MPFB character pipeline, blender_screenshots
(they need the Blender Flatpak)
Tools/review/ the visual loop: render_screenshots.sh, judge_screenshot.py, hero_compare.py,
build_comparison_md.py, e2e_asset_check.py, hero_iterate.sh, visual_loop.py,
visual_targets.json
Tools/gen/ image and texture generation: the ComfyUI driver, deterministic texture writers,
reference fetching
Tools/input/ OS-level input injection
root _common.py, check-lfs.sh, addon_compat_probe.py, sibling_asset_audit.py, tests/
Every moved script now resolves the repository root as ../.. and puts the tools root plus its siblings on
sys.path, so 'import ue_common' still works from unreal/. The test suite bootstrap does the same for the five
folders. render_screenshots.sh takes the folder as a third argument to run_cmdlet, and the e2e driver,
hero_iterate.sh and the comparison generator were repointed.
51 README rows now link to their new location, the README gains a Layout section naming each folder's
sandbox, and the architecture notes and Blender README follow the moves.
Verified: 108 tests pass, prettier is clean, judge_screenshot.py and hero_compare.py run from their new
homes, and the e2e run was aborted mid-way (it had been rebuilding an empty DemoMap for 15 minutes) and is
being rerun against the new layout.
127 lines
4.7 KiB
Python
127 lines
4.7 KiB
Python
"""Tests for Geo/tools/mapbox_buildings.py — the pure merge logic.
|
|
|
|
No network calls here: Tilequery responses are represented as the small dicts
|
|
the API returns, and only the selection/comparison/formatting helpers are
|
|
exercised. The live call is verified by running the tool.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
_TOOLS = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
sys.path.insert(0, _TOOLS)
|
|
for _sub in ("review", "gen", "unreal", "blender", "input"):
|
|
sys.path.insert(0, os.path.join(_TOOLS, _sub))
|
|
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import unittest
|
|
|
|
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
|
sys.path.insert(0, os.path.join(ROOT, "Geo", "tools"))
|
|
|
|
import mapbox_buildings as mb # noqa: E402
|
|
|
|
|
|
def feature(distance, height=None, min_height=0, type_="building", layer="building"):
|
|
props = {"tilequery": {"distance": distance, "layer": layer}}
|
|
if height is not None:
|
|
props["height"] = height
|
|
props["min_height"] = min_height
|
|
props["type"] = type_
|
|
return {"properties": props}
|
|
|
|
|
|
class NearestBuildingTest(unittest.TestCase):
|
|
def test_picks_the_closest_building(self):
|
|
payload = {"features": [feature(6.0, 10.0), feature(1.0, 20.0)]}
|
|
best = mb.nearest_building(payload, max_distance=8.0)
|
|
self.assertEqual(best["height"], 20.0)
|
|
|
|
def test_ignores_hits_beyond_max_distance(self):
|
|
payload = {"features": [feature(20.0, 10.0)]}
|
|
self.assertIsNone(mb.nearest_building(payload, max_distance=8.0))
|
|
|
|
def test_ignores_other_layers(self):
|
|
payload = {"features": [feature(0.0, 10.0, layer="road")]}
|
|
self.assertIsNone(mb.nearest_building(payload, max_distance=8.0))
|
|
|
|
def test_no_features(self):
|
|
self.assertIsNone(mb.nearest_building({"features": []}, max_distance=8.0))
|
|
|
|
|
|
class CompareTest(unittest.TestCase):
|
|
def test_match_within_half_a_metre(self):
|
|
self.assertEqual(mb.compare(14.5, "height tag", 14.2)[0], "match")
|
|
|
|
def test_close_within_two_metres(self):
|
|
verdict, delta = mb.compare(38.4, "levels x 3.2 m", 37.2)
|
|
self.assertEqual(verdict, "close")
|
|
self.assertAlmostEqual(delta, -1.2)
|
|
|
|
def test_disagree_beyond_two_metres(self):
|
|
verdict, delta = mb.compare(6.4, "GUESS: default 2 levels x 3.2 m", 3.0)
|
|
self.assertEqual(verdict, "disagree")
|
|
self.assertAlmostEqual(delta, -3.4)
|
|
|
|
def test_mapbox_only_when_we_have_nothing(self):
|
|
self.assertEqual(mb.compare(0.0, "height tag", 12.0)[0], "mapbox-only")
|
|
|
|
def test_ours_only_when_mapbox_returns_nothing(self):
|
|
self.assertEqual(mb.compare(12.0, "height tag", None)[0], "ours-only")
|
|
|
|
def test_non_building_is_excluded_from_comparison(self):
|
|
verdict, delta = mb.compare(0.0, "not a building volume (roof)", 3.0)
|
|
self.assertEqual(verdict, "non-building")
|
|
self.assertIsNone(delta)
|
|
|
|
def test_canopy_is_non_building(self):
|
|
verdict, _ = mb.compare(0.0, "not a building volume (canopy)", 3.0)
|
|
self.assertEqual(verdict, "non-building")
|
|
|
|
|
|
class CentroidTest(unittest.TestCase):
|
|
def test_centroid_of_a_square(self):
|
|
lat, lon = mb.centroid_lat_lon(
|
|
[(34.0, -118.0), (34.0, -117.0), (35.0, -117.0), (35.0, -118.0)])
|
|
self.assertAlmostEqual(lat, 34.5)
|
|
self.assertAlmostEqual(lon, -117.5)
|
|
|
|
|
|
class RenderTest(unittest.TestCase):
|
|
ARGS = type("A", (), {"radius": 25, "max_distance": 8.0, "only_diffs": False})()
|
|
|
|
def test_disagreements_sort_first(self):
|
|
rows = [
|
|
{"verdict": "match", "delta_m": 0.1, "way": 1, "name": "", "kind": "yes",
|
|
"osm_height_m": 10.0, "osm_source": "height tag", "mapbox_height_m": 10.1,
|
|
"mapbox_min_height_m": 0, "mapbox_type": "building",
|
|
"mapbox_distance_m": 0.0, "cached": True, "lat": 0, "lon": 0},
|
|
{"verdict": "disagree", "delta_m": -3.4, "way": 2, "name": "", "kind": "yes",
|
|
"osm_height_m": 6.4, "osm_source": "GUESS", "mapbox_height_m": 3.0,
|
|
"mapbox_min_height_m": 0, "mapbox_type": "building",
|
|
"mapbox_distance_m": 0.0, "cached": True, "lat": 0, "lon": 0},
|
|
]
|
|
text = mb.render_markdown(rows, self.ARGS)
|
|
self.assertLess(text.index("way 2"), text.index("way 1"))
|
|
|
|
def test_never_contains_a_token(self):
|
|
rows = []
|
|
text = mb.render_markdown(rows, self.ARGS)
|
|
self.assertNotIn("access_token", text)
|
|
self.assertNotIn("sk.", text)
|
|
|
|
|
|
class TokenTest(unittest.TestCase):
|
|
def test_explicit_token_wins(self):
|
|
self.assertEqual(mb.load_token("abc123"), "abc123")
|
|
|
|
def test_token_is_stripped(self):
|
|
self.assertEqual(mb.load_token(" abc123\n"), "abc123")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|