2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2026-05-10 16:07:23 +01:00

more area location tests

This commit is contained in:
2026-05-09 21:55:53 +01:00
parent dbb9f35d9b
commit b0dc464796
3 changed files with 91 additions and 21 deletions
+73 -3
View File
@@ -75,6 +75,76 @@ def run_12_point_test(which_area_func):
print(f"\nSummary: {passed}/12 points passed.")
# Uncomment to run:
run_limit_tests(which_area)
run_12_point_test(which_area)
import random
import time
import xml.etree.ElementTree as ET
from position_utils import which_area
def generate_performance_test(num_points=200):
# Border limits derived from GPX data
west_lon = 13.72476763 # Point 1626-22
east_lon = 13.86031535 # Point 1626-256
# Calculate the span to create a square N/S range
span = east_lon - west_lon
# Midpoint of the border (approximate center for the test square)
mid_lat = 47.69
min_lat = mid_lat - (span / 2)
max_lat = mid_lat + (span / 2)
test_points = []
for _ in range(num_points):
lat = random.uniform(min_lat, max_lat)
lon = random.uniform(west_lon, east_lon)
test_points.append((lat, lon))
return test_points
def export_random_points_gpx(points_with_results, filename="random_test_points.gpx"):
root = ET.Element("gpx", version="1.1", creator="PerformanceTester",
xmlns="http://www.topografix.com/GPX/1/1")
for lat, lon, area, valid in points_with_results:
wpt = ET.SubElement(root, "wpt", lat=f"{lat:.8f}", lon=f"{lon:.8f}")
name = ET.SubElement(wpt, "name")
name.text = f"{area}"
desc = ET.SubElement(wpt, "desc")
desc.text = f"Valid: {valid}"
tree = ET.ElementTree(root)
tree.write(filename, encoding="utf-8", xml_declaration=True)
print(f"Random points exported to {filename}")
def run_performance_test():
# 1. Generate coordinates
coords = generate_performance_test(200)
results = []
# 2. Start Timing
start_time = time.perf_counter()
for lat, lon in coords:
valid, area = which_area(lat, lon)
results.append((lat, lon, area, valid))
end_time = time.perf_counter()
# 3. Output results
total_time_ms = (end_time - start_time) * 1000
avg_time_us = (total_time_ms * 1000) / len(coords)
print(f"--- Performance Results ---")
print(f"Total time for {len(coords)} points: {total_time_ms:.4f} ms")
print(f"Average time per lookup: {avg_time_us:.2f} microseconds")
# 4. Export for visualization
export_random_points_gpx(results)
if __name__ == "__main__":
run_limit_tests(which_area)
run_12_point_test(which_area)
run_performance_test()
+16 -18
View File
@@ -6,7 +6,7 @@ def load_and_clean_gpx(filename):
if not Path(filename).exists:
print("No file")
else:
print(f"Loading {filename}")
print(f"Loading '{filename}'")
# Parse GPX
tree = ET.parse(filename)
root = tree.getroot()
@@ -64,7 +64,7 @@ def save_cleaned_gpx(points, output_filename="cleaned_border.gpx"):
ET.indent(tree, space="\t", level=0)
tree.write(output_filename, encoding="windows-1252", xml_declaration=True)
print(f"Cleaned track exported to {output_filename}")
print(f"Cleaned track exported to '{output_filename}'")
def split_into_monotonic_segments(points):
@@ -94,18 +94,11 @@ def split_into_monotonic_segments(points):
current_segment.append(p_curr)
segments.append(current_segment)
print(len(segments))
print(f"{len(segments)} segments in border.")
return segments
PREPARED_SEGMENTS = []
MIN_LON = 0
MAX_LON = 0
def generate_boundary_segments():
# Example Workflow:
points = load_and_clean_gpx('1623-6_border.gpx')
# save_cleaned_gpx(points, "cleaned_border_output.gpx") # done once, not needed
mono_segments = split_into_monotonic_segments(points)
@@ -116,6 +109,7 @@ def generate_boundary_segments():
# Prepare segments for binary search
# We store each segment as (sorted_lons, corresponding_lats)
PREPARED_SEGMENTS = []
for seg in mono_segments:
lons = [p[0] for p in seg]
lats = [p[1] for p in seg]
@@ -132,23 +126,27 @@ def generate_boundary_segments():
'min_lon': min(lons),
'max_lon': max(lons)
})
return MIN_LON, MAX_LON
return PREPARED_SEGMENTS, MIN_LON, MAX_LON
def which_area(lat, lon):
global PREPARED_SEGMENTS, MIN_LON, MAX_LON
# Initialize state on the function object itself if it doesn't exist
# Yes, this is an attrubte *on a function*, an unusual python capbility
if not hasattr(which_area, "data"):
prepared_segments, min_l, max_l = generate_boundary_segments()
which_area.data = {
"prepared_segments": prepared_segments,
"min_lon": min_l,
"max_lon": max_l
}
if not PREPARED_SEGMENTS:
MIN_LON, MAX_LON = generate_boundary_segments()
# Fast boundary check (East/West limits)
if lon < MIN_LON or lon > MAX_LON:
if lon < which_area.data["min_lon"] or lon > which_area.data["max_lon"]:
return False, "None"
# Area 1626 is North, Area 1623 is South
# We find the boundary latitude at this longitude
boundary_lat = None
for seg in PREPARED_SEGMENTS:
for seg in which_area.data["prepared_segments"]:
# Check if lon is within this monotonic segment
if seg['min_lon'] <= lon <= seg['max_lon']:
lons = seg['lons']
File diff suppressed because one or more lines are too long