From d186f316f0117a29aa795428f131f372df56d24d Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Nov 2023 12:49:19 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B5.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D1=81=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=80=D1=82=D0=B0=D0=BC=D0=B8=20=D0=9C=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B0=D1=82=D0=BE=D1=80=D0=B0.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BE=D0=B1=D1=89=D0=B8=D0=B9?= =?UTF-8?q?=20=D1=88=D0=B5=D0=B9=D0=B4=D0=B5=D1=80.=20=D0=A0=D0=B5=D1=84?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tab-switch.tscn | 2 +- scenes/tilemap.tscn | 1 + scenes/работа.tscn | 6 +- scripts/mercator.gd | 257 +++++++++++++++++--------------------- shaders/bip.gdshader | 10 +- shaders/sector.gdshader | 18 +-- shaders/shader_edu.tres | 42 +------ shaders/tilemap.gdshader | 5 +- shaders/tools.gdshaderinc | 29 +++++ 9 files changed, 159 insertions(+), 211 deletions(-) diff --git a/scenes/tab-switch.tscn b/scenes/tab-switch.tscn index c2c1e3cb..a580ec7f 100644 --- a/scenes/tab-switch.tscn +++ b/scenes/tab-switch.tscn @@ -4,7 +4,7 @@ [ext_resource type="PackedScene" uid="uid://b276iygic5itk" path="res://scenes/работа.tscn" id="2_pdbvn"] [ext_resource type="PackedScene" uid="uid://lwmw4egynmd1" path="res://scenes/контроль.tscn" id="3_2apbp"] [ext_resource type="PackedScene" uid="uid://trt0q8th3bn2" path="res://scenes/журнал.tscn" id="4_yq6c0"] -[ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/ЭМС.tscn" id="5_tlyql"] +[ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/эмс.tscn" id="5_tlyql"] [ext_resource type="PackedScene" uid="uid://bnptm4rlp60dq" path="res://scenes/настройки.tscn" id="6_rxq15"] [node name="tab_switch" type="TabContainer"] diff --git a/scenes/tilemap.tscn b/scenes/tilemap.tscn index 7dda1a1c..9f96ab88 100644 --- a/scenes/tilemap.tscn +++ b/scenes/tilemap.tscn @@ -8,6 +8,7 @@ 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") diff --git a/scenes/работа.tscn b/scenes/работа.tscn index 6a9f4fa0..8b9b4a9e 100644 --- a/scenes/работа.tscn +++ b/scenes/работа.tscn @@ -12,10 +12,9 @@ [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_x7kiv"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_whr8j"] resource_local_to_scene = true shader = ExtResource("11_7ohqv") -shader_parameter/center = Vector2(0.5, 0.5) shader_parameter/radius = 0.4 [node name="Работа" type="Panel"] @@ -134,8 +133,7 @@ offset_right = 1104.0 offset_bottom = 1056.0 [node name="tilemap" parent="." instance=ExtResource("10_wpi4s")] -material = SubResource("ShaderMaterial_x7kiv") -position = Vector2(548, 552) +material = SubResource("ShaderMaterial_whr8j") [connection signal="drag_begin" from="." to="." method="_on_drag_begin"] [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] diff --git a/scripts/mercator.gd b/scripts/mercator.gd index 163a6b52..ce60f106 100644 --- a/scripts/mercator.gd +++ b/scripts/mercator.gd @@ -1,5 +1,6 @@ extends Node -## Web mercator XYZ tile utilities + +## Веб-утилиты для работы с меркаторскими XYZ-плитками. const R2D: = 180.0 / PI const RE: = 6378137.0 @@ -9,9 +10,8 @@ const LL_EPSILON: = 1e-11 const MAX_ZOOM: = 28 -## An XYZ web mercator tile -## x, y, z : int -## x and y indexes of the tile and zoom level z. +## XYZ-плитка веб-меркатора [param x], [param y], [param z] индексы +# [b]x[/b] и [b]y[/b] плитки и уровень масштабирования [b]z[/b]. class Tile: var x: int var y: int @@ -38,20 +38,21 @@ class Tile: class LngLat: var lng: float = 0.0 ## Долгота в десятичных градусах восточной долготы. var lat: float = 0.0 ## Широта в десятичных градусах северной широты. + ## Возвращает в виде массива + func as_array() -> Array: return [self.lng, self.lat] func _init(lng0, lat0): self.lng = lng0 self.lat = lat0 -## Географическое ограничивающее поле. -## запад, юг, восток, север : float -## Значения границ в десятичных градусах. +## Географические границы. Хранит значения границ в десятичных градусах. class LngLatBbox: - var west: float - var south: float - var east: float - var north: float - func as_array(): return [self.west, self.south, self.east, self.north] + var west: float ## Запад + var south: float ## Юг + var east: float ## Восток + var north: float ## Север + ## Возвращает в виде массива + func as_array() -> Array: return [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 @@ -59,15 +60,13 @@ class LngLatBbox: self.north = n -## Граничная область веб-меркатора. -## Атрибуты: left, bottom, right, top : float. -## Значения границ в метрах. +## Граничная область веб-меркатора. Хранит значения границ в метрах. class Bbox: var left: float var bottom: float var right: float var top: float - func as_array(): return [self.left, self.bottom, self.right, self.top] + func as_array() -> Array: return [self.left, self.bottom, self.right, self.top] func _init(l: float = 0.0, b: float = 0.0, r: float = 0.0, t: float = 0.0): self.left = l self.bottom = b @@ -75,25 +74,26 @@ class Bbox: self.top = t -func degrees(v: float): return (v * 180.0) / PI +func degrees(v: float) -> float: return (v * 180.0) / PI -func radians(v: float): return (v * PI) / 180.0 +func radians(v: float) -> float: return (v * PI) / 180.0 -func rshift(val: int, n: int): return (val % 0x100000000) >> n +func rshift(val: int, n: int) -> int: return (val % 0x100000000) >> n ## Возвращает плитки и занимаемый ими размер области в пикселях: -## ширина, высота, левая граница, верхняя граница, плитки -## [param west] [float] Западная граница области -## [param east] [float] Восточная граница области -## [param south] [float] Южная граница области -## [param north] [float] Северная граница области -## [param size] [float] Размер плитки в пикселях -## [param zoom] [float] Детализация -func get_tiles(west, south, east, north, zoom, size): - var tiles = [create_tiles(west, south, east, north, zoom)] +## ширина, высота, левая граница, верхняя граница, плитки.[br] +## [param west] - Западная граница области.[br] +## [param east] - Восточная граница области.[br] +## [param south] - Южная граница области.[br] +## [param north] - Северная граница области.[br] +## [param size] - Размер плитки в пикселях.[br] +## [param zoom] - Детализация.[br] +func get_tiles(west: float, south: float, east: float, north: float, zoom: int, size: int) -> Array: + var tiles: = create_tiles(west, south, east, north, zoom) + var mm = [] for t in tiles: mm.append(t.x) var min_x = mm.min() @@ -109,32 +109,28 @@ func get_tiles(west, south, east, north, zoom, size): return [w, h, min_x, min_y, tiles, max_x - min_x + 1] -## Возвращает размер области в метрах -## [param west] [float] - Западная граница области -## [param param] [float] - Восточная граница области -## [param south] [float] - Южная граница области -## [param north] [float] - Северная граница области -## [return] [Array] -func get_size_from_degrees(west, south, east, north) -> Array[float]: +## Возвращает размер области в метрах.[br] +## [param west] - Западная граница области.[br] +## [param param] - Восточная граница области.[br] +## [param south] - Южная граница области.[br] +## [param north] - Северная граница области.[br] +func get_size_from_degrees(west: float, south: float, east: float, north: float) -> Array[float]: var xy0: = xy(west, north, true) var xy1: = xy(east, south, true) return [xy0[0] - xy1[0], xy0[1] - xy1[1]] -## Возвращает границы области в градусах -## [param m] [float] - Размер карты в метрах. -## [param lng] [float] - Долгота центра области в градусах (-180...180). -## [param lat] [float] - Широта центра области в градусах (-90...90). -## [return] [float, float, float, float] -func get_degrees_bounds(m: float, lng: float, lat: float): +## Возвращает границы области в градусах.[br] +## [param m] - Размер карты в метрах.[br] +## [param lng] - Долгота центра области в градусах (-180...180).[br] +## [param lat] - Широта центра области в градусах (-90...90).[br] +func get_degrees_bounds(m: float, lng: float, lat: float) -> Array[float]: m /= 2.0 var x_y = xy(lng, lat, true) - var ws = lnglat(x_y[0] - m, x_y[1] - m) - var en = lnglat(x_y[0] + m, x_y[1] + m) - return [ws[0], ws[1], en[0], en[1]] + return [x_y[0] - m, x_y[1] - m, x_y[0] + m, x_y[1] + m] -func get_tiles_bounds(tiles): +func get_tiles_bounds(tiles: Array[Tile]) -> Array: var mm = [] for t in tiles: mm.append(bounds(t).west) var mmw = mm.min(); mm.clear() @@ -151,17 +147,15 @@ func get_tiles_bounds(tiles): return [mmw, mms, mme, mmn] -## Возвращает левую верхнюю долготу и широту плитки. -## [param tile] Плитка или последовательность int. Может быть либо экземпляр -## Tile, либо 3 ints, X, Y, Z. -## [return] LngLat +## Возвращает левую верхнюю долготу и широту плитки.[br] +## [param tile] Плитка.[br] ## [codeblock] ## >>> ul(Tile(x=0, y=0, z=1)) ## LngLat(lng=-180.0, lat=85.0511287798066) ## >>> mercantile.ul(1, 1, 1) ## LngLat(lng=0.0, lat=0.0) ## [/codeblock] -func ul(tile: Tile, zoom: int): +func ul(tile: Tile, zoom: int) -> LngLat: var Z2 = pow(2, zoom) var lon_deg = tile.x / Z2 * 360.0 - 180.0 var lat_rad = atan(sinh(PI * (1 - 2 * tile.y / Z2))) @@ -169,9 +163,8 @@ func ul(tile: Tile, zoom: int): return LngLat.new(lon_deg, lat_deg) -## Возвращает левую верхнюю долготу и широту плитки. -## [param tile] [Плитка] Может быть либо экземпляром Tile, либо 3 интами, X, Y, Z. -## [return] [LngLat] +## Возвращает левую верхнюю долготу и широту плитки.[br] +## [param tile] - Плитка.[br] ## [codeblock] ## >>> ul(Tile(x=0, y=0, z=1)) ## LngLat(lng=-180.0, lat=85.0511287798066) @@ -186,21 +179,16 @@ func ul2(tile: Tile) -> Array[float]: return [lat_deg, lon_deg] -## Возвращает граничную область плитки. -## [param tile] [Tile] или [Array]. Может быть либо экземпляром [Tile], либо 3 -## целыми числами (X, Y, Z). -## [return] [LngLatBbox] +## Возвращает граничную область плитки.[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 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_deg = degrees(lr_lat_rad) - return LngLatBbox.new(ul_lon_deg, lr_lat_deg, lr_lon_deg, ul_lat_deg) @@ -212,12 +200,11 @@ func truncate_lnglat(lng: float, lat: float) -> Array: return [lng, lat] -## Преобразование долготы и широты в веб-меркатор x, y. -## [param lng] [param lat]: float -## Долгота и широта в десятичных градусах [param truncate] [bool] -Нужно ли -## усекать или обрезать входные данные до пределов веб-меркатора. -## [return] [x: float, y: float]. [param y] будет [b]inf[/b] на северном полюсе. -## ([param lat] >= 90) и [b]-inf[/b] на южном полюсе ([param lat] <= -90). +## Преобразование долготы и широты в веб-меркатор x, y.[br] +## [param lng] - Долгота в десятичных градусах.[br] +## [param lat] - Широта в десятичных градусах.[br] +## [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 x: float = RE * radians(lng) @@ -228,18 +215,17 @@ func xy(lng: float, lat: float, truncate: bool = false) -> Array[float]: return [x, y] -## Преобразование координат веб-меркатора x, y в долготу и широту. -## [param x] [float], [param y] [float] - Координаты веб-меркатора в метрах. -## [param truncate] [bool] - Нужно ли усекать или обрезать входные данные до границ веб-меркатора. -## [return] [LngLat] -func lnglat(x, y, truncate=false): - 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] +## Преобразование координат веб-меркатора x, y в долготу и широту.[br] +## [param x], [param y] - Координаты веб-меркатора в метрах.[br] +## [param truncate] - Нужно ли усекать или обрезать входные данные до границ веб-меркатора. +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] return LngLat.new(ll[0], ll[1]) -## Соседи плитки. [func neighbors] возвращает до восьми +## Соседи плитки. [method neighbors] возвращает до восьми ## соседних плиток, при этом плитки будут опущены, если они не являются действительными, например. ## Tile(-1, -1, z). [param tile]: Плитка или последовательность int ## Может быть либо экземпляр Tile, либо 3 ints, X, Y, Z. @@ -262,11 +248,9 @@ func neighbors(tile: Tile) -> Array[Tile]: return tiles -## Получение меркаторской граничной рамки веб-плитки -## [param tile] - Плитка или последовательность int. Может быть либо экземпляр -## [Tile], либо 3 ints, X, Y, Z. -## [return] [Bbox] -## Примечания. Эпсилон вычитается из правой границы и прибавляется к нижней. +## Получение меркаторской граничной рамки веб-плитки.[br] +## [param tile] - Плитка.[br] +## [i]Эпсилон вычитается из правой границы и прибавляется к нижней[/i] func xy_bounds(tile: Tile, zoom: int) -> Bbox: var tile_size = CE / pow(2, zoom) var left = tile.x * tile_size - CE / 2 @@ -285,10 +269,9 @@ func _xy(lng, lat, truncate=false) -> Array: ## Получение плитки, содержащей долготу и широту -## [param lng], [param lat] [float] - Пара долготы и широты в десятичных градусах. -## [param zoom] [int] - Уровень масштабирования веб-меркатора. -## [param truncate] [bool] - Нужно ли усекать вводимые данные до границ веб-меркатора. -## [return] [Tile] +## [param lng], [param lat] - Пара долготы и широты в десятичных градусах.[br] +## [param zoom] - Уровень масштабирования веб-меркатора.[br] +## [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) @@ -308,12 +291,10 @@ func create_tile(lng: float, lat: float, zoom: int, truncate: bool=false) -> Til return tile -## Получение четверного ключа плитки -## [param tile] [Tile] или последовательность [int]. Может быть либо экземпляр -## [Tile] или 3 целых, X, Y, Z. -## [return] [String] -func quadkey(tile: Tile, zoom) -> String: - var rs: = String() +## Получение четверного ключа плитки.[br] +## [param tile] Плитка +func quadkey(tile: Tile, zoom: int) -> String: + var rs: = '' for z in range(zoom, 0, -1): var digit = 0 var mask = 1 << (z - 1) @@ -325,10 +306,9 @@ func quadkey(tile: Tile, zoom) -> String: return rs -## Получение плитки, соответствующей четверному ключу. -## [param qk] [String] - Строка четверного ключа. -## [return] [Tile] -func quadkey_to_tile(qk: Array): +## Получение плитки, соответствующей четверному ключу.[br] +## [param qk] - Строка четверного ключа. +func quadkey_to_tile(qk: Array) -> Tile: var tile: = Tile.new() if len(qk) == 0: return tile var i = 0 @@ -351,14 +331,12 @@ func quadkey_to_tile(qk: Array): return tile -## Получение плиток, перекрываемых географической рамкой -## [param west], [param south], [param east], [param north]: последовательность [float] -## - Значения границ в десятичных градусах. -## [param zooms] [int] или [Array[int]]. - Один или несколько уровней масштабирования. -## [param truncate] [bool] - Нужно ли усекать вводимые данные до границ веб-меркатора. -## [return] Tile -## Примечания. В параметрах south и east используется небольшой эпсилон, чтобы -## функция выдавала ровно одну плитку при задании границ этой же плитки. +## Получение плиток, перекрываемых географической рамкой.[br] +## [param west], [param south], [param east], [param north] - Значения границ в десятичных градусах.[br] +## [param zooms] - Один или несколько уровней масштабирования.[br] +## [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) @@ -386,19 +364,17 @@ func create_tiles(west: float, south: float, east: float, north: float, zooms, t ## Получение родителя плитки. Родительская плитка - это плитка на один уровень масштабирования ниже, которая -## содержит данную "дочернюю" плитку. -## [param tile] [Tile] или последовательность int - Может быть либо экземпляром Tile. -## или 3 ints, X, Y, Z. -## [param zoom] [int] - Определяет уровень *масштабирования* возвращаемой родительской плитки. -## По умолчанию это значение на один ниже, чем у плитки (непосредственного родителя). -## [return] [Tile] +## содержит данную "дочернюю" плитку.[br] +## [param tile] - Плитка.[br] +## [param zoom] - Определяет уровень *масштабирования* возвращаемой родительской плитки. +## По умолчанию это значение на один ниже, чем у плитки (непосредственного родителя).[br] ## [codeblock] ## >>> parent(Tile(0, 0, 2)) ## Tile(x=0, y=0, z=1) ## >>> parent(Tile(0, 0, 2), zoom=0) ## Tile(x=0, y=0, z=0) ## [/codeblock] -func parent(tile: Tile, zoom=null): +func parent(tile: Tile, zoom=null) -> Tile: if tile.z == 0: return null assert((zoom != null) and (tile.z > zoom or zoom == int(zoom)), 'Масштаб (zoom) должен быть целым числом и меньше масштаба входной плитки (tile).') @@ -424,13 +400,12 @@ func parent(tile: Tile, zoom=null): ## Получение дочерних элементов плитки. Дочерние элементы упорядочены: -## верхний-левый, верхний-правый, bottom-right, bottom-left. -## [tile] [Tile] или последовательность int. Может быть либо экземпляром Tile, -## либо 3 интами, X, Y, Z. -## [param zoom] [int] Возвращает все дочерние элементы с масштабом *zoom*, в порядке убывания глубины. -## в порядке намотки по часовой стрелке. Если не указано, возвращаются ближайшие (т.е. zoom + 1) -## дочерние элементы плитки. -## [return] [Array] +## верхний-левый, верхний-правый, нижний-правый, нижний-левый. Возвращает все +## дочерние элементы с масштабом *zoom*, в порядке убывания глубины в порядке +## вращения по часовой стрелке. Если не указано, возвращаются ближайшие +## (т.е. zoom + 1) дочерние элементы плитки.[br] +## [param tile] - Плитка.[br] +## [param zoom] - Уровень детализации. ## [codeblock] ## >>> children(Tile(0, 0, 0)) ## [Tile(x=0, y=0, z=1), Tile(x=0, y=1, z=1), Tile(x=1, y=0, z=1), Tile(x=1, y=1, z=1)] @@ -455,7 +430,7 @@ func children(tile, zoom) -> Array: ## Если есть, то происходит их слияние. Возвращает список плиток, а также булево ## число, указывающее, были ли они объединены. При многократном применяя ## [method merge], можно упростить набор плиток. -func merge(merge_set): +func merge(merge_set) -> Array: var upwards_merge: = {} for tile in merge_set.keys(): var tile_parent = parent(tile) @@ -476,8 +451,7 @@ func merge(merge_set): ## Максимально уменьшает размер набора плиток путем слияния листьев с родителями. ## [param tiles] - Последовательность плиток для слияния. -## [return] [Array] -func simplify(tiles: Array): +func simplify(tiles: Array) -> Array: # Проверьте, существует ли уже плитка и ее родитель. # Убедитесь, что плитки отсортированы по масштабу, поэтому родительские # плитки встречаются первыми. Если да, отбросьте дочернюю плитку @@ -510,8 +484,7 @@ func simplify(tiles: Array): ## Tile(x=0, y=0, z=0). ## [param bbox] последовательность [float] значений границ запада, юга, востока, ## севера в десятичных градусах. -## [return] [Tile] -func bounding_tile(bbox, truncate: bool = false): +func bounding_tile(bbox, truncate: bool = false) -> Tile: if len(bbox) == 2: bbox += bbox @@ -556,18 +529,14 @@ func _getBboxZoom(bbox: Array): return MAX_ZOOM -## Получение GeoJSON-функции, соответствующей плитке -## [param tile] [Плитка] или последовательность int - Может быть либо экземпляром [Плитка], либо 3 int, X, Y, Z. -## [Tile] или 3 целых, X, Y, Z. -## [param fid] [String] - Идентификатор объекта. -## [param props] [Dictionary] - Необязательные дополнительные свойства признака. -## [param projected] [String] - Можно создать нестандартный веб-меркатор GeoJSON. -## передав 'mercator'. -## [param buffer] [float] - Необязательное буферное расстояние для полигона GeoJSON. -## [param precision] [int] - Координаты GeoJSON будут усечены до данного -## количества знаков после запятой. -## [return] [Dictionary] -func feature(tile: Tile, fid=null, props=null, projected='geographic', buffer=null): +## Получение GeoJSON-функции, соответствующей плитке.[br] +## [param tile] - Плитка.[br] +## [param fid] - Идентификатор объекта.[br] +## [param props] - Необязательные дополнительные свойства признака.[br] +## [param projected] - Можно создать нестандартный веб-меркатор GeoJSON передав 'mercator'[br] +## [param buffer] - Необязательное буферное расстояние для полигона GeoJSON.[br] +## [param precision] - Координаты GeoJSON будут усечены до данного количества знаков после запятой.[br] +func feature(tile: Tile, fid:String = 'null', props=null, projected='geographic', buffer=null) -> Dictionary: var west_south_east_north = bounds(tile).as_array() var west = west_south_east_north[0] var south = west_south_east_north[1] @@ -605,23 +574,22 @@ func feature(tile: Tile, fid=null, props=null, projected='geographic', buffer=nu if props: feat['properties'].update(props) - if fid != null: + if fid != 'null': feat['id'] = fid return feat -func isinstance(obj, types: Array): +func isinstance(obj, types: Array) -> bool: for type in types: if is_instance_of(obj, type): return true return false -## Все кортежи координат из геометрии, объекта или коллекции -## [param lng] [float] - Долгота -## [param lat] [float] - широта -## [return] [Array] +## Все кортежи координат из геометрии, объекта или коллекции.[br] +## [param lng] - Долгота.[br] +## [param lat] - широта.[br] func _coords(obj) -> Array: var coordinates = [] if is_instance_of(obj, TYPE_ARRAY): @@ -645,7 +613,7 @@ func _coords(obj) -> Array: return v -func func1(bbox: Array, coords: Array): +func _func1(bbox: Array, coords: Array) -> Array[float]: var w = bbox[0] var s = bbox[1] var e = bbox[2] @@ -655,10 +623,9 @@ func func1(bbox: Array, coords: Array): return [min(w, lng), min(s, lat), max(e, lng), max(n, lat)] -## Возвращает граничную область объекта GeoJSON. -## [param obj] - Отображение, геометрия GeoJSON, объект или коллекция объектов. -## [returns] [LngLatBbox] -func geojson_bounds(obj): +## Возвращает граничную область объекта GeoJSON.[br] +## [param obj] - Отображение, геометрия GeoJSON, объект или коллекция объектов.[br] +func geojson_bounds(obj) -> LngLatBbox: var coords: Array = _coords(obj) - var wsen = coords.reduce(func1, [180.0, 90.0, -180.0, -90.0]) + var wsen = coords.reduce(_func1, [180.0, 90.0, -180.0, -90.0]) return LngLatBbox.new(wsen[0], wsen[1], wsen[2], wsen[3]) diff --git a/shaders/bip.gdshader b/shaders/bip.gdshader index 56ead0a5..558e5252 100644 --- a/shaders/bip.gdshader +++ b/shaders/bip.gdshader @@ -1,7 +1,8 @@ shader_type canvas_item; -/* Закрашенная окружность */ +#include "tools.gdshaderinc" +/* Закрашенная окружность */ uniform vec4 color: source_color = vec4(1, 1, 1, 1); uniform vec4 color_up: source_color = vec4(1, 1, 1, 1); /* Цвет вспышки при обновлении */ uniform uint tick_update = 0; /* Время последнего обновления, мс */ @@ -11,13 +12,8 @@ const vec2 center = vec2(0.125, 0.125); /* Центр долже const float radius = 0.125 - ds * 2.0; /* Радиус должен быть 0.5, но это не так */ -float smooth_px(float r, float R) -{ - return 1.0 - smoothstep(R - ds, R + ds, r); -} - void fragment() { - COLOR = color * smooth_px(length(UV - center), radius); + COLOR = color * smooth_px(length(UV - center), radius, ds); } diff --git a/shaders/sector.gdshader b/shaders/sector.gdshader index e8d8cf50..1b2d43d5 100644 --- a/shaders/sector.gdshader +++ b/shaders/sector.gdshader @@ -1,5 +1,7 @@ shader_type canvas_item; +#include "tools.gdshaderinc" + /* Закрашенный сектор окружности ограниченный угловым сектором и радиусами */ uniform vec4 color: source_color = vec4(1, 1, 1, 1); @@ -16,12 +18,6 @@ const float dsa = 0.0025; /* Относительное расс const float dsr = 0.00025; /* Относительное расстояние на котором выполняется сглаживание краёв по круговым линиям */ -float smooth_px(float r, float R, float ds) -{ - return 1.0 - smoothstep(R - ds, R + ds, r); -} - - vec4 sector(vec4 c, vec2 uv_pos, float r0, float r1, float w) { bool rc = false; @@ -49,17 +45,9 @@ vec4 sector(vec4 c, vec2 uv_pos, float r0, float r1, float w) } -void rotate_vec2(inout vec2 vert, float a) -{ - float sin_a = sin(a); - float cos_a = cos(a); - vert *= mat2(vec2(cos_a, sin_a), vec2(-sin_a, cos_a)); -} - - void vertex() { - rotate_vec2(VERTEX, radians(90.0 - dir)); + rotate_vec2(VERTEX, radians(90.0 - dir), vec2(0, 0)); } diff --git a/shaders/shader_edu.tres b/shaders/shader_edu.tres index f7d68e11..ed5b6155 100644 --- a/shaders/shader_edu.tres +++ b/shaders/shader_edu.tres @@ -3,6 +3,8 @@ [sub_resource type="Shader" id="1"] code = "shader_type canvas_item; +#include \"tools.gdshaderinc\" + uniform vec2 pc0; /* Центр сетки антенн */ uniform float rotation: hint_range(0.0, 360.0) = 0.0; /* */ uniform vec4 color0: source_color = vec4(0.38, 0.47, 0.51, 0.4); @@ -40,12 +42,6 @@ const float d4 = 90.0; const float ds = 1.0; -float SMOOTH(float r, float R, float d) -{ - return 1.0 - smoothstep(R - d, R + d, r); -} - - void sector(inout vec4 c, vec2 uv, vec2 center, float a, float da, float r0, float r1, vec4 color) { float l = distance(center, uv); @@ -55,8 +51,8 @@ void sector(inout vec4 c, vec2 uv, vec2 center, float a, float da, float r0, flo da /= 2.0; float a0 = radians(a - da); float a1 = radians(a + da); - float va = SMOOTH(a0 * sf, theta, ds) - SMOOTH(a1 * sf, theta, ds); - float vr = SMOOTH(r0, l, ds) - SMOOTH(r1, l, ds); + float va = smooth_px(a0 * sf, theta, ds) - smooth_px(a1 * sf, theta, ds); + float vr = smooth_px(r0, l, ds) - smooth_px(r1, l, ds); float rgb = sqrt(va * vr); c.rgb += color.rgb * rgb * color.a; c.a += rgb * color.a; @@ -75,37 +71,9 @@ void antenas(inout vec4 c, vec2 uv, vec2 p0, int cnt, float r0, float r1, vec4 c } -void circle_thin(inout vec3 color, vec2 uv, vec2 p, float r, float w, vec3 c, float a) -{ - float d = distance(uv, p); - float v0 = r - w; - float v1 = r + w; - color += a * sqrt(smoothstep(v1, v0, d) * smoothstep(v0, v1, d) * c); -} - - -void line_r(inout vec4 color, vec2 uv, vec2 center, float theta0, float radius, vec4 c) -{ - vec2 d = uv - center; - vec2 p = radius * vec2(cos(theta0 * PI / 180.0), - sin(theta0 * PI / 180.0)); - float l = length(d - p * clamp(dot(d, p) / dot(p, p), 0.0, 1.0)); - color.rgb += c.rgb * SMOOTH(l, 1.0, ds) * c.a; -} - - -void rotate_vec2(inout vec2 vert, float a) -{ - float sin_a = sin(a); - float cos_a = cos(a); - vert *= mat2(vec2(cos_a, sin_a), vec2(-sin_a, cos_a)); -} - - void vertex() { - VERTEX -= pc0; - rotate_vec2(VERTEX, radians(rotation)); - VERTEX += pc0; + rotate_vec2(VERTEX, radians(rotation), pc0); } diff --git a/shaders/tilemap.gdshader b/shaders/tilemap.gdshader index f1403dc5..d9daad9b 100644 --- a/shaders/tilemap.gdshader +++ b/shaders/tilemap.gdshader @@ -2,9 +2,10 @@ shader_type canvas_item; #include "tools.gdshaderinc" -uniform vec2 center = vec2(0.5, 0.5); -uniform float radius: hint_range(0.0, 1.0) = 0.4; /* Радиус */ +/* Рисует текстуру по маске в форме окружности */ +uniform float radius: hint_range(0.0, 1.0) = 0.4; /* Радиус */ +const vec2 center = vec2(0.5, 0.5); void fragment() { diff --git a/shaders/tools.gdshaderinc b/shaders/tools.gdshaderinc index bb0b6d32..8dc0df97 100644 --- a/shaders/tools.gdshaderinc +++ b/shaders/tools.gdshaderinc @@ -1,6 +1,35 @@ const float DS = 0.004; /* Относительное расстояние на котором выполняется сглаживание краёв */ + float smooth_px(float r, float R, float ds) { return 1.0 - smoothstep(R - ds, R + ds, r); } + + +void circle_thin(inout vec3 color, vec2 uv, vec2 p, float r, float w, vec3 c, float a) +{ + float d = distance(uv, p); + float v0 = r - w; + float v1 = r + w; + color += a * sqrt(smoothstep(v1, v0, d) * smoothstep(v0, v1, d) * c); +} + + +void line_r(inout vec4 color, vec2 uv, vec2 center, float theta0, float radius, vec4 c) +{ + vec2 d = uv - center; + vec2 p = radius * vec2(cos(theta0 * PI / 180.0), - sin(theta0 * PI / 180.0)); + float l = length(d - p * clamp(dot(d, p) / dot(p, p), 0.0, 1.0)); + color.rgb += c.rgb * smooth_px(l, 1.0, DS) * c.a; +} + + +void rotate_vec2(inout vec2 vert, float a, vec2 pos) +{ + vert -= pos; + float sin_a = sin(a); + float cos_a = cos(a); + vert *= mat2(vec2(cos_a, sin_a), vec2(-sin_a, cos_a)); + vert += pos; +}