@mytec: iter3.2.2 ready for test

This commit is contained in:
2026-02-02 12:42:02 +02:00
parent c8c2608266
commit f5429e40fd
2 changed files with 60 additions and 16 deletions

View File

@@ -167,10 +167,14 @@ def find_dominant_paths_vectorized(
3. Vectorized reflection point calculation
4. Simplified diffraction estimate
Callers should pass pre-filtered buildings and spatial_idx=None
to avoid redundant spatial queries (coverage_service already filters).
Returns dict with:
has_los, path_type, total_loss, path_length, reflection_point
"""
global _vec_log_count
t_total = time.perf_counter()
# Fast path: no buildings at all → direct LOS, skip all numpy work
has_spatial_data = spatial_idx is not None and spatial_idx._grid
@@ -183,11 +187,13 @@ def find_dominant_paths_vectorized(
'reflection_point': None,
}
# Get nearby buildings via spatial index (same filtering as sync version)
# Get nearby buildings via spatial index or use pre-filtered list
t0 = time.perf_counter()
if spatial_idx:
line_buildings = spatial_idx.query_line(tx_lat, tx_lon, rx_lat, rx_lon)
else:
line_buildings = buildings
t_query = time.perf_counter() - t0
# No nearby buildings along this line → direct LOS
if not line_buildings:
@@ -199,12 +205,14 @@ def find_dominant_paths_vectorized(
'reflection_point': None,
}
t0 = time.perf_counter()
line_buildings = _filter_buildings_by_distance(
line_buildings,
(tx_lat, tx_lon), (rx_lat, rx_lon),
max_count=MAX_BUILDINGS_FOR_LINE,
max_distance=MAX_DISTANCE_FROM_PATH,
)
t_filter = time.perf_counter() - t0
# Reference point for local coordinate system
ref_lat = (tx_lat + rx_lat) / 2
@@ -219,19 +227,11 @@ def find_dominant_paths_vectorized(
direct_dist = np.linalg.norm(rx - tx)
# Convert buildings to arrays
t0 = time.perf_counter()
walls_start, walls_end, wall_to_bldg, poly_x, poly_y, poly_lengths = (
_buildings_to_arrays(line_buildings, ref_lat, ref_lon)
)
# Diagnostic log for first few points
_vec_log_count += 1
if _vec_log_count <= 3:
print(
f"[DOMINANT_PATH_VEC] Point #{_vec_log_count}: "
f"buildings={len(line_buildings)}, walls={len(walls_start)}, "
f"dist={direct_dist:.0f}m",
flush=True,
)
t_arrays = time.perf_counter() - t0
# No buildings → direct LOS
if len(poly_lengths) == 0 or np.all(poly_lengths < 3):
@@ -244,9 +244,22 @@ def find_dominant_paths_vectorized(
}
# Step 1: Vectorized direct LOS check
t0 = time.perf_counter()
intersects, _ = line_intersects_polygons_batch(tx, rx, poly_x, poly_y, poly_lengths)
t_los = time.perf_counter() - t0
if not np.any(intersects):
t_total_ms = (time.perf_counter() - t_total) * 1000
_vec_log_count += 1
if _vec_log_count <= 10:
print(
f"[DP_TIMING] #{_vec_log_count} LOS_CLEAR "
f"bldgs={len(line_buildings)} walls={len(walls_start)} "
f"query={t_query*1000:.1f}ms filter={t_filter*1000:.1f}ms "
f"arrays={t_arrays*1000:.1f}ms los={t_los*1000:.1f}ms "
f"total={t_total_ms:.1f}ms",
flush=True,
)
return {
'has_los': True,
'path_type': 'direct',
@@ -256,7 +269,8 @@ def find_dominant_paths_vectorized(
}
# Step 2: Vectorized reflection path finding
# Use all line buildings for reflection walls
# Reuse line buildings for reflection (no separate spatial query)
t0 = time.perf_counter()
if spatial_idx:
mid_lat = (tx_lat + rx_lat) / 2
mid_lon = (tx_lon + rx_lon) / 2
@@ -280,15 +294,34 @@ def find_dominant_paths_vectorized(
else:
r_walls_start, r_walls_end, r_wall_to_bldg = walls_start, walls_end, wall_to_bldg
r_poly_x, r_poly_y, r_poly_lengths = poly_x, poly_y, poly_lengths
t_refl_setup = time.perf_counter() - t0
t0 = time.perf_counter()
refl_point, refl_length, refl_loss = find_best_reflection_path_vectorized(
tx, rx,
r_walls_start, r_walls_end, r_wall_to_bldg,
r_poly_x, r_poly_y, r_poly_lengths,
max_candidates=30,
max_walls=100,
max_los_checks=10,
max_los_checks=5,
)
t_refl_calc = time.perf_counter() - t0
t_total_ms = (time.perf_counter() - t_total) * 1000
# Diagnostic log for first few points
_vec_log_count += 1
if _vec_log_count <= 10:
print(
f"[DP_TIMING] #{_vec_log_count} LOS_BLOCKED "
f"bldgs={len(line_buildings)} walls={len(walls_start)} "
f"dist={direct_dist:.0f}m "
f"query={t_query*1000:.1f}ms filter={t_filter*1000:.1f}ms "
f"arrays={t_arrays*1000:.1f}ms los={t_los*1000:.1f}ms "
f"refl_setup={t_refl_setup*1000:.1f}ms refl_calc={t_refl_calc*1000:.1f}ms "
f"total={t_total_ms:.1f}ms",
flush=True,
)
if refl_point is not None:
# Convert reflection point back to lat/lon