CCCPaste

geo_maths.gd

# geo_maths.gd
# geospatial mathematics utilities for earth globe
# translated from geographical-adventures geomaths.cs

class_name GeoMaths

const EARTH_RADIUS_KM: float = 6371.0
const EARTH_CIRCUMFERENCE_KM: float = EARTH_RADIUS_KM * PI * 2.0

# convert point on unit sphere to coordinate (longitude, latitude in radians)
static func point_to_coordinate(point_on_unit_sphere: Vector3) -> Vector2:
var latitude = asin(point_on_unit_sphere.y)
var a = point_on_unit_sphere.x
var b = -point_on_unit_sphere.z
var longitude = atan2(a, b)
return Vector2(longitude, latitude)

# calculate point on sphere given longitude and latitude (in radians) and radius
static func coordinate_to_point(longitude: float, latitude: float, radius: float = 1.0) -> Vector3:
var y = sin(latitude)
var r = cos(latitude) # radius of 2d circle cut through sphere at y
var x = sin(longitude) * r
var z = -cos(longitude) * r
return Vector3(x, y, z) * radius

# convert coordinate (lon, lat in radians) to uv texture coordinates [0,1]
static func coordinate_to_uv(longitude: float, latitude: float) -> Vector2:
var u = (longitude + PI) / (2.0 * PI)
var v = (latitude + PI / 2.0) / PI
return Vector2(u, v)

# convert point on unit sphere to uv coordinates
static func point_to_uv(point_on_unit_sphere: Vector3) -> Vector2:
var coord = point_to_coordinate(point_on_unit_sphere)
return coordinate_to_uv(coord.x, coord.y)

# convert uv coordinates to coordinate (lon, lat in radians)
static func uv_to_coordinate(uv: Vector2) -> Vector2:
var longitude = (uv.x - 0.5) * 2.0 * PI
var latitude = (uv.y - 0.5) * PI
return Vector2(longitude, latitude)

# convert uv coordinates to point on unit sphere
static func uv_to_point_on_sphere(uv: Vector2) -> Vector3:
var coord = uv_to_coordinate(uv)
return coordinate_to_point(coord.x, coord.y)

# calculate distance between two points on unit sphere (result in radians)
static func distance_between_points_on_unit_sphere(a: Vector3, b: Vector3) -> float:
# more precise for small distances than acos(dot(a,b))
return atan2(a.cross(b).length(), a.dot(b))