Files
uarep-ctl/scenes/tilemap/tilemap.gd

174 lines
8.5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class_name main_tilemap extends Sprite2D
## Возможные состояния конечного автомата заданий.
enum TASK_STATE {
DONE, ## Выполнено.
WAIT, ## Ожидание плитки.
RUN, ## Запуск выполнения.
CHECK, ## Проверка пустого места.
ERROR ## Ошибка.
}
## Координаты для проверок [lng, lat].
const TEST_DATA: = {
'Калиниград': [ 20.51095, 54.70649 ],
'Москва': [ 37.6156, 55.7522 ],
'Нью-Йорк': [ -74.006, 40.7143 ],
'Сидней': [ 151.20732, -33.8678500 ],
'Таганрог': [ 38.8969, 47.2362 ],
'Хельсинки': [ 24.9354, 60.1695 ],
'Азорские о-ва': [ 28.3996582, 38.5397568 ],
'Мехико': [ -99.12766, 19.42847 ],
'Белое море': [ 68.136606, 42.045546 ],
'море Беллинсгаузена': [ -72.406587, -74.857997 ],
'Фиджи': [ 178.065032, -17.713371 ],
'Ноль': [ 0.0, 0.0 ],
'Точка1': [ 170.0, 0.0 ],
'Точка2': [-170.0, 0.0 ],
'Море' : [ 19.4, 54.91 ] }
const MAP_MODES: = {
0: 'application/config/map_image_size_rto',
1: 'application/config/map_image_size_rls' }
const MAP_RELATIVE_RADIUSES: = {
0: 0.39,
1: 0.466
}
var map_image: Image ## Изображение с картой.
var map_tile_state: TASK_STATE ## Текущее состояние конечного автомата плитки.
var map_bcs: Vector3 ## Яркость, контраст насыщенность.
var map_server_addr: String ## Адрес сервера изображений карт в проекции Меркатора.
var map_tile_format: String ##
var map_tile_stack: Array ## Стек для хранения плиток карты.
var map_request: HTTPRequest ## Обработчик запросов http.
var map_zoom: int ## Уровень детализации карты.
var map_tile: Rect2i ## Область одной плитки: [x-координата области, y-координата области, x-индекс плитки, y-индекс плитки].
var map_mode: int ## Режим карты: 0 - приоритет РТО, 1 - приоритет РЛС.
var prev_tiles_dic: Dictionary ##
var lnglat: Array ## Текущие координаты.
var root_rect: Rect2i
func _ready():
lnglat = TEST_DATA['Таганрог']
map_tile_state = TASK_STATE.DONE
map_request = HTTPRequest.new()
add_child(map_request)
map_request.request_completed.connect(self._map_request_completed)
map_bcs = ProjectSettings.get_setting('application/config/map_bcs', Vector3(1.0, 1.0, 1.0))
map_server_addr = ProjectSettings.get_setting('application/config/map_server_addr')
map_tile_format = ProjectSettings.get_setting('application/config/map_tile_format', '%s/%d/%d/%d.png')
var map_image_size = ProjectSettings.get_setting(MAP_MODES[0], Vector2i(512, 512))
var map_tile_size = ProjectSettings.get_setting('application/config/map_tile_size', 256)
map_image = Image.create(map_image_size.x, map_image_size.y, true, Image.FORMAT_RGB8)
map_tile = Rect2i(0, 0, map_tile_size, map_tile_size)
signaller.connect('zoom_changed', Callable(self, '_on_zoom_changed'))
signaller.connect('map_mode_changed', Callable(self, '_on_map_mode_changed'))
log.info('Адрес сервера поставщика карт: \"%s\"' % map_server_addr)
log.info('Модуль географической карты готов')
func _on_map_mode_changed(mode: int) -> void:
var map_image_size = ProjectSettings.get_setting(MAP_MODES[mode])
material.set('shader_parameter/radius', MAP_RELATIVE_RADIUSES[mode])
map_image.fill(Color(0, 0, 0, 0))
map_image.resize(map_image_size.x, map_image_size.y)
map_tile_state = TASK_STATE.DONE
map_mode = mode
var tile: = mercator.create_tile(lnglat[0], lnglat[1], map_zoom)
map_tile_stack.clear()
map_tile_stack.append(tile)
prev_tiles_dic.clear()
func mark_image_center(image: Image, color: Color = Color.RED):
var c = image.get_size() / 2
map_image.set_pixel(c.x - 1, c.y - 1, color)
map_image.set_pixel(c.x - 1, c.y, color)
map_image.set_pixel(c.x, c.y - 1, color)
map_image.set_pixel(c.x, c.y, color)
func _on_zoom_changed(zoom: int):
if map_tile_stack.size() != 0:
return
map_zoom = zoom
var tile: = mercator.create_tile(lnglat[0], lnglat[1], zoom)
map_tile_stack.clear()
map_tile_stack.append(tile)
prev_tiles_dic.clear()
func img_tile_to_map_image(image: Image, dst_pos: Vector2i):
image.adjust_bcs(map_bcs.x, map_bcs.y, map_bcs.z)
map_image.blit_rect(image, map_tile, dst_pos)
func _process(_delta: float):
if (map_tile_state == TASK_STATE.DONE) and map_tile_stack.size():
var tile: mercator.Tile = map_tile_stack[-1]
var tile_addr: = map_tile_format % [map_server_addr, tile.z, tile.x , tile.y]
var rc = map_request.request(tile_addr)
if rc == OK:
map_tile_state = TASK_STATE.WAIT
else:
log.error('%s: Невозможно сформировать запрос HTTP' % self)
map_tile_state = TASK_STATE.ERROR
elif map_tile_state == TASK_STATE.CHECK:
var root_tile: = mercator.Tile.new(root_rect.size.x, root_rect.size.y, map_zoom)
var neighbors_tiles = mercator.get_perimetr_tiles(root_tile, (map_image.get_size().x / map_tile.size.x) / 2)
var neighbors_tiles_dic = {}
for tile in neighbors_tiles:
neighbors_tiles_dic[[tile.x, tile.y]] = false
if neighbors_tiles_dic != prev_tiles_dic:
for tile in neighbors_tiles:
tile.is_root = false
map_tile_stack.push_front(tile)
prev_tiles_dic[[tile.x, tile.y]] = false
else:
if map_tile_stack.size() == 0:
signaller.emit_signal('zoom_complete', map_zoom)
map_tile_state = TASK_STATE.DONE
func _map_request_completed(result, response_code, headers, data):
if result != HTTPRequest.RESULT_SUCCESS:
log.error('%s: Запрос не обработан. result: \"%s\", response_code: \"%s\", headers: \"%s\"' % [self, result, response_code, headers])
map_tile_state = TASK_STATE.ERROR
return
var img_tile = Image.new()
var error = img_tile.load_png_from_buffer(data)
if error != OK:
log.error('%s: Полученые данные невозможно использовать для формироания изображения. result: \"%s\", response_code: \"%s\", headers: \"%s\"' % [self, result, response_code, headers])
map_tile_state = TASK_STATE.ERROR
return
var tile = map_tile_stack.pop_back()
map_tile_state = TASK_STATE.CHECK
if tile.is_root:
# Отображение корневой плитки
map_image.fill(Color(0, 0, 0, 0))
var bounds: = mercator.bounds(tile)
var lng_c = (bounds.east + bounds.west) / 2.0
var lat_c = (bounds.north + bounds.south) / 2.0
var sx: float = float(map_tile.size.x) / (bounds.east - bounds.west) * (lng_c - tile.lng) + map_tile.size.x / 2.0 # Cмещение в пискселях центра плитки от заданной точки по горизонтали.
var sy: float = float(map_tile.size.y) / (bounds.north - bounds.south) * (lat_c - tile.lat) - map_tile.size.y / 2.0 # Cмещение в пискселях центра плитки от заданной точки по вертикали.
var dst_pos: Vector2i = Vector2i(int(sx), int(-sy)) + map_tile.size * map_mode
img_tile_to_map_image(img_tile, dst_pos)
root_rect = Rect2i(dst_pos.x, dst_pos.y, tile.x, tile.y)
else:
# Отображение соседних плиток
var delta: = Vector2i(tile.x - root_rect.size.x, tile.y - root_rect.size.y)
var dst_pos: Vector2i = root_rect.position + delta * map_tile.size
img_tile_to_map_image(img_tile, dst_pos)
mark_image_center(map_image)
texture = ImageTexture.create_from_image(map_image)