mirror of
https://github.com/PaiGramTeam/fastapi_genshin_map.git
synced 2024-11-24 07:10:42 +00:00
✨ 支持分层地图
This commit is contained in:
parent
18a6380078
commit
6ded28d5bc
1
.gitignore
vendored
1
.gitignore
vendored
@ -131,4 +131,5 @@ dmypy.json
|
|||||||
# 地图资源
|
# 地图资源
|
||||||
fastapi_genshin_map/GetMapImage/map_data
|
fastapi_genshin_map/GetMapImage/map_data
|
||||||
fastapi_genshin_map/GetMapImage/resource_data
|
fastapi_genshin_map/GetMapImage/resource_data
|
||||||
|
fastapi_genshin_map/GetMapImage/icon_data
|
||||||
fastapi_genshin_map/GetMapImage/genshinmap.log
|
fastapi_genshin_map/GetMapImage/genshinmap.log
|
@ -43,4 +43,4 @@
|
|||||||
+ [GPL-3.0 License](https://github.com/KimigaiiWuyi/GenshinUID/blob/main/LICENSE) ©[@KimigaiiWuyi](https://github.com/KimigaiiWuyi)
|
+ [GPL-3.0 License](https://github.com/KimigaiiWuyi/GenshinUID/blob/main/LICENSE) ©[@KimigaiiWuyi](https://github.com/KimigaiiWuyi)
|
||||||
|
|
||||||
## 丨返回图示例
|
## 丨返回图示例
|
||||||
![测试.jpg](https://s2.loli.net/2022/10/17/D2cI5tQdgVk3Uuz.jpg)
|
![测试.jpg](https://s2.loli.net/2023/10/18/Khd5LRQF3HqrEVD.jpg)
|
||||||
|
@ -6,7 +6,7 @@ import numpy as np
|
|||||||
from sklearn.cluster import KMeans
|
from sklearn.cluster import KMeans
|
||||||
from shapely.geometry import Point, Polygon
|
from shapely.geometry import Point, Polygon
|
||||||
|
|
||||||
from .models import XYPoint
|
from .models import XYPoint, XYZPoint
|
||||||
|
|
||||||
Pos = Tuple[float, float]
|
Pos = Tuple[float, float]
|
||||||
Poses = List[XYPoint]
|
Poses = List[XYPoint]
|
||||||
@ -14,8 +14,8 @@ Points = List[Point]
|
|||||||
|
|
||||||
|
|
||||||
def k_means_points(
|
def k_means_points(
|
||||||
points: List[XYPoint], length: int = 500, clusters: int = 3
|
points: List[XYZPoint], length: int = 500, clusters: int = 3
|
||||||
) -> List[Tuple[XYPoint, XYPoint, Poses]]:
|
) -> List[Tuple[XYZPoint, XYZPoint, Poses]]:
|
||||||
"""
|
"""
|
||||||
通过 K-Means 获取集群坐标列表
|
通过 K-Means 获取集群坐标列表
|
||||||
|
|
||||||
|
@ -59,6 +59,10 @@ class Point(BaseModel):
|
|||||||
author_name: str
|
author_name: str
|
||||||
ctime: str
|
ctime: str
|
||||||
display_state: int
|
display_state: int
|
||||||
|
area_id: int
|
||||||
|
ext_attrs: str
|
||||||
|
z_level: int
|
||||||
|
icon_sign: int
|
||||||
|
|
||||||
|
|
||||||
class Slice(BaseModel):
|
class Slice(BaseModel):
|
||||||
@ -100,6 +104,12 @@ class XYPoint(NamedTuple):
|
|||||||
y: float
|
y: float
|
||||||
|
|
||||||
|
|
||||||
|
class XYZPoint(NamedTuple):
|
||||||
|
x: float
|
||||||
|
y: float
|
||||||
|
z: int
|
||||||
|
|
||||||
|
|
||||||
class Kind(BaseModel):
|
class Kind(BaseModel):
|
||||||
id: int
|
id: int
|
||||||
name: str
|
name: str
|
||||||
|
@ -8,7 +8,7 @@ from asyncio import gather, create_task
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
from httpx import AsyncClient
|
from httpx import AsyncClient
|
||||||
|
|
||||||
from .models import Maps, Point, XYPoint
|
from .models import Maps, Point, XYPoint, XYZPoint
|
||||||
|
|
||||||
CLIENT = AsyncClient()
|
CLIENT = AsyncClient()
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ async def get_map_by_pos(
|
|||||||
return await get_img(map.slices[_pos_to_index(x, y)])
|
return await get_img(map.slices[_pos_to_index(x, y)])
|
||||||
|
|
||||||
|
|
||||||
def get_points_by_id(id_: int, points: List[Point]) -> List[XYPoint]:
|
def get_points_by_id(id_: int, points: List[Point]) -> List[XYZPoint]:
|
||||||
"""
|
"""
|
||||||
根据 Label ID 获取坐标点
|
根据 Label ID 获取坐标点
|
||||||
|
|
||||||
@ -91,13 +91,13 @@ def get_points_by_id(id_: int, points: List[Point]) -> List[XYPoint]:
|
|||||||
`list[XYPoint]`
|
`list[XYPoint]`
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
XYPoint(point.x_pos, point.y_pos)
|
XYZPoint(point.x_pos, point.y_pos, point.z_level)
|
||||||
for point in points
|
for point in points
|
||||||
if point.label_id == id_
|
if point.label_id == id_
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def convert_pos(points: List[XYPoint], origin: List[int]) -> List[XYPoint]:
|
def convert_pos(points: List[XYZPoint], origin: List[int]) -> List[XYZPoint]:
|
||||||
"""
|
"""
|
||||||
将米游社资源坐标转换为以左上角为原点的坐标系的坐标
|
将米游社资源坐标转换为以左上角为原点的坐标系的坐标
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ def convert_pos(points: List[XYPoint], origin: List[int]) -> List[XYPoint]:
|
|||||||
>>> convert_pos(points, origin)
|
>>> convert_pos(points, origin)
|
||||||
[XYPoint(x=6044, y=9335), XYPoint(x=644, y=6135)]
|
[XYPoint(x=6044, y=9335), XYPoint(x=644, y=6135)]
|
||||||
"""
|
"""
|
||||||
return [XYPoint(x + origin[0], y + origin[1]) for x, y in points]
|
return [XYZPoint(x + origin[0], y + origin[1], z) for x, y, z in points]
|
||||||
|
|
||||||
|
|
||||||
def convert_pos_crop(
|
def convert_pos_crop(
|
||||||
|
10
fastapi_genshin_map/GetMapImage/download.py
Normal file
10
fastapi_genshin_map/GetMapImage/download.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import aiofiles
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
|
|
||||||
|
async def download_file(url, save_path):
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(url) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
async with aiofiles.open(save_path, "wb") as f:
|
||||||
|
await f.write(await response.read())
|
@ -9,6 +9,7 @@ from PIL import Image
|
|||||||
|
|
||||||
from .GenshinMap.genshinmap import img, models, request, utils
|
from .GenshinMap.genshinmap import img, models, request, utils
|
||||||
from .logger import logger
|
from .logger import logger
|
||||||
|
from .download import download_file
|
||||||
|
|
||||||
Image.MAX_IMAGE_PIXELS = 333120000
|
Image.MAX_IMAGE_PIXELS = 333120000
|
||||||
router = APIRouter(prefix="/get_map")
|
router = APIRouter(prefix="/get_map")
|
||||||
@ -16,6 +17,7 @@ TEXT_PATH = Path(__file__).parent / "texture2d"
|
|||||||
mark_quest = Image.open(TEXT_PATH / "mark_quest.png").resize((32, 32))
|
mark_quest = Image.open(TEXT_PATH / "mark_quest.png").resize((32, 32))
|
||||||
MAP = Path(__file__).parent / "map_data"
|
MAP = Path(__file__).parent / "map_data"
|
||||||
RESOURCE_PATH = Path(__file__).parent / "resource_data"
|
RESOURCE_PATH = Path(__file__).parent / "resource_data"
|
||||||
|
ICON_PATH = Path(__file__).parent / "icon_data"
|
||||||
CHASM_PATH = MAP / "chasm.png"
|
CHASM_PATH = MAP / "chasm.png"
|
||||||
ENKANOMIYA_PATH = MAP / "enkanomiya.png"
|
ENKANOMIYA_PATH = MAP / "enkanomiya.png"
|
||||||
TEYVAT_PATH = MAP / "teyvat.png"
|
TEYVAT_PATH = MAP / "teyvat.png"
|
||||||
@ -30,6 +32,9 @@ MAP_ID_DICT = {
|
|||||||
# MapID.golden_apple_archipelago, # 金苹果群岛
|
# MapID.golden_apple_archipelago, # 金苹果群岛
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if not ICON_PATH.exists():
|
||||||
|
ICON_PATH.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
@router.on_event("startup")
|
@router.on_event("startup")
|
||||||
async def create_genshin_map():
|
async def create_genshin_map():
|
||||||
@ -89,15 +94,16 @@ async def get_map_response(
|
|||||||
return save_path
|
return save_path
|
||||||
|
|
||||||
maps = await request.get_maps(map_id)
|
maps = await request.get_maps(map_id)
|
||||||
labels = await request.get_labels(map_id)
|
trees = await request.get_labels(map_id)
|
||||||
|
|
||||||
# 请求资源ID
|
# 请求资源ID
|
||||||
resource_id = 0
|
resource_id = 0
|
||||||
for label in labels:
|
for tree in trees:
|
||||||
for child in label.children:
|
for label in tree.children:
|
||||||
if resource_name == child.name:
|
if resource_name == label.name:
|
||||||
resource_id = child.id
|
resource_id = label.id
|
||||||
resource_name = child.name
|
resource_name = label.name
|
||||||
|
icon = label.icon
|
||||||
break
|
break
|
||||||
|
|
||||||
if resource_id == 0:
|
if resource_id == 0:
|
||||||
@ -109,6 +115,7 @@ async def get_map_response(
|
|||||||
|
|
||||||
# 转换坐标
|
# 转换坐标
|
||||||
transmittable_converted = utils.convert_pos(transmittable, maps.detail.origin)
|
transmittable_converted = utils.convert_pos(transmittable, maps.detail.origin)
|
||||||
|
print(transmittable_converted)
|
||||||
|
|
||||||
# 进行最密点获取
|
# 进行最密点获取
|
||||||
if is_cluster:
|
if is_cluster:
|
||||||
@ -167,9 +174,20 @@ async def get_map_response(
|
|||||||
int(point.x) - int(lt_point.x),
|
int(point.x) - int(lt_point.x),
|
||||||
int(point.y) - int(lt_point.y),
|
int(point.y) - int(lt_point.y),
|
||||||
)
|
)
|
||||||
genshin_map.paste(
|
|
||||||
mark_quest, (point_trans[0] - 16, point_trans[1] - 16), mark_quest
|
icon_path = ICON_PATH / f"{resource_name}.png"
|
||||||
)
|
if not icon_path.exists():
|
||||||
|
await download_file(icon, icon_path)
|
||||||
|
icon_pic = Image.open(icon_path).resize((52, 52))
|
||||||
|
|
||||||
|
if point.z <= 3:
|
||||||
|
mark = Image.open(TEXT_PATH / f"mark_{point.z}.png")
|
||||||
|
else:
|
||||||
|
mark = Image.open(TEXT_PATH / f"mark_B.png")
|
||||||
|
|
||||||
|
mark.paste(icon_pic, (25, 17), icon_pic)
|
||||||
|
|
||||||
|
genshin_map.paste(mark, (point_trans[0] - 50, point_trans[1] - 100), mark)
|
||||||
|
|
||||||
# 转换RGB图
|
# 转换RGB图
|
||||||
genshin_map = genshin_map.convert("RGB")
|
genshin_map = genshin_map.convert("RGB")
|
||||||
@ -199,6 +217,7 @@ async def get_map_by_point(
|
|||||||
if resource_name == a or resource_name in resource_aliases[m][a]:
|
if resource_name == a or resource_name in resource_aliases[m][a]:
|
||||||
return a
|
return a
|
||||||
return resource_name
|
return resource_name
|
||||||
|
|
||||||
# 判断别名
|
# 判断别名
|
||||||
resource_name = resource_aliases_to_name(resource_name)
|
resource_name = resource_aliases_to_name(resource_name)
|
||||||
|
|
||||||
|
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_0.png
Normal file
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_1.png
Normal file
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_2.png
Normal file
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_3.png
Normal file
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_B.png
Normal file
BIN
fastapi_genshin_map/GetMapImage/texture2d/mark_B.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
Loading…
Reference in New Issue
Block a user