Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Feb 9, 2026

Addresses review comments on PR #358's spatial optimization. Four issues: (1) missing IDL test coverage, (2) find_nearby_issues returns approximation instead of accurate distance, (3) misleading comments, (4) inconsistent Earth radius constants.

Changes

  • Hybrid distance calculation: Use equirectangular squared-distance as pre-filter, compute Haversine only for candidates that pass. Maintains ~4x speedup while returning accurate great-circle distances to callers.

  • IDL test coverage: Added test cases for ±180° boundary and high-latitude (60°N) scenarios where longitude compression matters.

  • Unified Earth radius: Replaced hardcoded R = 6378137.0 in get_bounding_box with shared EARTH_RADIUS_METERS = 6371000.0. Documented choice of mean radius over WGS84 equatorial radius.

  • Clarified documentation: Updated comments and docstrings to specify returned distances are Haversine (great-circle), not approximations.

# Before: Only equirectangular (fast but approximate)
if dist_sq <= radius_sq:
    distance = math.sqrt(dist_sq)  # Approximation
    nearby_issues.append((issue, distance))

# After: Hybrid approach (fast pre-filter + accurate result)
if dist_sq <= radius_sq:
    distance = haversine_distance(target_lat, target_lon, issue.latitude, issue.longitude)
    nearby_issues.append((issue, distance))

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.


Summary by cubic

Optimized spatial deduplication with a fast equirectangular pre-filter and Haversine for final, sorted distances. Unified Earth-radius usage to the mean radius and expanded tests for edge cases.

  • Refactors
    • Pre-filter with equirectangular; compute Haversine for candidates and return distances sorted by proximity. Added focused tests for IDL/high‑latitude handling and small‑distance approximation accuracy.
    • Use EARTH_RADIUS_METERS (6371000) across utils (including bounding boxes) and document why the mean radius is preferred over WGS84 equatorial. Added Earth‑radius consistency checks.

Written for commit 6eb751c. Summary will update on new commits.

Copilot AI and others added 2 commits February 9, 2026 08:31
- Use equirectangular as pre-filter, then compute accurate Haversine distance for candidates
- Fix misleading comment about "actual distance" (now clarifies it's great-circle distance)
- Unify Earth radius constants (use EARTH_RADIUS_METERS everywhere)
- Add comprehensive IDL and high-latitude test cases

Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
Clarify why mean radius is used over WGS84 equatorial radius

Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
Copilot AI changed the title [WIP] Optimize spatial deduplication with equirectangular approximation fix(spatial): address review feedback - hybrid distance calculation and IDL test coverage Feb 9, 2026
Copilot AI requested a review from RohanExploit February 9, 2026 08:34
@RohanExploit RohanExploit marked this pull request as ready for review February 9, 2026 08:43
Copilot AI review requested due to automatic review settings February 9, 2026 08:43
@github-actions
Copy link

github-actions bot commented Feb 9, 2026

🔍 Quality Reminder

Thanks for the updates! Please ensure:
- Your changes don't break existing functionality
- All tests still pass
- Code quality standards are maintained

*The maintainers will verify that the overall project flow remains intact.*

@RohanExploit RohanExploit merged commit 91c9566 into bolt/spatial-optimization-15204600466855577516 Feb 9, 2026
3 checks passed
@github-actions github-actions bot added the size/m label Feb 9, 2026
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="tests/test_spatial_utils_only.py">

<violation number="1" location="tests/test_spatial_utils_only.py:123">
P2: Misleading comment contradicts test behavior. The comment says "shouldn't match across IDL" but the test uses a 250km radius and asserts that both issues ARE found (including across IDL). The variable name `nearby_small` is also misleading since 250km is not small.</violation>
</file>

<file name="backend/spatial_utils.py">

<violation number="1" location="backend/spatial_utils.py:135">
P2: Missing radius check after computing Haversine distance. The equirectangular pre-filter can underestimate distances, allowing issues outside the radius to be included. The accurate Haversine distance should be verified against `radius_meters` before appending.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Issue(id=6, latitude=0.0, longitude=-179.0),
]

# With small radius, shouldn't match across IDL
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Misleading comment contradicts test behavior. The comment says "shouldn't match across IDL" but the test uses a 250km radius and asserts that both issues ARE found (including across IDL). The variable name nearby_small is also misleading since 250km is not small.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/test_spatial_utils_only.py, line 123:

<comment>Misleading comment contradicts test behavior. The comment says "shouldn't match across IDL" but the test uses a 250km radius and asserts that both issues ARE found (including across IDL). The variable name `nearby_small` is also misleading since 250km is not small.</comment>

<file context>
@@ -0,0 +1,205 @@
+        Issue(id=6, latitude=0.0, longitude=-179.0),
+    ]
+    
+    # With small radius, shouldn't match across IDL
+    nearby_small = find_nearby_issues(issues_wrapped, 0.0, 179.0, radius_meters=250000)
+    print(f"  Found {len(nearby_small)} issues within 250km from 179.0°E")
</file context>
Fix with Cubic

# Calculate actual distance (sqrt of squared distance)
distance = math.sqrt(dist_sq)
# Calculate accurate great-circle distance for candidates that passed filter
distance = haversine_distance(target_lat, target_lon, issue.latitude, issue.longitude)
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Missing radius check after computing Haversine distance. The equirectangular pre-filter can underestimate distances, allowing issues outside the radius to be included. The accurate Haversine distance should be verified against radius_meters before appending.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/spatial_utils.py, line 135:

<comment>Missing radius check after computing Haversine distance. The equirectangular pre-filter can underestimate distances, allowing issues outside the radius to be included. The accurate Haversine distance should be verified against `radius_meters` before appending.</comment>

<file context>
@@ -120,16 +123,16 @@ def find_nearby_issues(
-            # Calculate actual distance (sqrt of squared distance)
-            distance = math.sqrt(dist_sq)
+            # Calculate accurate great-circle distance for candidates that passed filter
+            distance = haversine_distance(target_lat, target_lon, issue.latitude, issue.longitude)
             nearby_issues.append((issue, distance))
 
</file context>
Suggested change
distance = haversine_distance(target_lat, target_lon, issue.latitude, issue.longitude)
distance = haversine_distance(target_lat, target_lon, issue.latitude, issue.longitude)
if distance > radius_meters:
continue
Fix with Cubic

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves the spatial deduplication utilities and related guidance by returning accurate great-circle distances while preserving the equirectangular performance optimization, and adds International Date Line-focused tests.

Changes:

  • Hybrid distance calculation: equirectangular squared-distance pre-filter + Haversine for returned distances in find_nearby_issues.
  • Unified Earth radius constant usage in spatial helpers.
  • Added/expanded IDL and high-latitude test coverage; updated internal optimization notes.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
backend/spatial_utils.py Unifies Earth radius constant and switches nearby-issue distance output to accurate Haversine after a fast pre-filter.
tests/test_spatial_deduplication.py Adds an IDL handling test for spatial utilities.
tests/test_spatial_utils_only.py Introduces a focused spatial utility test suite (Haversine/equirectangular/IDL/constant checks).
.jules/bolt.md Updates internal “bolt” guidance to document the hybrid pre-filter + accurate-distance approach.
Comments suppressed due to low confidence (1)

backend/spatial_utils.py:38

  • get_bounding_box can return min_lon/max_lon outside the [-180, 180] range (or a range that crosses the International Date Line). Callers use these values directly in SQL Issue.longitude >= min_lon / <= max_lon filters, which will miss valid candidates across the IDL (e.g., target lon=179.9, radius=30km should include lon=-179.9, but won’t). Consider normalizing longitudes and explicitly handling the wrap case (e.g., return a flag / two longitude intervals, or provide a helper that builds the correct SQL filter with an OR when the box crosses the IDL; also consider the near-pole case where longitude should be unconstrained).
def get_bounding_box(lat: float, lon: float, radius_meters: float) -> Tuple[float, float, float, float]:
    """
    Calculate the bounding box coordinates for a given radius.
    Returns (min_lat, max_lat, min_lon, max_lon).
    """
    # Coordinate offsets in radians
    # Prevent division by zero at poles
    effective_lat = max(min(lat, 89.9), -89.9)
    dlat = radius_meters / EARTH_RADIUS_METERS
    dlon = radius_meters / (EARTH_RADIUS_METERS * math.cos(math.pi * effective_lat / 180.0))

    # Offset positions in decimal degrees
    lat_offset = dlat * 180.0 / math.pi
    lon_offset = dlon * 180.0 / math.pi

    min_lat = lat - lat_offset
    max_lat = lat + lat_offset
    min_lon = lon - lon_offset
    max_lon = lon + lon_offset


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +95 to +130
def test_international_date_line_handling():
"""Test that longitude wrapping works correctly near the International Date Line"""
print("Testing International Date Line handling...")

# Test case 1: Points near +180/-180 boundary
# Point at 179.9°E and point at -179.9°W should be ~22km apart, not ~35978km
issues = [
Issue(id=1, latitude=0.0, longitude=179.9),
Issue(id=2, latitude=0.0, longitude=-179.9),
]

# Test from eastern side of IDL
nearby_east = find_nearby_issues(issues, 0.0, 179.9, radius_meters=30000)
print(f"Found {len(nearby_east)} issues within 30km from 179.9°E")
assert len(nearby_east) == 2, f"Expected 2 issues (both sides of IDL), got {len(nearby_east)}"

# Verify the cross-IDL distance is calculated correctly
cross_idl_distance = haversine_distance(0.0, 179.9, 0.0, -179.9)
print(f"Cross-IDL distance (179.9 to -179.9): {cross_idl_distance:.2f} meters")
assert cross_idl_distance < 25000, f"Cross-IDL distance should be ~22km, got {cross_idl_distance:.2f}m"

# Test case 2: High latitude near IDL
# At 60°N, longitude degrees are compressed (1° ≈ 55.6km)
issues_high_lat = [
Issue(id=3, latitude=60.0, longitude=179.5),
Issue(id=4, latitude=60.0, longitude=-179.5),
]

nearby_high_lat = find_nearby_issues(issues_high_lat, 60.0, 179.5, radius_meters=60000)
print(f"Found {len(nearby_high_lat)} issues at 60°N within 60km")
assert len(nearby_high_lat) == 2, f"Expected 2 issues at high latitude, got {len(nearby_high_lat)}"

high_lat_distance = haversine_distance(60.0, 179.5, 60.0, -179.5)
print(f"High latitude cross-IDL distance: {high_lat_distance:.2f} meters")
assert 50000 <= high_lat_distance <= 60000, f"High-lat cross-IDL distance should be ~55.6km, got {high_lat_distance:.2f}m"

Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new IDL test validates find_nearby_issues on an in-memory list, but the production endpoints first pre-filter in SQL using get_bounding_box + longitude >= min_lon AND longitude <= max_lon. Since get_bounding_box doesn’t currently handle International Date Line wrap, the API can still miss cross-IDL candidates even if find_nearby_issues is correct. Add a test that exercises the /api/issues/nearby endpoint (or a unit test for get_bounding_box’s wrap behavior) around ±180° to prevent regressions.

Copilot uses AI. Check for mistakes.
Comment on lines +123 to +127
# With small radius, shouldn't match across IDL
nearby_small = find_nearby_issues(issues_wrapped, 0.0, 179.0, radius_meters=250000)
print(f" Found {len(nearby_small)} issues within 250km from 179.0°E")
# Both should be found as they're ~222km apart
assert len(nearby_small) == 2, f"Expected 2 issues, got {len(nearby_small)}"
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment for this case is contradictory: it says “With small radius, shouldn't match across IDL”, but the radius is 250km and the assertions expect the cross‑IDL point (~222km away) to be included. Please update the comment to reflect what’s being tested (e.g., that cross‑IDL matching occurs only when the radius is large enough).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants