mirror of
https://github.com/enzet/map-machine.git
synced 2025-05-16 18:46:24 +02:00
Mapper.
This commit is contained in:
commit
becf68f7e1
3 changed files with 1079 additions and 0 deletions
120
flinger.py
Normal file
120
flinger.py
Normal file
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Author: Sergey Vartanov (me@enzet.ru)
|
||||
"""
|
||||
|
||||
import math
|
||||
import sys
|
||||
|
||||
sys.path.append('lib')
|
||||
|
||||
from vector import Vector
|
||||
|
||||
|
||||
class Flinger(object):
|
||||
"""
|
||||
Flinger. Coordinates repositioning.
|
||||
"""
|
||||
def __init__(self, minimum, maximum, target_minimum=None, target_maximum=None, ratio=None):
|
||||
self.minimum = minimum
|
||||
self.maximum = maximum
|
||||
|
||||
if not target_minimum:
|
||||
target_minimum = Vector()
|
||||
if not target_maximum:
|
||||
target_maximum = maximum - minimum
|
||||
|
||||
space = Vector()
|
||||
|
||||
if ratio:
|
||||
if ratio == 'geo':
|
||||
ratio = math.sin((90.0 - ((self.maximum.y + self.minimum.y) / 2.0)) / 180.0 * math.pi)
|
||||
|
||||
current_ratio = (self.maximum.x - self.minimum.x) * ratio / (self.maximum.y - self.minimum.y)
|
||||
target_ratio = (target_maximum.x - target_minimum.x) / (target_maximum.y - target_minimum.y)
|
||||
|
||||
if current_ratio >= target_ratio:
|
||||
n = (target_maximum.x - target_minimum.x) / (maximum.x - minimum.x) / ratio
|
||||
space.y = ((target_maximum.y - target_minimum.y) - (maximum.y - minimum.y) * n) / 2.0
|
||||
space.x = 0
|
||||
else:
|
||||
n = (target_maximum.y - target_minimum.y) / (maximum.y - minimum.y)
|
||||
space.x = ((target_maximum.x - target_minimum.x) - (maximum.x - minimum.x) * n) / 2.0
|
||||
space.y = 0
|
||||
|
||||
target_minimum.x += space
|
||||
target_maximum.x += space
|
||||
|
||||
self.target_minimum = target_minimum
|
||||
self.target_maximum = target_maximum
|
||||
|
||||
def fling(self, current):
|
||||
"""
|
||||
Fling current point to the surface.
|
||||
"""
|
||||
x = map_(current.x, self.minimum.x, self.maximum.x, self.target_minimum.x, self.target_maximum.x)
|
||||
y = map_(current.y, self.minimum.y, self.maximum.y, self.target_minimum.y, self.target_maximum.y)
|
||||
return Vector(x, y)
|
||||
|
||||
|
||||
class Geo:
|
||||
def __init__(self, lat, lon):
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
def __add__(self, other):
|
||||
return Geo(self.lat + other.lat, self.lon + other.lon)
|
||||
def __sub__(self, other):
|
||||
return Geo(self.lat - other.lat, self.lon - other.lon)
|
||||
def __repr__(self):
|
||||
return `self.lat` + ', ' + `self.lon`
|
||||
|
||||
|
||||
class GeoFlinger:
|
||||
def __init__(self, minimum, maximum, target_minimum=None, target_maximum=None):
|
||||
self.minimum = minimum
|
||||
self.maximum = maximum
|
||||
|
||||
# Ratio is depended of latitude. It is always <= 1.
|
||||
# In one latitude degree is always 40 000 / 360 km.
|
||||
# In one current longitude degree is about 40 000 / 360 * ratio km.
|
||||
|
||||
ratio = math.sin((90.0 - ((self.maximum.lat + self.minimum.lat) / 2.0)) / 180.0 * math.pi)
|
||||
|
||||
# Longitude displayed as x.
|
||||
# Latitude displayed as y.
|
||||
|
||||
# Ratio is x / y.
|
||||
|
||||
space = Vector()
|
||||
current_ratio = (self.maximum.lon - self.minimum.lon) * ratio / (self.maximum.lat - self.minimum.lat)
|
||||
target_ratio = (target_maximum.x - target_minimum.x) / (target_maximum.y - target_minimum.y)
|
||||
|
||||
if current_ratio >= target_ratio:
|
||||
n = (target_maximum.x - target_minimum.x) / (maximum.lon - minimum.lon) / ratio
|
||||
space.y = ((target_maximum.y - target_minimum.y) - (maximum.lat - minimum.lat) * n) / 2.0
|
||||
space.x = 0
|
||||
else:
|
||||
n = (target_maximum.y - target_minimum.y) / (maximum.lat - minimum.lat) * ratio
|
||||
space.x = ((target_maximum.x - target_minimum.x) - (maximum.lon - minimum.lon) * n) / 2.0
|
||||
space.y = 0
|
||||
|
||||
self.target_minimum = target_minimum + space
|
||||
self.target_maximum = target_maximum - space
|
||||
|
||||
self.space = space
|
||||
|
||||
def fling(self, current):
|
||||
x = map_(current.lon, self.minimum.lon, self.maximum.lon,
|
||||
self.target_minimum.x, self.target_maximum.x)
|
||||
y = map_(self.maximum.lat + self.minimum.lat - current.lat,
|
||||
self.minimum.lat, self.maximum.lat,
|
||||
self.target_minimum.y, self.target_maximum.y)
|
||||
return Vector(x, y)
|
||||
|
||||
|
||||
def map_(value, current_min, current_max, target_min, target_max):
|
||||
"""
|
||||
Map current value in bounds of current_min and current_max to bounds of target_min and target_max.
|
||||
"""
|
||||
return target_min + (value - current_min) / (current_max - current_min) * (target_max - target_min)
|
Loading…
Add table
Add a link
Reference in a new issue