В процессе. Карта отображается. Ошибка: накапливаются запросы на получение карты.
This commit is contained in:
@@ -19,8 +19,11 @@ boot_splash/show_image=false
|
||||
boot_splash/fullsize=false
|
||||
boot_splash/use_filter=false
|
||||
config/icon="res://data/icon.png"
|
||||
config/map_addr="https://a.tile.openstreetmap.org"
|
||||
config/map_bcs=Vector3(0.5, 1.8, 0.3)
|
||||
config/map_server_addr="https://a.tile.openstreetmap.org"
|
||||
config/map_bcs=Vector3(0.5, 1.5, 0.3)
|
||||
config/map_tile_size=256
|
||||
config/map_image_hight=512
|
||||
config/map_image_width=512
|
||||
|
||||
[autoload]
|
||||
|
||||
@@ -38,7 +41,7 @@ yemsboards="*res://scripts/yemsboards.gd"
|
||||
yemsconsts="*res://scripts/yems-consts.gd"
|
||||
interfer="*res://scripts/interfer.gd"
|
||||
hotkeys="*res://scripts/hotkeys.gd"
|
||||
mercantile="*res://scripts/mercator.gd"
|
||||
mercator="*res://scripts/mercator.gd"
|
||||
|
||||
[debug]
|
||||
|
||||
@@ -71,6 +74,10 @@ version_control/autoload_on_startup=true
|
||||
|
||||
enabled=PackedStringArray()
|
||||
|
||||
[global]
|
||||
|
||||
map_server_addr=false
|
||||
|
||||
[gui]
|
||||
|
||||
common/text_edit_undo_stack_max_size=10
|
||||
|
||||
@@ -11,9 +11,9 @@ action_mode = 0
|
||||
texture_normal = ExtResource("1_r871k")
|
||||
ignore_texture_size = true
|
||||
stretch_mode = 0
|
||||
metadata/i_scale = 0
|
||||
metadata/prefix = "Масштаб:"
|
||||
metadata/scales = [10.0, 20.0, 50.0, 100.0, 250.0]
|
||||
metadata/prefix = "Детализация:"
|
||||
metadata/i_zoom = 0
|
||||
metadata/zooms = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
[node name="lbl" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
|
||||
@@ -1,62 +1,119 @@
|
||||
extends Sprite2D
|
||||
|
||||
## Состояния КА карты
|
||||
enum TILE_STATE {
|
||||
IDLE, ## Покой
|
||||
WAIT, ## Ожидание
|
||||
DONE, ## Выполнено
|
||||
ERROR ## Ошибка
|
||||
## Возможные состояния конечного автомата заданий
|
||||
enum TASK_STATE {
|
||||
DONE, ## Выполнено
|
||||
WAIT, ## Ожидание плитки
|
||||
RUN, ## Запуск выполнения
|
||||
CHECK, ## Проверка пустого места
|
||||
ERROR ## Ошибка
|
||||
}
|
||||
|
||||
var curent_map_tile: Vector3i ## Текущая запрошенная плитка
|
||||
var curent_state: TILE_STATE = TILE_STATE.IDLE ## Текущее состояние КА карты
|
||||
var image: Image ## Изображение с картой
|
||||
var map_bcs: Vector3 ## Яркость, контраст насыщенность
|
||||
|
||||
## Координаты для проверок [lng, lat]
|
||||
var 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 ],
|
||||
'Море' : [ 19.4, 54.91 ] }
|
||||
|
||||
|
||||
var map_image: Image ## Изображение с картой
|
||||
var map_tile_state: TASK_STATE ## Текущее состояние конечного автомата плитки
|
||||
var map_bcs: Vector3 ## Яркость, контраст насыщенность
|
||||
var map_server_addr: String ## Адрес сервера изображений карт в проекции Меркатора
|
||||
var map_tile_stack: Array ## Стек для хранения плиток карты
|
||||
var map_request: HTTPRequest ## Обработчик запросов http
|
||||
var map_zoom: int ## Уровень детализации карты
|
||||
var map_rects: Array[Rect2i] ## Занятые плиткой области изображения карты
|
||||
var map_tile: Rect2i ## Область одной плитки: [x-координата области, y-координата области, x-индекс плитки, y-индекс плитки]
|
||||
|
||||
|
||||
func _ready():
|
||||
# Create an HTTP request node and connect its completion signal.
|
||||
var tile = mercantile.Tile.new()
|
||||
print_debug('Плитка: %s %s' % [tile, tile.is_valid()])
|
||||
var http_request = HTTPRequest.new()
|
||||
add_child(http_request)
|
||||
http_request.request_completed.connect(self._http_request_completed)
|
||||
curent_map_tile = Vector3i(0, 0, 0)
|
||||
|
||||
image = Image.create(512, 512, true, Image.FORMAT_RGB8)
|
||||
map_tile_state = TASK_STATE.DONE
|
||||
map_request = HTTPRequest.new()
|
||||
add_child(map_request)
|
||||
map_request.request_completed.connect(self._map_request_completed)
|
||||
var map_image_width = ProjectSettings.get_setting('application/config/map_image_width', 512)
|
||||
var map_image_hight = ProjectSettings.get_setting('application/config/map_image_hight', 512)
|
||||
map_image = Image.create(map_image_width, map_image_hight, true, Image.FORMAT_RGB8)
|
||||
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')
|
||||
var map_tile_size = ProjectSettings.get_setting('application/config/map_tile_size', 256)
|
||||
map_tile = Rect2i(0, 0, map_tile_size, map_tile_size)
|
||||
signaller.connect('zoom_changed', Callable(self, '_on_zoom_changed'))
|
||||
|
||||
var error = http_request.request('https://a.tile.openstreetmap.org/0/0/0.png')
|
||||
if error == OK:
|
||||
curent_state = TILE_STATE.WAIT
|
||||
else:
|
||||
push_error('Ошибка: Не возможно сформировать запрос HTTP')
|
||||
curent_state = TILE_STATE.ERROR
|
||||
|
||||
func _on_zoom_changed(zoom: int):
|
||||
map_zoom = zoom
|
||||
var tile: = mercator.create_tile(TEST_DATA['Таганрог'][0], TEST_DATA['Таганрог'][1], zoom)
|
||||
map_tile_stack.push_front(tile)
|
||||
|
||||
|
||||
func request_tile(tile: mercator.Tile, server_addr: String) -> Error:
|
||||
var tile_addr: = '%s/%d/%d/%d.png' % [server_addr, tile.z, tile.x , tile.y]
|
||||
return map_request.request(tile_addr)
|
||||
|
||||
|
||||
func _process(delta: float):
|
||||
pass
|
||||
if (map_tile_state == TASK_STATE.DONE) and map_tile_stack.size():
|
||||
var tile: mercator.Tile = map_tile_stack[-1]
|
||||
if request_tile(tile, map_server_addr) == OK:
|
||||
map_tile_state = TASK_STATE.WAIT
|
||||
else:
|
||||
push_error('Ошибка: Невозможно сформировать запрос HTTP')
|
||||
map_tile_state = TASK_STATE.ERROR
|
||||
elif map_tile_state == TASK_STATE.CHECK:
|
||||
var root_rect: Rect2i = map_rects[0]
|
||||
var root_tile: = mercator.Tile.new(root_rect.size.x, root_rect.size.y, map_zoom)
|
||||
var neighbors_tiles = mercator.neighbors(root_tile)
|
||||
for tile in neighbors_tiles:
|
||||
tile.is_root = false
|
||||
map_tile_stack.push_front(tile)
|
||||
map_tile_state = TASK_STATE.DONE
|
||||
|
||||
|
||||
func _http_request_completed(result, response_code, headers, data):
|
||||
func _map_request_completed(result, response_code, headers, data):
|
||||
if result != HTTPRequest.RESULT_SUCCESS:
|
||||
push_error('Ошибка: запрос не обработан: %s' % result)
|
||||
curent_state = TILE_STATE.ERROR
|
||||
log.error('Запрос не обработан. result:\"%s\" response_code:\"%s\", headers:\"%s\"' % [result, response_code, headers])
|
||||
map_tile_state = TASK_STATE.ERROR
|
||||
return
|
||||
|
||||
var image0 = Image.new()
|
||||
var error = image0.load_png_from_buffer(data)
|
||||
var img_tile = Image.new()
|
||||
var error = img_tile.load_png_from_buffer(data)
|
||||
if error != OK:
|
||||
push_error('Ошибка: Полученые данные невозможно использовать для формироания изображения')
|
||||
curent_state = TILE_STATE.ERROR
|
||||
log.error('Полученые данные невозможно использовать для формироания изображения. result:\"%s\" response_code:\"%s\", headers:\"%s\"' % [result, response_code, headers])
|
||||
map_tile_state = TASK_STATE.ERROR
|
||||
return
|
||||
|
||||
curent_state = TILE_STATE.DONE
|
||||
var tile_size = image0.get_size()
|
||||
|
||||
image.blit_rect(image0, Rect2i(0, 0, tile_size.x, tile_size.y), Vector2i( 0, 0))
|
||||
image.blit_rect(image0, Rect2i(0, 0, tile_size.x, tile_size.y), Vector2i(tile_size.x, 0))
|
||||
image.blit_rect(image0, Rect2i(0, 0, tile_size.x, tile_size.y), Vector2i( 0, tile_size.y))
|
||||
image.blit_rect(image0, Rect2i(0, 0, tile_size.x, tile_size.y), Vector2i(tile_size.y, tile_size.y))
|
||||
image.adjust_bcs(map_bcs.x, map_bcs.y, map_bcs.z)
|
||||
texture = ImageTexture.create_from_image(image)
|
||||
print_debug(map_tile_stack)
|
||||
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))
|
||||
map_rects.clear() # очистить список занятых областей изображения карты
|
||||
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 = map_tile.size.x / (bounds.east - bounds.west) * (lng_c - tile.lng) + map_tile.size.x / 2.0 # смещение в пискселях центра плитки от заданной точки по горизонтали
|
||||
var sy = map_tile.size.y / (bounds.north - bounds.south) * (lat_c - tile.lat) - map_tile.size.y / 2.0 # смещение в пискселях центра плитки от заданной точки по вертикали
|
||||
var dst_pos = Vector2i(sx, -sy)
|
||||
map_image.blit_rect(img_tile, map_tile, dst_pos)
|
||||
map_rects.append(Rect2i(dst_pos.x, dst_pos.y, tile.x, tile.y)) # сохранить корневую плитку
|
||||
else:
|
||||
# Отображение соседних плиток
|
||||
var root_rect: Rect2i = map_rects[0] # Получить корневую плитку
|
||||
var dx: int = tile.x - root_rect.size.x # Вычислить положение дочерней плитки относительно корневой
|
||||
var dy: int = tile.y - root_rect.size.y
|
||||
var dst_pos: Vector2i = root_rect.position + Vector2i(dx, dy) * map_tile.size
|
||||
map_image.blit_rect(img_tile, map_tile, dst_pos)
|
||||
map_rects.append(Rect2i(dst_pos.x, dst_pos.y, tile.x, tile.y))
|
||||
texture = ImageTexture.create_from_image(map_image)
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_pmqvj"]
|
||||
resource_local_to_scene = true
|
||||
shader = ExtResource("1_tsdui")
|
||||
shader_parameter/center = Vector2(0.5, 0.5)
|
||||
shader_parameter/radius = 0.4
|
||||
shader_parameter/rotation = 0.0
|
||||
|
||||
[node name="tilemap" type="Sprite2D"]
|
||||
material = SubResource("ShaderMaterial_pmqvj")
|
||||
|
||||
@@ -64,6 +64,7 @@ func _ready():
|
||||
threats.connect('threat_lost', Callable(self, 'on_threat_lost'))
|
||||
threats.connect('threats_resized', Callable(self, 'on_threats_resized'))
|
||||
threats.connect('threat_update', Callable(self, 'on_threat_update'))
|
||||
signaller.emit_signal('zoom_changed', 0)
|
||||
|
||||
|
||||
## Производит отображение цели на диаграмму
|
||||
@@ -175,12 +176,11 @@ func _input(event) -> void:
|
||||
shift_pressed = event.pressed
|
||||
|
||||
|
||||
## Изменяет масштаб
|
||||
## Изменяет детализацию
|
||||
func _on_btn_scale_pressed() -> void:
|
||||
var i_scale = $btn_scale.get_meta('i_scale')
|
||||
var zoom = $btn_scale.get_meta('zoom')
|
||||
var prefix = $btn_scale.get_meta('prefix')
|
||||
var scales = $btn_scale.get_meta('scales')
|
||||
i_scale += 1
|
||||
i_scale %= scales.size()
|
||||
$btn_scale.set_meta('i_scale', i_scale)
|
||||
$btn_scale/lbl.text = '%s %.0f км' % [prefix, scales[i_scale]]
|
||||
zoom = (zoom + 1) % 20
|
||||
$btn_scale.set_meta('zoom', zoom)
|
||||
$btn_scale/lbl.text = '%s %d' % [prefix, zoom]
|
||||
signaller.emit_signal('zoom_changed', zoom)
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
[ext_resource type="PackedScene" uid="uid://bbq6nklh36yij" path="res://scenes/tilemap.tscn" id="10_wpi4s"]
|
||||
[ext_resource type="Shader" path="res://shaders/tilemap.gdshader" id="11_7ohqv"]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_whr8j"]
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_6tiyy"]
|
||||
resource_local_to_scene = true
|
||||
shader = ExtResource("11_7ohqv")
|
||||
shader_parameter/radius = 0.4
|
||||
shader_parameter/radius = 0.39
|
||||
|
||||
[node name="Работа" type="Panel"]
|
||||
script = ExtResource("1_vmjjl")
|
||||
@@ -44,6 +44,9 @@ offset_right = 1594.0
|
||||
offset_bottom = 1170.0
|
||||
metadata/_edit_lock_ = true
|
||||
|
||||
[node name="tilemap" parent="." instance=ExtResource("10_wpi4s")]
|
||||
material = SubResource("ShaderMaterial_6tiyy")
|
||||
|
||||
[node name="canvas" parent="." instance=ExtResource("7_pvt8f")]
|
||||
metadata/_edit_lock_ = true
|
||||
|
||||
@@ -131,9 +134,7 @@ offset_left = 952.0
|
||||
offset_top = 1038.0
|
||||
offset_right = 1104.0
|
||||
offset_bottom = 1056.0
|
||||
|
||||
[node name="tilemap" parent="." instance=ExtResource("10_wpi4s")]
|
||||
material = SubResource("ShaderMaterial_whr8j")
|
||||
metadata/zoom = 0
|
||||
|
||||
[connection signal="drag_begin" from="." to="." method="_on_drag_begin"]
|
||||
[connection signal="drag_continue" from="." to="." method="_on_drag_continue"]
|
||||
|
||||
@@ -2,12 +2,14 @@ extends Node
|
||||
|
||||
## Веб-утилиты для работы с меркаторскими XYZ-плитками.
|
||||
|
||||
const R2D: = 180.0 / PI
|
||||
const RE: = 6378137.0
|
||||
const CE: = 2.0 * PI * RE
|
||||
const EPSILON: = 1e-14
|
||||
const LL_EPSILON: = 1e-11
|
||||
const MAX_ZOOM: = 28
|
||||
const R2D: = 180.0 / PI
|
||||
const RE: = 6378137.0 ## Радиус Земли в метрах
|
||||
const CE: = 2.0 * PI * RE ## Длина окружности Земли в метрах
|
||||
const EPSILON: = 1e-14
|
||||
const LL_EPSILON: = 1e-11
|
||||
const MAX_ZOOM: = 20
|
||||
const MAX_NORTH = 85.051129
|
||||
const MAX_SOUTH = -85.051129
|
||||
|
||||
|
||||
## XYZ-плитка веб-меркатора [param x], [param y], [param z] индексы
|
||||
@@ -16,15 +18,19 @@ class Tile:
|
||||
var x: int
|
||||
var y: int
|
||||
var z: int
|
||||
var lng: float ## Координаты, которые плитка должна покрывать, долгота, градусы
|
||||
var lat: float ## Широта, градусы
|
||||
var is_root: bool ## Признак, что плитка корневая (покрывает координаты)
|
||||
|
||||
func as_array(): return [self.x, self.y, self.z]
|
||||
|
||||
func _to_string() -> String: return '[%d, %d, %d]' % [self.x, self.y, self.z]
|
||||
|
||||
func _init(x0: int = 0, y0: int = 0, z0: int = 0):
|
||||
func _init(x0: int = 0, y0: int = 0, z0: int = 0, is_root0: bool = true):
|
||||
self.x = x0
|
||||
self.y = y0
|
||||
self.z = z0
|
||||
self.is_root = is_root0
|
||||
|
||||
func is_valid() -> bool:
|
||||
if (self.z >= 0) and (self.z < MAX_ZOOM):
|
||||
@@ -38,8 +44,12 @@ class Tile:
|
||||
class LngLat:
|
||||
var lng: float = 0.0 ## Долгота в десятичных градусах восточной долготы.
|
||||
var lat: float = 0.0 ## Широта в десятичных градусах северной широты.
|
||||
|
||||
## Возвращает в виде массива
|
||||
func as_array() -> Array: return [self.lng, self.lat]
|
||||
|
||||
func _to_string() -> String: return '[%f, %f, %f]' % [self.x, self.y, self.z]
|
||||
|
||||
func _init(lng0, lat0):
|
||||
self.lng = lng0
|
||||
self.lat = lat0
|
||||
@@ -51,8 +61,12 @@ class LngLatBbox:
|
||||
var south: float ## Юг
|
||||
var east: float ## Восток
|
||||
var north: float ## Север
|
||||
|
||||
## Возвращает в виде массива
|
||||
func as_array() -> Array: return [self.west, self.south, self.east, self.north]
|
||||
|
||||
func _to_string() -> String: return '[%f, %f, %f, %f]' % [self.west, self.south, self.east, self.north]
|
||||
|
||||
func _init(w: float = 0.0, s: float = 0.0, e: float = 0.0, n: float = 0.0):
|
||||
self.west = w
|
||||
self.south = s
|
||||
@@ -83,6 +97,21 @@ func radians(v: float) -> float: return (v * PI) / 180.0
|
||||
func rshift(val: int, n: int) -> int: return (val % 0x100000000) >> n
|
||||
|
||||
|
||||
## Расстояние по горизонтали в метрах, представленное одним пикселем
|
||||
## [paramn lat] - Широта, градусы.[br]
|
||||
## [paramn zoom] - Уровень детализации.[br]
|
||||
## [paramn size] - Размер плитки в пикселях.[br]
|
||||
func dist_per_pixel(lat: float, zoom: int, size: int = 256) -> float:
|
||||
return (CE / float(size)) * cos(radians(lat)) / float(2 ** zoom)
|
||||
|
||||
|
||||
## Расстояние по горизонтали в метрах, представленное одной плиткой
|
||||
## [paramn lat] - Широта, градусы.[br]
|
||||
## [paramn zoom] - Уровень детализации.[br]
|
||||
func dist_per_tile(lat: float, zoom: int) -> float:
|
||||
return CE * cos(radians(lat)) / float(2 ** zoom)
|
||||
|
||||
|
||||
## Возвращает плитки и занимаемый ими размер области в пикселях:
|
||||
## ширина, высота, левая граница, верхняя граница, плитки.[br]
|
||||
## [param west] - Западная граница области.[br]
|
||||
@@ -130,6 +159,7 @@ func get_degrees_bounds(m: float, lng: float, lat: float) -> Array[float]:
|
||||
return [x_y[0] - m, x_y[1] - m, x_y[0] + m, x_y[1] + m]
|
||||
|
||||
|
||||
## Возвращает границы плиток в градусах
|
||||
func get_tiles_bounds(tiles: Array[Tile]) -> Array:
|
||||
var mm = []
|
||||
for t in tiles: mm.append(bounds(t).west)
|
||||
@@ -182,17 +212,17 @@ func ul2(tile: Tile) -> Array[float]:
|
||||
## Возвращает граничную область плитки.[br]
|
||||
## [param tile] - Плитка.[br]
|
||||
func bounds(tile: Tile) -> LngLatBbox:
|
||||
var Z2: = pow(2, tile.z)
|
||||
var ul_lon_deg = tile.x / Z2 * 360.0 - 180.0
|
||||
var ul_lat_rad = atan(sinh(PI * (1 - 2 * tile.y / Z2)))
|
||||
var z2: = pow(2, tile.z)
|
||||
var ul_lon_deg = tile.x / z2 * 360.0 - 180.0
|
||||
var lr_lon_deg = (tile.x + 1) / z2 * 360.0 - 180.0
|
||||
var ul_lat_rad = atan(sinh(PI * (1 - 2 * tile.y / z2)))
|
||||
var ul_lat_deg = degrees(ul_lat_rad)
|
||||
var lr_lon_deg = (tile.x + 1) / Z2 * 360.0 - 180.0
|
||||
var lr_lat_rad = atan(sinh(PI * (1 - 2 * (tile.y + 1) / Z2)))
|
||||
var lr_lat_rad = atan(sinh(PI * (1 - 2 * (tile.y + 1) / z2)))
|
||||
var lr_lat_deg = degrees(lr_lat_rad)
|
||||
return LngLatBbox.new(ul_lon_deg, lr_lat_deg, lr_lon_deg, ul_lat_deg)
|
||||
|
||||
|
||||
func truncate_lnglat(lng: float, lat: float) -> Array:
|
||||
func truncate_lnglat(lng: float, lat: float) -> Array[float]:
|
||||
if lng > 180.0: lng = 180.0
|
||||
elif lng < -180.0: lng = -180.0
|
||||
if lat > 90.0: lat = 90.0
|
||||
@@ -200,7 +230,7 @@ func truncate_lnglat(lng: float, lat: float) -> Array:
|
||||
return [lng, lat]
|
||||
|
||||
|
||||
## Преобразование долготы и широты в веб-меркатор x, y.[br]
|
||||
## Преобразование долготы и широты в веб-меркатор x, y в метрах.[br]
|
||||
## [param lng] - Долгота в десятичных градусах.[br]
|
||||
## [param lat] - Широта в десятичных градусах.[br]
|
||||
## [param truncate] - Нужно ли усекать входные данные до пределов веб-меркатора.[br]
|
||||
@@ -234,14 +264,17 @@ func lnglat(x: float, y: float, truncate: bool = false) -> LngLat:
|
||||
## >>> neighbors(Tile(486, 332, 10))
|
||||
## [Tile(x=485, y=331, z=10), Tile(x=485, y=332, z=10), Tile(x=485, y=333, z=10), Tile(x=486, y=331, z=10), Tile(x=486, y=333, z=10), Tile(x=487, y=331, z=10), Tile(x=487, y=332, z=10), Tile(x=487, y=333, z=10)]
|
||||
## [/codeblock]
|
||||
func neighbors(tile: Tile) -> Array[Tile]:
|
||||
var tiles: = Array()
|
||||
var lo_hi = [0, 2 ** tile.z - 1]
|
||||
func neighbors(tile: Tile) -> Array:
|
||||
var tiles: = []
|
||||
var hi = 2 ** tile.z - 1
|
||||
for i in [-1, 0, 1]:
|
||||
for j in [-1, 0, 1]:
|
||||
if i == 0 and j == 0: continue
|
||||
elif tile.x + i < 0 or tile.y + j < 0: continue
|
||||
elif tile.x + i > lo_hi[1] or tile.y + j > lo_hi[i]: continue
|
||||
if i == 0 and j == 0:
|
||||
continue
|
||||
elif (tile.x + i) < 0 or (tile.y + j) < 0:
|
||||
continue
|
||||
elif (tile.x + i) > hi or (tile.y + j) > hi:
|
||||
continue
|
||||
var t = Tile.new(tile.x + i, tile.y + j, tile.z)
|
||||
if t.is_valid():
|
||||
tiles.append(t)
|
||||
@@ -260,9 +293,9 @@ func xy_bounds(tile: Tile, zoom: int) -> Bbox:
|
||||
return Bbox.new(left, bottom, right, top)
|
||||
|
||||
|
||||
func _xy(lng, lat, truncate=false) -> Array:
|
||||
func _xy(lng, lat, truncate=false) -> Array[float]:
|
||||
var ll: = [lng, lat] if not truncate else truncate_lnglat(lng, lat)
|
||||
var x = ll[0] / 360.0 + 0.5
|
||||
var x: float = ll[0] / 360.0 + 0.5
|
||||
var sinlat: = sin(radians(ll[1]))
|
||||
var y: = 0.5 - 0.25 * log((1.0 + sinlat) / (1.0 - sinlat)) / PI
|
||||
return [x, y]
|
||||
@@ -274,25 +307,27 @@ func _xy(lng, lat, truncate=false) -> Array:
|
||||
## [param truncate] - Нужно ли усекать вводимые данные до границ веб-меркатора.[br]
|
||||
func create_tile(lng: float, lat: float, zoom: int, truncate: bool=false) -> Tile:
|
||||
var xy0: = _xy(lng, lat, truncate)
|
||||
var Z2 = pow(2, zoom)
|
||||
var z2 = pow(2, zoom)
|
||||
|
||||
# Чтобы устранить потерю точности при переходе от одной плитки к другой
|
||||
# и lng/lat, точки в пределах EPSILON от правой стороны тайла
|
||||
# и lng/lat, точки в пределах EPSILON от правой стороны плитки
|
||||
# считаются в следующей за ней плитке.
|
||||
var tile: = Tile.new()
|
||||
if xy0[0] <= 0: tile.x = 0
|
||||
elif xy0[0] >= 1: tile.x = int(Z2 - 1)
|
||||
else: tile.x = int(floor((xy0[0] + EPSILON) * Z2))
|
||||
elif xy0[0] >= 1: tile.x = int(z2 - 1)
|
||||
else: tile.x = int(floor((xy0[0] + EPSILON) * z2))
|
||||
|
||||
if xy0[1] <= 0: tile.y = 0
|
||||
elif xy0[1] >= 1: tile.y = int(Z2 - 1)
|
||||
else: tile.y = int(floor((xy0[1] + EPSILON) * Z2))
|
||||
elif xy0[1] >= 1: tile.y = int(z2 - 1)
|
||||
else: tile.y = int(floor((xy0[1] + EPSILON) * z2))
|
||||
tile.z = zoom
|
||||
tile.lng = lng
|
||||
tile.lat = lat
|
||||
return tile
|
||||
|
||||
|
||||
## Получение четверного ключа плитки.[br]
|
||||
## [param tile] Плитка
|
||||
## [param tile] - Плитка
|
||||
func quadkey(tile: Tile, zoom: int) -> String:
|
||||
var rs: = ''
|
||||
for z in range(zoom, 0, -1):
|
||||
@@ -337,9 +372,7 @@ func quadkey_to_tile(qk: Array) -> Tile:
|
||||
## [param truncate] [bool] - Нужно ли усекать вводимые данные до границ веб-меркатора.[br]
|
||||
## [i]В параметрах south и east используется небольшой эпсилон, чтобы
|
||||
## функция выдавала ровно одну плитку при задании границ этой же плитки.[/i]
|
||||
func create_tiles(west: float, south: float, east: float, north: float, zooms, truncate: bool=false) -> Array[Tile]:
|
||||
var west_south = [west, south] if truncate else truncate_lnglat(west, south)
|
||||
var east_north = [east, north] if truncate else truncate_lnglat(east, north)
|
||||
func create_tiles(west: float, south: float, east: float, north: float, zooms) -> Array[Tile]:
|
||||
var bboxes = [[west, south, east, north]] if west <= east else [[-180.0, south, east, north], [west, south, 180.0, north]]
|
||||
var tiles = []
|
||||
if not is_instance_of(zooms, TYPE_ARRAY):
|
||||
@@ -351,7 +384,7 @@ func create_tiles(west: float, south: float, east: float, north: float, zooms, t
|
||||
var n = box[3]
|
||||
# Зажим граничных значений.
|
||||
w = max(-180.0, w)
|
||||
s = max(-85.051129, s)
|
||||
s = max(MAX_SOUTH, s)
|
||||
e = min(180.0, e)
|
||||
n = min(85.051129, n)
|
||||
for z in zooms:
|
||||
@@ -412,8 +445,7 @@ func parent(tile: Tile, zoom=null) -> Tile:
|
||||
## >>> children(Tile(0, 0, 0), zoom=2)
|
||||
## [Tile(x=0, y=0, z=2), Tile(x=0, y=1, z=2), Tile(x=0, y=2, z=2), Tile(x=0, y=3, z=2), ...]
|
||||
## [/codeblock]
|
||||
func children(tile, zoom) -> Array:
|
||||
assert((tile.z <= zoom) and zoom == int(zoom), 'Масштаб (zoom) должен быть целым числом и превышать масштаб входной плитки (tile)')
|
||||
func children(tile: Tile, zoom: int) -> Array:
|
||||
var target_zoom = zoom if zoom != null else tile.z + 1
|
||||
var tiles: Array[Tile] = [tile]
|
||||
while tiles[0].z >= target_zoom:
|
||||
@@ -484,33 +516,26 @@ func simplify(tiles: Array) -> Array:
|
||||
## Tile(x=0, y=0, z=0).
|
||||
## [param bbox] последовательность [float] значений границ запада, юга, востока,
|
||||
## севера в десятичных градусах.
|
||||
func bounding_tile(bbox, truncate: bool = false) -> Tile:
|
||||
if len(bbox) == 2:
|
||||
bbox += bbox
|
||||
|
||||
var w = bbox[0]
|
||||
var s = bbox[1]
|
||||
var e = bbox[2]
|
||||
var n = bbox[3]
|
||||
func bounding_tile(bbox: Bbox, truncate: bool = false) -> Tile:
|
||||
|
||||
if truncate:
|
||||
var w_s = truncate_lnglat(w, s)
|
||||
w = w_s[0]
|
||||
s = w_s[1]
|
||||
var e_n = truncate_lnglat(e, n)
|
||||
n = e_n[0]
|
||||
e = e_n[1]
|
||||
var w_s = truncate_lnglat(bbox.left, bbox.bottom)
|
||||
bbox.left = w_s[0]
|
||||
bbox.bottom = w_s[1]
|
||||
var e_n = truncate_lnglat(bbox.right, bbox.north)
|
||||
bbox.right = e_n[0]
|
||||
bbox.top = e_n[1]
|
||||
|
||||
e -= LL_EPSILON
|
||||
s += LL_EPSILON
|
||||
bbox.right -= LL_EPSILON
|
||||
bbox.bottom += LL_EPSILON
|
||||
|
||||
var tmin = create_tile(w, n, 32)
|
||||
var tmax = create_tile(e, s, 32)
|
||||
var tmin = create_tile(bbox.left, bbox.top, 32)
|
||||
var tmax = create_tile(bbox.right, bbox.bottom, 32)
|
||||
assert(tmin.is_valid())
|
||||
assert(tmax.is_valid())
|
||||
|
||||
var cell = [tmin.x, tmin.y, tmax.x, tmax.y]
|
||||
var z = _getBboxZoom(cell)
|
||||
var z = _get_bbox_zoom(cell)
|
||||
|
||||
if z == 0:
|
||||
return Tile.new()
|
||||
@@ -521,7 +546,7 @@ func bounding_tile(bbox, truncate: bool = false) -> Tile:
|
||||
return Tile.new(x, y, z)
|
||||
|
||||
|
||||
func _getBboxZoom(bbox: Array):
|
||||
func _get_bbox_zoom(bbox: Array):
|
||||
for z in MAX_ZOOM:
|
||||
var mask: int = 1 << (32 - (z + 1))
|
||||
if (bbox[0] & mask) != (bbox[2] & mask) or (bbox[1] & mask) != (bbox[3] & mask):
|
||||
|
||||
@@ -20,3 +20,8 @@ signal threat_unselected(threats: Dictionary, th)
|
||||
## Вызывается, когда пользователь переключает режим окна программы полный экран - оконный
|
||||
## [param id] - Идентификатор окна. Присваевается вручную
|
||||
signal full_screen(id: int)
|
||||
|
||||
|
||||
## Вызывается при изменении уровня детализации карты
|
||||
## [param zoom] - Вновь установленный уровень детализации
|
||||
signal zoom_changed(zoom: int)
|
||||
|
||||
@@ -54,7 +54,6 @@ func _ready() -> void:
|
||||
timer_check_lost.start(repsettings.ThreatParams.time_lost / 1000.0)
|
||||
|
||||
|
||||
|
||||
## Периодически удаляет устаревшие цели
|
||||
func on_timer_check_lost(time_lost: int, threats: Dictionary):
|
||||
var tick = Time.get_ticks_msec()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
extends Node
|
||||
|
||||
##
|
||||
##
|
||||
const INPUT_ROWS1 = [
|
||||
[12,['283333 МР-231S, Строб ЭМС', 'X52', '0.00', '0.00']],
|
||||
[13,['29НРЛС МР-231-3, УИЗП', 'X54', '0.00', '0.00']],
|
||||
|
||||
@@ -4,11 +4,11 @@ shader_type canvas_item;
|
||||
|
||||
/* Рисует текстуру по маске в форме окружности */
|
||||
|
||||
uniform float radius: hint_range(0.0, 1.0) = 0.4; /* Радиус */
|
||||
uniform float radius: hint_range(0.0, 1.0) = 0.8; /* Радиус */
|
||||
const vec2 center = vec2(0.5, 0.5);
|
||||
|
||||
void fragment()
|
||||
{
|
||||
COLOR = texture(TEXTURE, UV) * smooth_px(length(UV - center), radius, DS);
|
||||
COLOR = texture(TEXTURE, UV);// * smooth_px(length(UV - center), radius, DS);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user