2026-01-19 09:36:22 +08:00
|
|
|
|
# slope_aspect_img13
|
2026-01-14 11:37:35 +08:00
|
|
|
|
import numpy as np
|
|
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
|
|
from scipy.ndimage import sobel
|
|
|
|
|
|
import matplotlib as mpl
|
|
|
|
|
|
import rasterio
|
|
|
|
|
|
from osgeo import gdal
|
|
|
|
|
|
from matplotlib.patches import FancyArrowPatch
|
|
|
|
|
|
from mpl_toolkits.mplot3d import proj3d
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
# 自定义3D箭头类
|
|
|
|
|
|
class Arrow3D(FancyArrowPatch):
|
|
|
|
|
|
def __init__(self, xs, ys, zs, *args, **kwargs):
|
|
|
|
|
|
super().__init__((0,0), (0,0), *args, **kwargs)
|
|
|
|
|
|
self._verts3d = xs, ys, zs
|
|
|
|
|
|
|
|
|
|
|
|
def do_3d_projection(self, renderer=None):
|
|
|
|
|
|
xs3d, ys3d, zs3d = self._verts3d
|
|
|
|
|
|
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
|
|
|
|
|
|
self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
|
|
|
|
|
|
return min(zs)
|
|
|
|
|
|
|
|
|
|
|
|
def read_dem_rasterio(filepath):
|
|
|
|
|
|
"""使用rasterio读取DEM数据"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
with rasterio.open(filepath) as src:
|
|
|
|
|
|
dem_data = src.read(1)
|
|
|
|
|
|
transform = src.transform
|
|
|
|
|
|
bounds = src.bounds
|
|
|
|
|
|
crs = src.crs
|
|
|
|
|
|
|
|
|
|
|
|
print(f"DEM信息:")
|
|
|
|
|
|
print(f" 尺寸: {dem_data.shape}")
|
|
|
|
|
|
print(f" 范围: {bounds}")
|
|
|
|
|
|
print(f" 坐标系: {crs}")
|
|
|
|
|
|
print(f" 高程范围: {np.nanmin(dem_data):.2f} - {np.nanmax(dem_data):.2f}")
|
|
|
|
|
|
|
|
|
|
|
|
if np.isnan(dem_data).any():
|
|
|
|
|
|
print(" 检测到NaN值")
|
|
|
|
|
|
dem_data = np.nan_to_num(dem_data, nan=np.nanmean(dem_data))
|
|
|
|
|
|
|
|
|
|
|
|
rows, cols = dem_data.shape
|
|
|
|
|
|
x = np.linspace(bounds.left, bounds.right, cols)
|
|
|
|
|
|
y = np.linspace(bounds.bottom, bounds.top, rows)
|
|
|
|
|
|
X, Y = np.meshgrid(x, y)
|
|
|
|
|
|
|
|
|
|
|
|
return X, Y, dem_data
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"使用rasterio读取失败: {e}")
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def read_slope_aspect_by_dem(dem_path, overall_3d_output_path=None) :
|
|
|
|
|
|
# ---------------------- 核心:解决中文乱码配置 ----------------------
|
|
|
|
|
|
setup_chinese_font()
|
|
|
|
|
|
|
|
|
|
|
|
# 尝试读取DEM数据
|
|
|
|
|
|
print("正在读取DEM文件...")
|
|
|
|
|
|
X, Y, Z = read_dem_rasterio(dem_path)
|
|
|
|
|
|
|
|
|
|
|
|
if X is None:
|
|
|
|
|
|
raise FileNotFoundError(f"无法读取DEM文件: {dem_path}")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查数据有效性
|
|
|
|
|
|
if Z.size == 0 or np.all(Z == 0):
|
|
|
|
|
|
raise ValueError("DEM数据无效或全部为0")
|
|
|
|
|
|
|
|
|
|
|
|
# 重采样
|
|
|
|
|
|
if Z.shape[0] > 200 or Z.shape[1] > 200:
|
|
|
|
|
|
print(f"原始DEM尺寸较大 ({Z.shape}),进行重采样...")
|
|
|
|
|
|
from scipy.ndimage import zoom
|
|
|
|
|
|
scale_factor = min(200/Z.shape[0], 200/Z.shape[1])
|
|
|
|
|
|
Z = zoom(Z, scale_factor, order=1)
|
|
|
|
|
|
X = zoom(X, scale_factor, order=1)
|
|
|
|
|
|
Y = zoom(Y, scale_factor, order=1)
|
|
|
|
|
|
print(f"重采样后尺寸: {Z.shape}")
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 2. 计算坡度和坡向 ----------------------
|
|
|
|
|
|
print("计算坡度和坡向...")
|
|
|
|
|
|
|
|
|
|
|
|
dx_pixel = np.abs(X[0,1] - X[0,0]) * 111000
|
|
|
|
|
|
dy_pixel = np.abs(Y[1,0] - Y[0,0]) * 111000
|
|
|
|
|
|
|
|
|
|
|
|
dx = sobel(Z, axis=1) / (2 * dx_pixel)
|
|
|
|
|
|
dy = sobel(Z, axis=0) / (2 * dy_pixel)
|
|
|
|
|
|
|
|
|
|
|
|
slope_rad = np.arctan(np.sqrt(dx**2 + dy**2))
|
|
|
|
|
|
slope_deg = slope_rad * (180 / np.pi)
|
|
|
|
|
|
|
|
|
|
|
|
aspect_rad = np.arctan2(-dx, dy)
|
|
|
|
|
|
aspect_deg = aspect_rad * (180 / np.pi)
|
|
|
|
|
|
aspect_deg[aspect_deg < 0] += 360
|
|
|
|
|
|
|
|
|
|
|
|
print(f"坡度范围: {np.min(slope_deg):.2f}° - {np.max(slope_deg):.2f}°")
|
|
|
|
|
|
print(f"坡向范围: {np.min(aspect_deg):.2f}° - {np.max(aspect_deg):.2f}°")
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 3. 计算整体坡向 ----------------------
|
|
|
|
|
|
print("\n计算整体坡向...")
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_overall_aspect(aspect_deg, slope_deg, method='weighted_mean'):
|
|
|
|
|
|
"""计算整体坡向"""
|
|
|
|
|
|
aspect_rad = np.deg2rad(aspect_deg)
|
|
|
|
|
|
|
|
|
|
|
|
if method == 'weighted_mean':
|
|
|
|
|
|
# 坡度加权平均法
|
|
|
|
|
|
u = np.sin(aspect_rad)
|
|
|
|
|
|
v = np.cos(aspect_rad)
|
|
|
|
|
|
|
|
|
|
|
|
weights = slope_deg.flatten()
|
|
|
|
|
|
weighted_u = np.nansum(u.flatten() * weights) / np.nansum(weights)
|
|
|
|
|
|
weighted_v = np.nansum(v.flatten() * weights) / np.nansum(weights)
|
|
|
|
|
|
|
|
|
|
|
|
weighted_aspect_rad = np.arctan2(weighted_u, weighted_v)
|
|
|
|
|
|
weighted_aspect_deg = np.rad2deg(weighted_aspect_rad)
|
|
|
|
|
|
|
|
|
|
|
|
if weighted_aspect_deg < 0:
|
|
|
|
|
|
weighted_aspect_deg += 360
|
|
|
|
|
|
|
|
|
|
|
|
weighted_strength = np.sqrt(weighted_u**2 + weighted_v**2)
|
|
|
|
|
|
return weighted_aspect_deg, weighted_strength, "坡度加权平均法"
|
|
|
|
|
|
|
|
|
|
|
|
elif method == 'vector_mean':
|
|
|
|
|
|
# 向量平均法
|
|
|
|
|
|
u = np.sin(aspect_rad)
|
|
|
|
|
|
v = np.cos(aspect_rad)
|
|
|
|
|
|
|
|
|
|
|
|
mean_u = np.nanmean(u)
|
|
|
|
|
|
mean_v = np.nanmean(v)
|
|
|
|
|
|
|
|
|
|
|
|
mean_aspect_rad = np.arctan2(mean_u, mean_v)
|
|
|
|
|
|
mean_aspect_deg = np.rad2deg(mean_aspect_rad)
|
|
|
|
|
|
|
|
|
|
|
|
if mean_aspect_deg < 0:
|
|
|
|
|
|
mean_aspect_deg += 360
|
|
|
|
|
|
|
|
|
|
|
|
vector_strength = np.sqrt(mean_u**2 + mean_v**2)
|
|
|
|
|
|
return mean_aspect_deg, vector_strength, "向量平均法"
|
|
|
|
|
|
|
|
|
|
|
|
# 使用坡度加权平均法计算整体坡向
|
|
|
|
|
|
overall_aspect, overall_strength, method_name = calculate_overall_aspect(aspect_deg, slope_deg, 'weighted_mean')
|
|
|
|
|
|
|
|
|
|
|
|
# 将整体坡向转换为方向描述
|
|
|
|
|
|
if overall_aspect < 22.5 or overall_aspect >= 337.5:
|
|
|
|
|
|
overall_direction = "北"
|
|
|
|
|
|
elif 22.5 <= overall_aspect < 67.5:
|
|
|
|
|
|
overall_direction = "东北"
|
|
|
|
|
|
elif 67.5 <= overall_aspect < 112.5:
|
|
|
|
|
|
overall_direction = "东"
|
|
|
|
|
|
elif 112.5 <= overall_aspect < 157.5:
|
|
|
|
|
|
overall_direction = "东南"
|
|
|
|
|
|
elif 157.5 <= overall_aspect < 202.5:
|
|
|
|
|
|
overall_direction = "南"
|
|
|
|
|
|
elif 202.5 <= overall_aspect < 247.5:
|
|
|
|
|
|
overall_direction = "西南"
|
|
|
|
|
|
elif 247.5 <= overall_aspect < 292.5:
|
|
|
|
|
|
overall_direction = "西"
|
|
|
|
|
|
else:
|
|
|
|
|
|
overall_direction = "西北"
|
|
|
|
|
|
|
|
|
|
|
|
print(f"整体坡向 ({method_name}):")
|
|
|
|
|
|
print(f" 角度: {overall_aspect:.1f}°")
|
|
|
|
|
|
print(f" 方向: {overall_direction}")
|
|
|
|
|
|
# print(f" 一致性: {overall_strength:.3f}")
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 5. 3D可视化(俯视图,包含整体坡向和关键点坡向) ----------------------
|
|
|
|
|
|
print("\n生成3D俯视图可视化...")
|
|
|
|
|
|
fig3d, ax3d = plt.subplots(figsize=(16, 12), subplot_kw={"projection": "3d"})
|
|
|
|
|
|
|
|
|
|
|
|
# 绘制地形曲面 - 俯视图需要更清晰的地形表现
|
|
|
|
|
|
norm = mpl.colors.Normalize(vmin=np.percentile(slope_deg, 5),
|
|
|
|
|
|
vmax=np.percentile(slope_deg, 95))
|
|
|
|
|
|
|
|
|
|
|
|
plot_skip = max(2, Z.shape[0] // 60) # 增加采样密度,使俯视图更清晰
|
|
|
|
|
|
X_plot = X[::plot_skip, ::plot_skip]
|
|
|
|
|
|
Y_plot = Y[::plot_skip, ::plot_skip]
|
|
|
|
|
|
Z_plot = Z[::plot_skip, ::plot_skip]
|
|
|
|
|
|
slope_plot = slope_deg[::plot_skip, ::plot_skip]
|
|
|
|
|
|
|
|
|
|
|
|
surf = ax3d.plot_surface(
|
|
|
|
|
|
X_plot, Y_plot, Z_plot,
|
|
|
|
|
|
cmap="viridis_r",
|
|
|
|
|
|
alpha=0.85, # 增加透明度,使箭头更明显
|
|
|
|
|
|
linewidth=0.1, # 很细的网格线
|
|
|
|
|
|
facecolors=plt.cm.viridis_r(norm(slope_plot)),
|
|
|
|
|
|
zorder=1
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 绘制整体坡向箭头(中心位置,红色粗箭头) ----------------------
|
|
|
|
|
|
center_x = (X.min() + X.max()) / 2
|
|
|
|
|
|
center_y = (Y.min() + Y.max()) / 2
|
|
|
|
|
|
|
|
|
|
|
|
# 整体坡向箭头长度
|
|
|
|
|
|
arrow_length_overall = 0.15 * min(X.max()-X.min(), Y.max()-Y.min())
|
|
|
|
|
|
|
|
|
|
|
|
# 计算整体坡向箭头方向
|
|
|
|
|
|
scale_factor = 1.5
|
|
|
|
|
|
overall_aspect_rad = np.deg2rad(overall_aspect)
|
|
|
|
|
|
dx_overall = np.sin(overall_aspect_rad) * arrow_length_overall * scale_factor
|
|
|
|
|
|
dy_overall = np.cos(overall_aspect_rad) * arrow_length_overall * scale_factor
|
|
|
|
|
|
|
|
|
|
|
|
# 方案2:如果希望箭头在地形上方一定高度
|
|
|
|
|
|
terrain_max_z = Z.max() # 地形最高点
|
|
|
|
|
|
float_height = 0.2 * terrain_max_z # 在地形最高点上方20%的高度
|
|
|
|
|
|
|
|
|
|
|
|
# 绘制整体坡向箭头(红色,粗)
|
|
|
|
|
|
arrow_overall = Arrow3D(
|
|
|
|
|
|
[center_x, center_x + dx_overall],
|
|
|
|
|
|
[center_y, center_y + dy_overall],
|
|
|
|
|
|
[terrain_max_z + float_height, terrain_max_z + float_height], # 在地形上方
|
|
|
|
|
|
mutation_scale=25, # 稍大一些的箭头
|
|
|
|
|
|
lw=5, # 更粗的线
|
|
|
|
|
|
arrowstyle='-|>',
|
|
|
|
|
|
color='red',
|
|
|
|
|
|
alpha=0.98, # 更高的透明度
|
|
|
|
|
|
zorder=20 # 更高的绘制顺序
|
|
|
|
|
|
)
|
|
|
|
|
|
ax3d.add_artist(arrow_overall)
|
|
|
|
|
|
|
|
|
|
|
|
# 在整体坡向箭头起点添加标记
|
|
|
|
|
|
ax3d.scatter(center_x, center_y, terrain_max_z + float_height,
|
|
|
|
|
|
color='red', s=120, edgecolor='white', linewidth=2, zorder=21)
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 整体坡向面板放置在左上角 ----------------------
|
|
|
|
|
|
# 计算左上角位置
|
|
|
|
|
|
panel_x = X.min() + 0.02 * (X.max() - X.min()) # 左边留2%的边距
|
|
|
|
|
|
panel_y = Y.max() - 0.02 * (Y.max() - Y.min()) # 上边留2%的边距
|
|
|
|
|
|
panel_z = Z.max() + 0.5 * (Z.max() - Z.min()) # 进一步提高Z坐标,确保在视野内
|
|
|
|
|
|
|
|
|
|
|
|
# 整体坡向面板内容
|
|
|
|
|
|
overall_info = (
|
|
|
|
|
|
f"整体坡向分析\n"
|
|
|
|
|
|
f"角度: {overall_aspect:.1f}°\n"
|
|
|
|
|
|
f"方向: {overall_direction}"
|
|
|
|
|
|
# f"一致性: {overall_strength:.3f}"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 绘制整体坡向面板(左上角)
|
|
|
|
|
|
ax3d.text(panel_x, panel_y, panel_z,
|
|
|
|
|
|
overall_info,
|
|
|
|
|
|
fontsize=12, fontweight='bold',
|
|
|
|
|
|
bbox=dict(facecolor='white', alpha=0.5, boxstyle="round,pad=0.5",
|
|
|
|
|
|
edgecolor='red', linewidth=2.5),
|
|
|
|
|
|
ha='left', va='top', zorder=30)
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 设置3D图参数 ----------------------
|
|
|
|
|
|
ax3d.set_xlabel("经度 (X)", fontsize=12)
|
|
|
|
|
|
ax3d.set_ylabel("纬度 (Y)", fontsize=12)
|
|
|
|
|
|
ax3d.set_zlabel("高程 (m)", fontsize=12)
|
|
|
|
|
|
|
|
|
|
|
|
# 获取文件名用于标题
|
|
|
|
|
|
filename = os.path.basename(dem_path)
|
|
|
|
|
|
ax3d.set_title(f"DEM三维俯视图 - 坡向分析\n文件: {filename}",
|
|
|
|
|
|
fontsize=14, fontweight='bold', pad=20)
|
|
|
|
|
|
|
|
|
|
|
|
# 添加颜色条
|
|
|
|
|
|
cbar = plt.colorbar(
|
|
|
|
|
|
mpl.cm.ScalarMappable(norm=norm, cmap='viridis_r'),
|
|
|
|
|
|
ax=ax3d, shrink=0.6, aspect=25, pad=0.15
|
|
|
|
|
|
)
|
|
|
|
|
|
cbar.set_label("坡度 (°)", fontsize=12)
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 设置为俯视图(高仰角) ----------------------
|
|
|
|
|
|
view_elev = 85 # 接近90度的仰角,俯视效果
|
|
|
|
|
|
view_azim = overall_aspect + 180 # 从坡向的相反方向观看,可以看到坡面
|
|
|
|
|
|
|
|
|
|
|
|
# 确保方位角在0-360度范围内
|
|
|
|
|
|
view_azim = view_azim % 360
|
|
|
|
|
|
|
|
|
|
|
|
print(f"\n设置3D俯视图视角:")
|
|
|
|
|
|
print(f" 整体坡向: {overall_aspect:.1f}° ({overall_direction})")
|
|
|
|
|
|
print(f" 视角方位角: {view_azim:.1f}°")
|
|
|
|
|
|
print(f" 视角仰角: {view_elev:.1f}°")
|
|
|
|
|
|
|
|
|
|
|
|
# 应用俯视图视角设置
|
|
|
|
|
|
ax3d.view_init(elev=view_elev, azim=view_azim)
|
|
|
|
|
|
|
|
|
|
|
|
# 调整相机距离,使视角更广
|
|
|
|
|
|
ax3d.dist = 9.0 # 增加相机距离
|
|
|
|
|
|
|
|
|
|
|
|
# 设置坐标轴范围,确保所有元素都显示
|
|
|
|
|
|
z_min, z_max = Z.min(), Z.max()
|
|
|
|
|
|
z_padding = 0.6 * (z_max - z_min) # 适当增加Z轴范围
|
|
|
|
|
|
ax3d.set_zlim(z_min - 0.1*z_padding, z_max + z_padding)
|
|
|
|
|
|
|
|
|
|
|
|
# 设置XY轴范围
|
|
|
|
|
|
x_margin = 0.1 * (X.max() - X.min())
|
|
|
|
|
|
y_margin = 0.1 * (Y.max() - Y.min())
|
|
|
|
|
|
ax3d.set_xlim(X.min() - x_margin, X.max() + x_margin)
|
|
|
|
|
|
ax3d.set_ylim(Y.min() - y_margin, Y.max() + y_margin)
|
|
|
|
|
|
|
|
|
|
|
|
plt.tight_layout()
|
|
|
|
|
|
|
|
|
|
|
|
# 保存图片
|
|
|
|
|
|
if not overall_3d_output_path :
|
|
|
|
|
|
overall_3d_output_path = dem_path.replace('.tif', '_slopeAspect_3D_overlook.png')
|
|
|
|
|
|
plt.savefig(overall_3d_output_path, dpi=250, bbox_inches='tight', facecolor='white')
|
|
|
|
|
|
# plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
os.remove(dem_path)
|
|
|
|
|
|
print(f"\n3D俯视图已保存: {overall_3d_output_path}")
|
|
|
|
|
|
print("分析完成!")
|
|
|
|
|
|
print("="*60)
|
|
|
|
|
|
|
|
|
|
|
|
return overall_3d_output_path
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------- 跨平台中文字体配置 ----------------------
|
|
|
|
|
|
def setup_chinese_font():
|
|
|
|
|
|
"""设置中文字体支持,兼容Windows、Linux、macOS"""
|
|
|
|
|
|
import platform
|
|
|
|
|
|
|
|
|
|
|
|
plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
|
|
|
|
|
|
|
|
|
|
|
|
system = platform.system()
|
|
|
|
|
|
|
|
|
|
|
|
# 尝试添加系统中文字体路径
|
|
|
|
|
|
font_paths = []
|
|
|
|
|
|
|
|
|
|
|
|
if system == 'Windows':
|
|
|
|
|
|
# Windows 字体路径
|
|
|
|
|
|
font_paths = [
|
|
|
|
|
|
'C:/Windows/Fonts/simhei.ttf', # 黑体
|
|
|
|
|
|
'C:/Windows/Fonts/simkai.ttf', # 楷体
|
|
|
|
|
|
'C:/Windows/Fonts/simsun.ttc', # 宋体
|
|
|
|
|
|
'C:/Windows/Fonts/microsoftyahei.ttf', # 微软雅黑
|
|
|
|
|
|
]
|
|
|
|
|
|
elif system == 'Darwin': # macOS
|
|
|
|
|
|
# macOS 字体路径
|
|
|
|
|
|
font_paths = [
|
|
|
|
|
|
'/System/Library/Fonts/PingFang.ttc', # 苹方
|
|
|
|
|
|
'/System/Library/Fonts/STHeiti Light.ttc', # 华文黑体
|
|
|
|
|
|
'/System/Library/Fonts/STHeiti Medium.ttc',
|
|
|
|
|
|
'/Library/Fonts/Arial Unicode.ttf', # Arial Unicode
|
|
|
|
|
|
]
|
|
|
|
|
|
elif system == 'Linux':
|
|
|
|
|
|
# Linux 字体路径
|
|
|
|
|
|
font_paths = [
|
|
|
|
|
|
'/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', # 文泉驿微米黑
|
|
|
|
|
|
'/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc', # 文泉驿正黑
|
|
|
|
|
|
'/usr/share/fonts/truetype/arphic/uming.ttc', # AR PL UMing
|
|
|
|
|
|
'/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc', # Noto
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
# 尝试找到并添加第一个可用的中文字体
|
|
|
|
|
|
font_added = False
|
|
|
|
|
|
for font_path in font_paths:
|
|
|
|
|
|
try:
|
|
|
|
|
|
if os.path.exists(font_path):
|
|
|
|
|
|
font_prop = mpl.font_manager.FontProperties(fname=font_path)
|
|
|
|
|
|
font_name = font_prop.get_name()
|
|
|
|
|
|
mpl.font_manager.fontManager.addfont(font_path)
|
|
|
|
|
|
plt.rcParams['font.sans-serif'] = [font_name] + plt.rcParams['font.sans-serif']
|
|
|
|
|
|
font_added = True
|
|
|
|
|
|
print(f"已添加中文字体: {font_name} ({font_path})")
|
|
|
|
|
|
break
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"添加字体 {font_path} 失败: {e}")
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
# 如果以上方法都失败,使用通用备选方案
|
|
|
|
|
|
if not font_added:
|
|
|
|
|
|
if system == 'Windows':
|
|
|
|
|
|
fallback_fonts = ['SimHei', 'Microsoft YaHei', 'KaiTi', 'FangSong']
|
|
|
|
|
|
elif system == 'Darwin':
|
|
|
|
|
|
fallback_fonts = ['PingFang SC', 'Hiragino Sans GB', 'Apple LiGothic Medium']
|
|
|
|
|
|
else: # Linux and others
|
|
|
|
|
|
fallback_fonts = ['DejaVu Sans', 'WenQuanYi Micro Hei',
|
|
|
|
|
|
'Noto Sans CJK SC', 'Heiti TC', 'AR PL UMing CN']
|
|
|
|
|
|
|
|
|
|
|
|
current_fonts = plt.rcParams.get('font.sans-serif', [])
|
|
|
|
|
|
plt.rcParams['font.sans-serif'] = fallback_fonts + current_fonts
|
|
|
|
|
|
print(f"使用备选字体方案: {fallback_fonts[:2]}...")
|
|
|
|
|
|
|
|
|
|
|
|
# 设置字体族
|
|
|
|
|
|
plt.rcParams['font.family'] = 'sans-serif'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
dem_path = r'D:\devForBdzlWork\ai_project_v1\b3dm\test\o_dem_df67f1cc.tif'
|
|
|
|
|
|
read_slope_aspect_by_dem(dem_path)
|