В процессе. Карта отображается. Отображение детализации по факту завершения загрузки карты

This commit is contained in:
sasha80
2023-11-16 14:25:35 +03:00
parent 892cfabfda
commit 7f3e0f262f
7 changed files with 116 additions and 48 deletions

View File

@@ -24,6 +24,8 @@ 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
config/map_minimum_zoom=5
config/map_maximum_zoom=19
[autoload]

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://0uqi1ghf7sma"]
[ext_resource type="Texture2D" uid="uid://c1maea6yhd3k7" path="res://data/кнопка-масштаб.png" id="1_r871k"]
[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_ymtay"]
load_path = "res://.godot/imported/кнопка-масштаб.png-506c26462e59a71e6707c554c495504e.ctex"
[node name="btn_scale" type="TextureButton"]
self_modulate = Color(1, 1, 1, 0.509804)
@@ -8,7 +9,7 @@ offset_right = 152.0
offset_bottom = 18.0
tooltip_text = "Измененяет масштаб"
action_mode = 0
texture_normal = ExtResource("1_r871k")
texture_normal = SubResource("CompressedTexture2D_ymtay")
ignore_texture_size = true
stretch_mode = 0
metadata/prefix = "Детализация:"
@@ -20,5 +21,4 @@ layout_mode = 0
offset_top = -18.0
offset_right = 152.0
offset_bottom = 1.0
text = "Масштаб: 200 км"
vertical_alignment = 1

View File

@@ -12,17 +12,17 @@ enum TASK_STATE {
## Координаты для проверок [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 ] }
'Калиниград': [ 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 ## Изображение с картой
@@ -34,6 +34,8 @@ var map_request: HTTPRequest ## Обработчик запросов http
var map_zoom: int ## Уровень детализации карты
var map_rects: Array[Rect2i] ## Занятые плиткой области изображения карты
var map_tile: Rect2i ## Область одной плитки: [x-координата области, y-координата области, x-индекс плитки, y-индекс плитки]
var prev_tiles_dic = {} ##
var map_done: bool ##
func _ready():
@@ -48,13 +50,27 @@ func _ready():
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)
map_done = true
signaller.connect('zoom_changed', Callable(self, '_on_zoom_changed'))
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(TEST_DATA['Таганрог'][0], TEST_DATA['Таганрог'][1], zoom)
map_tile_stack.push_front(tile)
var ll = TEST_DATA['Мехико']
var tile: = mercator.create_tile(ll[0], ll[1], zoom)
map_tile_stack.clear()
map_tile_stack.append(tile)
prev_tiles_dic.clear()
func request_tile(tile: mercator.Tile, server_addr: String) -> Error:
@@ -62,6 +78,12 @@ func request_tile(tile: mercator.Tile, server_addr: String) -> Error:
return map_request.request(tile_addr)
func img_tile_to_map_image(image: Image, dst_pos: Vector2i, tile: mercator.Tile):
image.adjust_bcs(map_bcs.x, map_bcs.y, map_bcs.z)
map_image.blit_rect(image, map_tile, dst_pos)
map_rects.append(Rect2i(dst_pos.x, dst_pos.y, tile.x, tile.y)) # сохранить корневую плитку
func _process(delta: float):
if (map_tile_state == TASK_STATE.DONE) and map_tile_stack.size():
var tile: mercator.Tile = map_tile_stack[-1]
@@ -74,9 +96,16 @@ func _process(delta: float):
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)
var neighbors_tiles_dic = {}
for tile in neighbors_tiles:
tile.is_root = false
map_tile_stack.push_front(tile)
neighbors_tiles_dic[str(tile)] = 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[str(tile)] = false
else:
signaller.emit_signal('zoom_complete', map_zoom)
map_tile_state = TASK_STATE.DONE
@@ -93,7 +122,6 @@ func _map_request_completed(result, response_code, headers, data):
map_tile_state = TASK_STATE.ERROR
return
print_debug(map_tile_stack)
var tile = map_tile_stack.pop_back()
map_tile_state = TASK_STATE.CHECK
if tile.is_root:
@@ -101,19 +129,18 @@ func _map_request_completed(result, response_code, headers, data):
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 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 sx = map_tile.size.x / (bounds.east - bounds.west) * (lng_c - tile.lng) + map_tile.size.x / 2.0 # Cмещение в пискселях центра плитки от заданной точки по горизонтали.
var sy = map_tile.size.y / (bounds.north - bounds.south) * (lat_c - tile.lat) - map_tile.size.y / 2.0 # Cмещение в пискселях центра плитки от заданной точки по вертикали.
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)) # сохранить корневую плитку
img_tile_to_map_image(img_tile, dst_pos, tile)
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))
img_tile_to_map_image(img_tile, dst_pos, tile)
mark_image_center(map_image)
texture = ImageTexture.create_from_image(map_image)

View File

@@ -24,6 +24,8 @@ extends Panel
var drag_button: MouseButton ## Кнопка мыши нажатая при перетаскивании
var drag_fsm: DragFSM = DragFSM.IDLE ## Текущее состояние перетаскивания
var drag_pos_begin: Vector2 ## Точка начала перетаскивания
var max_zoom: int ## Максимальный уровень детализации
var min_zoom: int ## Минимальный уровень детализации
var shift_pressed: bool ## Кнопка SHIFT нажата
var strob_band_begin: float ## Ширина строба в момент начала перетаскивания
var strob_dir_begin: float ## Направление антенны в момент начала перетаскивания
@@ -52,6 +54,9 @@ func on_threats_resized(threats: Dictionary): $count_all_pad/count_all.text = '%
## Производит инициализацию
func _ready():
min_zoom = ProjectSettings.get_setting('application/config/map_minimum_zoom', 5)
max_zoom = ProjectSettings.get_setting('application/config/map_maximum_zoom', 19)
$btn_zoom.set_meta('zoom', min_zoom - 1)
$tilemap.position = $canvas.get_strob_center()
$btn_strob.button_connect('pressed', Callable(self, 'on_button_strobe_pressed'))
$btn_view.button_connect('toggled', Callable(self, 'on_button_view_toggled'))
@@ -64,7 +69,8 @@ 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)
call_deferred('_on_btn_scale_pressed')
signaller.connect('zoom_complete', Callable(self, '_on_zoom_complete'))
## Производит отображение цели на диаграмму
@@ -176,11 +182,15 @@ func _input(event) -> void:
shift_pressed = event.pressed
## Изменяет детализацию
## Вызывается по нажатию кнопки "Детализация"
func _on_btn_scale_pressed() -> void:
var zoom = $btn_scale.get_meta('zoom')
var prefix = $btn_scale.get_meta('prefix')
zoom = (zoom + 1) % 20
$btn_scale.set_meta('zoom', zoom)
$btn_scale/lbl.text = '%s %d' % [prefix, zoom]
var zoom = $btn_zoom.get_meta('zoom')
zoom = zoom + 1 if zoom < max_zoom else min_zoom
signaller.emit_signal('zoom_changed', zoom)
## Вызывается по завершению изменения детализации карты
func _on_zoom_complete(zoom: int) -> void:
var prefix = $btn_zoom.get_meta('prefix')
$btn_zoom/lbl.text = '%s %d' % [prefix, zoom]
$btn_zoom.set_meta('zoom', zoom)

View File

@@ -12,7 +12,7 @@
[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_6tiyy"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_idugi"]
resource_local_to_scene = true
shader = ExtResource("11_7ohqv")
shader_parameter/radius = 0.39
@@ -45,7 +45,7 @@ offset_bottom = 1170.0
metadata/_edit_lock_ = true
[node name="tilemap" parent="." instance=ExtResource("10_wpi4s")]
material = SubResource("ShaderMaterial_6tiyy")
material = SubResource("ShaderMaterial_idugi")
[node name="canvas" parent="." instance=ExtResource("7_pvt8f")]
metadata/_edit_lock_ = true
@@ -128,14 +128,14 @@ size_flags_horizontal = 3
size_flags_vertical = 3
text = "Вид"
[node name="btn_scale" parent="." instance=ExtResource("8_xddop")]
[node name="btn_zoom" parent="." instance=ExtResource("8_xddop")]
layout_mode = 0
offset_left = 952.0
offset_top = 1038.0
offset_right = 1104.0
offset_bottom = 1056.0
metadata/zoom = 0
metadata/zoom = 4
[connection signal="drag_begin" from="." to="." method="_on_drag_begin"]
[connection signal="drag_continue" from="." to="." method="_on_drag_continue"]
[connection signal="pressed" from="btn_scale" to="." method="_on_btn_scale_pressed"]
[connection signal="pressed" from="btn_zoom" to="." method="_on_btn_scale_pressed"]

View File

@@ -97,6 +97,27 @@ func radians(v: float) -> float: return (v * PI) / 180.0
func rshift(val: int, n: int) -> int: return (val % 0x100000000) >> n
func asinh(val: float): return log(val + sqrt(val * val + 1.0))
## Lon./lat. to tile numbers
func deg2num(lat_deg: float, lon_deg: float, zoom: int):
var lat_rad: = radians(lat_deg)
var n: = float(1 << zoom)
var xtile: = int((lon_deg + 180.0) / 360.0 * n)
var ytile: = int((1.0 - asinh(tan(lat_rad)) / PI) / 2.0 * n)
return [xtile, ytile]
## Tile numbers to lon./lat.
func num2deg(xtile: int, ytile: int, zoom: int):
var n: = float(1 << zoom)
var lon_deg: = float(xtile) / n * 360.0 - 180.0
var lat_rad: = atan(sinh(PI * (1.0 - 2.0 * float(ytile) / n)))
var lat_deg = degrees(lat_rad)
return [lat_deg, lon_deg]
## Расстояние по горизонтали в метрах, представленное одним пикселем
## [paramn lat] - Широта, градусы.[br]
## [paramn zoom] - Уровень детализации.[br]
@@ -213,16 +234,16 @@ func ul2(tile: Tile) -> Array[float]:
## [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 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_lon_deg = float(tile.x) / z2 * 360.0 - 180.0
var lr_lon_deg = (float(tile.x) + 1.0) / z2 * 360.0 - 180.0
var ul_lat_rad = atan(sinh(PI * (1.0 - 2.0 * float(tile.y) / z2)))
var ul_lat_deg = degrees(ul_lat_rad)
var lr_lat_rad = atan(sinh(PI * (1 - 2 * (tile.y + 1) / z2)))
var lr_lat_rad = atan(sinh(PI * (1.0 - 2.0 * (float(tile.y) + 1.0) / 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[float]:
func truncate_lnglat(lng: float, lat: float) -> Array:
if lng > 180.0: lng = 180.0
elif lng < -180.0: lng = -180.0
if lat > 90.0: lat = 90.0
@@ -236,7 +257,7 @@ func truncate_lnglat(lng: float, lat: float) -> Array[float]:
## [param truncate] - Нужно ли усекать входные данные до пределов веб-меркатора.[br]
## ([param lat] >= 90) [b]inf[/b] на северном и [b]-inf[/b] на южном полюсе ([param lat] <= -90).
func xy(lng: float, lat: float, truncate: bool = false) -> Array[float]:
var ll = truncate_lnglat(lng, lat) if truncate else [0.0, 0.0]
var ll = truncate_lnglat(lng, lat) if truncate else [lng, lat]
var x: float = RE * radians(lng)
var y: float = 0.0
if ll[1] <= -90.0: y = float('-inf')
@@ -251,7 +272,7 @@ func xy(lng: float, lat: float, truncate: bool = false) -> Array[float]:
func lnglat(x: float, y: float, truncate: bool = false) -> LngLat:
var lng: = x * R2D / RE
var lat: = ((PI * 0.5) - 2.0 * atan(exp(-y / RE))) * R2D
var ll: = truncate_lnglat(lng, lat) if truncate else [0.0, 0.0]
var ll: = truncate_lnglat(lng, lat) if truncate else [lng, lat]
return LngLat.new(ll[0], ll[1])
@@ -293,8 +314,8 @@ func xy_bounds(tile: Tile, zoom: int) -> Bbox:
return Bbox.new(left, bottom, right, top)
func _xy(lng, lat, truncate=false) -> Array[float]:
var ll: = [lng, lat] if not truncate else truncate_lnglat(lng, lat)
func _xy(lng: float, lat: float, truncate=false) -> Array:
var ll: = truncate_lnglat(lng, lat) if truncate else [lng, lat]
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

View File

@@ -22,6 +22,14 @@ signal threat_unselected(threats: Dictionary, th)
signal full_screen(id: int)
## Вызывается при изменении уровня детализации карты
## Вызывается при запросе изменения уровня детализации карты
## [param zoom] - Вновь установленный уровень детализации
signal zoom_changed(zoom: int)
## Вызывается при завершении изменения уровня детализации карты
## [param zoom] - Вновь установленный уровень детализации
signal zoom_complete(zoom: int)
## Вызывается при изменении координат карты
## [param lan], [param lat] - Вновь установленные координаты
signal map_coords_changed(zoom: int)