diff --git a/project.godot b/project.godot index 92217c13..e774541b 100644 --- a/project.godot +++ b/project.godot @@ -23,7 +23,7 @@ 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_minimum_zoom=3 config/map_maximum_zoom=19 config/map_server_addr="https://b.tile.openstreetmap.org" diff --git a/scenes/tilemap.gd b/scenes/tilemap.gd index 6138a3e1..53a29f55 100644 --- a/scenes/tilemap.gd +++ b/scenes/tilemap.gd @@ -22,6 +22,10 @@ var TEST_DATA: = { 'Мехико': [ -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 ] } @@ -35,7 +39,6 @@ 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(): @@ -50,7 +53,6 @@ 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')) @@ -66,7 +68,7 @@ func _on_zoom_changed(zoom: int): if map_tile_stack.size() != 0: return map_zoom = zoom - var ll = TEST_DATA['Мехико'] + var ll = TEST_DATA['Фиджи'] var tile: = mercator.create_tile(ll[0], ll[1], zoom) map_tile_stack.clear() map_tile_stack.append(tile) @@ -90,22 +92,24 @@ func _process(_delta: float): if request_tile(tile, map_server_addr) == OK: map_tile_state = TASK_STATE.WAIT else: - push_error('Ошибка: Невозможно сформировать запрос HTTP') + log.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) + var neighbors_tiles = mercator.get_perimetr_tiles(root_tile, (map_image.get_size().x / map_tile.size.x) / 1) # = mercator.neighbors(root_tile) var neighbors_tiles_dic = {} for tile in neighbors_tiles: - neighbors_tiles_dic[str(tile)] = false + 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[str(tile)] = false + prev_tiles_dic[[tile.x, tile.y]] = false else: - signaller.emit_signal('zoom_complete', map_zoom) + if map_tile_stack.size() == 0: + signaller.emit_signal('zoom_complete', map_zoom) + print_debug('zoom_complete: %s' % [map_rects]) map_tile_state = TASK_STATE.DONE @@ -124,21 +128,22 @@ func _map_request_completed(result, response_code, headers, data): 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() # очистить список занятых областей изображения карты + 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 # 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) + var sx: float = float(map_tile.size.x) / (bounds.east - bounds.west) * (lng_c - tile.lng) + map_tile.size.x / 2 # Cмещение в пискселях центра плитки от заданной точки по горизонтали. + var sy: float = float(map_tile.size.y) / (bounds.north - bounds.south) * (lat_c - tile.lat) - map_tile.size.y / 2 # Cмещение в пискселях центра плитки от заданной точки по вертикали. + var dst_pos: Vector2i = Vector2i(sx, -sy) 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 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 img_tile_to_map_image(img_tile, dst_pos, tile) diff --git a/scenes/работа.tscn b/scenes/работа.tscn index e018a206..5f6ea8bc 100644 --- a/scenes/работа.tscn +++ b/scenes/работа.tscn @@ -131,7 +131,7 @@ offset_left = 952.0 offset_top = 1038.0 offset_right = 1104.0 offset_bottom = 1056.0 -metadata/zoom = 4 +metadata/zoom = 2 [node name="canvas" parent="." instance=ExtResource("11_b6su4")] diff --git a/scripts/mercator.gd b/scripts/mercator.gd index 8ead0fe8..c429922c 100644 --- a/scripts/mercator.gd +++ b/scripts/mercator.gd @@ -40,6 +40,21 @@ class Tile: return false + func _bound_index(index: int) -> int: + var mi: int = 2 ** self.z + if index < 0: + index *= -1 + index %= mi + index = mi - index + else: + index %= mi + return index + + func fix_xy(): + self.x = _bound_index(self.x) + self.y = _bound_index(self.y) + + ## Пара долготы и широты. class LngLat: var lng: float = 0.0 ## Долгота в десятичных градусах восточной долготы. @@ -287,18 +302,43 @@ func lnglat(x: float, y: float, truncate: bool = false) -> LngLat: ## [/codeblock] 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) > 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) + t.fix_xy() + tiles.append(t) + return tiles + + +## Возвращает все плитки вокруг заданной плитки +func get_allaround_tiles(tile: Tile, mr: int = 1) -> Array: + var xys = {} + var mi: int = 2 ** tile.z + for r in mr: + for a in range(0, 360, 180 / mi): + var ra = radians(a) + var ix = int(roundf(r * cos(ra))) + tile.x + var iy = int(roundf(r * sin(ra))) + tile.y + var t = Tile.new(ix, iy, tile.z) + t.fix_xy() + xys[[t.x, t.y]] = false + var tiles = [] + for txy in xys.keys(): + tiles.append(Tile.new(txy[0], txy[1], tile.z)) + return tiles + + +## Возвращает все плитки по периметру заданной плитки +func get_perimetr_tiles(tile: Tile, mr: int = 1) -> Array: + var tiles = [] + for i in range(-mr, mr + 1): + for j in range(-mr, mr + 1): + if i == 0 and j == 0: continue + var t = Tile.new(i + tile.x, j + tile.y, tile.z) + t.fix_xy() + tiles.append(t) return tiles diff --git a/scripts/tools.gd b/scripts/tools.gd index 6174fad9..5b266f04 100644 --- a/scripts/tools.gd +++ b/scripts/tools.gd @@ -3,6 +3,10 @@ extends Node ## Простые часто используемые функции +## Возвращает округлённое значение [param v] с точностью [param a] +func round_to(v: float, a: float) -> float: return snappedf(v, -a if v < 0 else a) + + ## Возвращает true, если val число, false - если иначе func type_is_num(val) -> bool: return (typeof(val) == TYPE_INT) or (typeof(val) == typeof(0.0)) diff --git a/shaders/tilemap.gdshader b/shaders/tilemap.gdshader index 2b502ea8..65aa7a35 100644 --- a/shaders/tilemap.gdshader +++ b/shaders/tilemap.gdshader @@ -9,6 +9,7 @@ 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); + //COLOR.a *= smooth_px(length(UV - center), radius, DS); }