如何查找geohash tdr706周边10公里范围内的所有geohashes?
tdr706 Hey there! Let's walk through exactly how to pull this off. Geohashes are a handy way to map lat/lon pairs to strings, but working with their spatial boundaries takes a bit of geometry and some clever iteration. Here's a step-by-step breakdown:
Step 1: Decode the Target Geohash to Latitude/Longitude
First, we need to get the center coordinates of tdr706—this gives us our starting point. Most programming languages have Geohash libraries to handle this easily. For example, in Python:
import geohash import math # Decode the target geohash to center lat/lon center_lat, center_lon = geohash.decode('tdr706')
Step 2: Calculate the 10km Radius Boundary Box
Since the Earth is a sphere, we can't just add a fixed number of degrees to lat/lon—longitude distances shrink as you move away from the equator. Here's how to compute the min/max lat/lon that defines our 10km radius:
- Latitude adjustment: 1 degree of latitude ≈ 111.32 km. So 10km translates to ~0.0898 degrees.
- Longitude adjustment: 1 degree of longitude ≈ 111.32 * cos(latitude) km. We calculate this using the center latitude to account for curvature.
# Calculate lat/lon offsets for 10km radius lat_offset = 10 / 111.32 # ~0.0898 degrees lon_offset = 10 / (111.32 * math.cos(math.radians(center_lat))) # Define the boundary box min_lat = center_lat - lat_offset max_lat = center_lat + lat_offset min_lon = center_lon - lon_offset max_lon = center_lon + lon_offset
Step 3: Generate All Geohashes Covering the Boundary Box
Now we need to find every Geohash whose area overlaps with our 10km boundary. There are two reliable approaches here:
Approach A: Expand Neighboring Geohashes (Efficient)
Start with the original tdr706, then recursively add all its neighboring Geohashes, checking if their bounding boxes overlap with our target range. This avoids wasting time on irrelevant areas:
def get_neighbors(gh): """Get all 8 neighboring geohashes of a given geohash""" neighbors = geohash.neighbors(gh) # Returns tuple: (north, south, east, west, northeast, southeast, northwest, southwest) return list(neighbors) def find_geohashes_in_bbox(target_gh, min_lat, max_lat, min_lon, max_lon): visited = set() queue = [target_gh] visited.add(target_gh) while queue: current_gh = queue.pop(0) # Get the bounding box of the current geohash gh_bbox = geohash.bbox(current_gh) gh_min_lat = float(gh_bbox['s']) gh_max_lat = float(gh_bbox['n']) gh_min_lon = float(gh_bbox['w']) gh_max_lon = float(gh_bbox['e']) # Check if this geohash's bbox overlaps with our target range if not (gh_max_lat < min_lat or gh_min_lat > max_lat or gh_max_lon < min_lon or gh_min_lon > max_lon): # Add all unvisited neighbors to the queue for neighbor in get_neighbors(current_gh): if neighbor not in visited: visited.add(neighbor) queue.append(neighbor) return list(visited) # Get all relevant geohashes relevant_geohashes = find_geohashes_in_bbox('tdr706', min_lat, max_lat, min_lon, max_lon)
Approach B: Iterate and Filter (Simpler but Less Efficient)
If you're working with a small boundary, you can generate all possible Geohashes at your desired precision and filter those whose centers fall within 10km of the target. Use the Haversine formula to calculate distance between two lat/lon pairs:
def haversine(lat1, lon1, lat2, lon2): """Calculate the great-circle distance between two points in km""" R = 6371 # Earth radius in km d_lat = math.radians(lat2 - lat1) d_lon = math.radians(lon2 - lon1) a = math.sin(d_lat/2)**2 + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(d_lon/2)**2 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) return R * c # Set desired precision (5 chars = ~1km resolution, 6 chars = ~150m) precision = 5 candidate_geohashes = set() # Iterate over lat/lon in small steps to generate geohashes lat_step = 0.01 # ~1.1km step lon_step = 0.01 * math.cos(math.radians(center_lat)) lat = min_lat while lat <= max_lat: lon = min_lon while lon <= max_lon: gh = geohash.encode(lat, lon, precision=precision) candidate_geohashes.add(gh) lon += lon_step lat += lat_step # Filter candidates to those within 10km final_geohashes = [] for gh in candidate_geohashes: gh_lat, gh_lon = geohash.decode(gh) distance = haversine(center_lat, center_lon, gh_lat, gh_lon) if distance <= 10: final_geohashes.append(gh)
Step 4: Validate and Refine
- Precision choice: Longer Geohashes mean more granular results (e.g., 6 characters for ~150m resolution). Just adjust the
precisionparameter in the code. - Edge cases: The boundary box method might include some Geohashes that only partially overlap with the 10km radius. Use the Haversine check (from Approach B) to filter those out if strict accuracy is needed.
内容的提问来源于stack exchange,提问作者Arjun Raaghav

