mirror of
https://github.com/PaiGramTeam/fastapi_genshin_map.git
synced 2024-11-21 21:58:08 +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/resource_data
|
||||
fastapi_genshin_map/GetMapImage/icon_data
|
||||
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)
|
||||
|
||||
## 丨返回图示例
|
||||
![测试.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 shapely.geometry import Point, Polygon
|
||||
|
||||
from .models import XYPoint
|
||||
from .models import XYPoint, XYZPoint
|
||||
|
||||
Pos = Tuple[float, float]
|
||||
Poses = List[XYPoint]
|
||||
@ -14,8 +14,8 @@ Points = List[Point]
|
||||
|
||||
|
||||
def k_means_points(
|
||||
points: List[XYPoint], length: int = 500, clusters: int = 3
|
||||
) -> List[Tuple[XYPoint, XYPoint, Poses]]:
|
||||
points: List[XYZPoint], length: int = 500, clusters: int = 3
|
||||
) -> List[Tuple[XYZPoint, XYZPoint, Poses]]:
|
||||
"""
|
||||
通过 K-Means 获取集群坐标列表
|
||||
|
||||
|
@ -59,6 +59,10 @@ class Point(BaseModel):
|
||||
author_name: str
|
||||
ctime: str
|
||||
display_state: int
|
||||
area_id: int
|
||||
ext_attrs: str
|
||||
z_level: int
|
||||
icon_sign: int
|
||||
|
||||
|
||||
class Slice(BaseModel):
|
||||
@ -100,6 +104,12 @@ class XYPoint(NamedTuple):
|
||||
y: float
|
||||
|
||||
|
||||
class XYZPoint(NamedTuple):
|
||||
x: float
|
||||
y: float
|
||||
z: int
|
||||
|
||||
|
||||
class Kind(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
|
@ -8,7 +8,7 @@ from asyncio import gather, create_task
|
||||
from PIL import Image
|
||||
from httpx import AsyncClient
|
||||
|
||||
from .models import Maps, Point, XYPoint
|
||||
from .models import Maps, Point, XYPoint, XYZPoint
|
||||
|
||||
CLIENT = AsyncClient()
|
||||
|
||||
@ -76,7 +76,7 @@ async def get_map_by_pos(
|
||||
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 获取坐标点
|
||||
|
||||
@ -91,13 +91,13 @@ def get_points_by_id(id_: int, points: List[Point]) -> List[XYPoint]:
|
||||
`list[XYPoint]`
|
||||
"""
|
||||
return [
|
||||
XYPoint(point.x_pos, point.y_pos)
|
||||
XYZPoint(point.x_pos, point.y_pos, point.z_level)
|
||||
for point in points
|
||||
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)
|
||||
[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(
|
||||
|
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 .logger import logger
|
||||
from .download import download_file
|
||||
|
||||
Image.MAX_IMAGE_PIXELS = 333120000
|
||||
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))
|
||||
MAP = Path(__file__).parent / "map_data"
|
||||
RESOURCE_PATH = Path(__file__).parent / "resource_data"
|
||||
ICON_PATH = Path(__file__).parent / "icon_data"
|
||||
CHASM_PATH = MAP / "chasm.png"
|
||||
ENKANOMIYA_PATH = MAP / "enkanomiya.png"
|
||||
TEYVAT_PATH = MAP / "teyvat.png"
|
||||
@ -30,6 +32,9 @@ MAP_ID_DICT = {
|
||||
# MapID.golden_apple_archipelago, # 金苹果群岛
|
||||
}
|
||||
|
||||
if not ICON_PATH.exists():
|
||||
ICON_PATH.mkdir(exist_ok=True)
|
||||
|
||||
|
||||
@router.on_event("startup")
|
||||
async def create_genshin_map():
|
||||
@ -89,15 +94,16 @@ async def get_map_response(
|
||||
return save_path
|
||||
|
||||
maps = await request.get_maps(map_id)
|
||||
labels = await request.get_labels(map_id)
|
||||
trees = await request.get_labels(map_id)
|
||||
|
||||
# 请求资源ID
|
||||
resource_id = 0
|
||||
for label in labels:
|
||||
for child in label.children:
|
||||
if resource_name == child.name:
|
||||
resource_id = child.id
|
||||
resource_name = child.name
|
||||
for tree in trees:
|
||||
for label in tree.children:
|
||||
if resource_name == label.name:
|
||||
resource_id = label.id
|
||||
resource_name = label.name
|
||||
icon = label.icon
|
||||
break
|
||||
|
||||
if resource_id == 0:
|
||||
@ -109,6 +115,7 @@ async def get_map_response(
|
||||
|
||||
# 转换坐标
|
||||
transmittable_converted = utils.convert_pos(transmittable, maps.detail.origin)
|
||||
print(transmittable_converted)
|
||||
|
||||
# 进行最密点获取
|
||||
if is_cluster:
|
||||
@ -167,9 +174,20 @@ async def get_map_response(
|
||||
int(point.x) - int(lt_point.x),
|
||||
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图
|
||||
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]:
|
||||
return a
|
||||
return 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