dawarich/app/services/maps/hexagon_polygon_generator.rb
2025-09-16 20:41:53 +02:00

70 lines
No EOL
2.2 KiB
Ruby

# frozen_string_literal: true
module Maps
class HexagonPolygonGenerator
DEFAULT_SIZE_METERS = 1000
def self.call(center_lng:, center_lat:, size_meters: DEFAULT_SIZE_METERS)
new(center_lng: center_lng, center_lat: center_lat, size_meters: size_meters).call
end
def initialize(center_lng:, center_lat:, size_meters: DEFAULT_SIZE_METERS)
@center_lng = center_lng
@center_lat = center_lat
@size_meters = size_meters
end
def call
generate_hexagon_polygon
end
private
attr_reader :center_lng, :center_lat, :size_meters
def generate_hexagon_polygon
# Generate hexagon vertices around center point
# PostGIS ST_HexagonGrid uses size_meters as the edge-to-edge distance (width/flat-to-flat)
# For a regular hexagon with width = size_meters:
# - Width (edge to edge) = size_meters
# - Radius (center to vertex) = width / √3 ≈ size_meters * 0.577
# - Edge length ≈ radius ≈ size_meters * 0.577
radius_meters = size_meters / Math.sqrt(2.7) # Convert width to radius
# Convert meter radius to degrees (rough approximation)
# 1 degree latitude ≈ 111,111 meters
# 1 degree longitude ≈ 111,111 * cos(latitude) meters
lat_degree_in_meters = 111_111.0
lng_degree_in_meters = lat_degree_in_meters * Math.cos(center_lat * Math::PI / 180)
radius_lat_degrees = radius_meters / lat_degree_in_meters
radius_lng_degrees = radius_meters / lng_degree_in_meters
vertices = build_vertices(radius_lat_degrees, radius_lng_degrees)
{
'type' => 'Polygon',
'coordinates' => [vertices]
}
end
def build_vertices(radius_lat_degrees, radius_lng_degrees)
vertices = []
6.times do |i|
# Calculate angle for each vertex (60 degrees apart, starting from 0)
angle = (i * 60) * Math::PI / 180
# Calculate vertex position
lat_offset = radius_lat_degrees * Math.sin(angle)
lng_offset = radius_lng_degrees * Math.cos(angle)
vertices << [center_lng + lng_offset, center_lat + lat_offset]
end
# Close the polygon by adding the first vertex at the end
vertices << vertices.first
vertices
end
end
end