格式统一
This commit is contained in:
@ -164,6 +164,24 @@ class LogManager(QObject):
|
|||||||
if self._log_text is not None:
|
if self._log_text is not None:
|
||||||
self._log_text.clear()
|
self._log_text.clear()
|
||||||
|
|
||||||
|
def info(self, message: str):
|
||||||
|
"""便捷方法:发布 info 级别日志。"""
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': message, 'level': 'info',
|
||||||
|
})
|
||||||
|
|
||||||
|
def warning(self, message: str):
|
||||||
|
"""便捷方法:发布 warning 级别日志。"""
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': message, 'level': 'warning',
|
||||||
|
})
|
||||||
|
|
||||||
|
def error(self, message: str):
|
||||||
|
"""便捷方法:发布 error 级别日志。"""
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': message, 'level': 'error',
|
||||||
|
})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def progress_bar(self) -> QProgressBar:
|
def progress_bar(self) -> QProgressBar:
|
||||||
return self._progress_bar
|
return self._progress_bar
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QWidget, QTabWidget, QScrollArea, QSpinBox, QDoubleSpinBox, QComboBox
|
from PyQt5.QtWidgets import QWidget, QTabWidget, QScrollArea, QSpinBox, QDoubleSpinBox, QComboBox
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
@ -301,6 +302,16 @@ class PanelFactory:
|
|||||||
if not os.path.exists(absolute_path):
|
if not os.path.exists(absolute_path):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# ★ 2026-07-01 加强:若是目录,必须非空(至少含 1 个文件),
|
||||||
|
# 防止 PipelineContext 预创建的空目录(如 9_ML_Prediction)被当作有效产出广播
|
||||||
|
if os.path.isdir(absolute_path):
|
||||||
|
try:
|
||||||
|
has_content = any(True for _ in Path(absolute_path).iterdir())
|
||||||
|
except (OSError, PermissionError):
|
||||||
|
has_content = False
|
||||||
|
if not has_content:
|
||||||
|
continue
|
||||||
|
|
||||||
global_event_bus.publish('OutputUpdated', {
|
global_event_bus.publish('OutputUpdated', {
|
||||||
'step_id': dep_step,
|
'step_id': dep_step,
|
||||||
'output_type': output_type,
|
'output_type': output_type,
|
||||||
|
|||||||
@ -69,22 +69,72 @@ class Step11MapBatchThread(QThread):
|
|||||||
except Exception:
|
except Exception:
|
||||||
mpl_prev = None
|
mpl_prev = None
|
||||||
try:
|
try:
|
||||||
from src.core.steps.mapping_step import MappingStep
|
from src.postprocessing.map import ContentMapper
|
||||||
|
|
||||||
n = len(self.csv_paths)
|
n = len(self.csv_paths)
|
||||||
|
if n == 0:
|
||||||
|
self.finished_ok.emit(0)
|
||||||
|
return
|
||||||
|
|
||||||
|
boundary_shp = self.step10_kwargs.get('boundary_shp_path')
|
||||||
|
input_crs = self.step10_kwargs.get('input_crs', 'EPSG:32651')
|
||||||
|
output_crs = self.step10_kwargs.get('output_crs', input_crs)
|
||||||
|
resolution = float(self.step10_kwargs.get('resolution', 30))
|
||||||
|
|
||||||
|
# ── ★ 2026-07-01:QThread 内预计算共享空间上下文 ──
|
||||||
|
# 63 个 CSV 坐标一致,边界/网格/掩膜只算一次
|
||||||
|
mapper = ContentMapper(input_crs=input_crs, output_crs=output_crs)
|
||||||
|
shared_ctx = None
|
||||||
|
if n > 1 and boundary_shp:
|
||||||
|
try:
|
||||||
|
shared_ctx = mapper.prepare_shared_context(
|
||||||
|
sample_csv=self.csv_paths[0],
|
||||||
|
shp_file=boundary_shp,
|
||||||
|
resolution=resolution,
|
||||||
|
)
|
||||||
|
self.log_message.emit(
|
||||||
|
f"[共享上下文] 空间基准预计算完成,后续 {n} 个 CSV 复用", "info"
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self.log_message.emit(
|
||||||
|
f"[警告] 共享上下文失败: {e},回退逐个处理", "warning"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ── 批量处理 ──
|
||||||
for i, csv_p in enumerate(self.csv_paths):
|
for i, csv_p in enumerate(self.csv_paths):
|
||||||
if self._cancelled:
|
if self._cancelled:
|
||||||
self.log_message.emit("专题图批量任务已被用户取消", "warning")
|
self.log_message.emit("专题图批量任务已被用户取消", "warning")
|
||||||
break
|
break
|
||||||
self.progress.emit(i + 1, n)
|
self.progress.emit(i + 1, n)
|
||||||
self.log_message.emit(f"专题图 [{i + 1}/{n}] {csv_p}", "info")
|
self.log_message.emit(f"专题图 [{i + 1}/{n}] {csv_p}", "info")
|
||||||
kw = {**self.step10_kwargs, "prediction_csv_path": csv_p}
|
|
||||||
kw.pop("skip_dependency_check", None)
|
stem = Path(csv_p).stem
|
||||||
if self.output_dir_optional:
|
output_file = (
|
||||||
stem = Path(csv_p).stem
|
str(Path(self.output_dir_optional) / f'{stem}_distribution.png')
|
||||||
kw["output_image_path"] = str(Path(self.output_dir_optional) / f"{stem}_distribution.png")
|
if self.output_dir_optional
|
||||||
else:
|
else None
|
||||||
kw["output_image_path"] = None
|
)
|
||||||
MappingStep.generate_distribution_map(**kw)
|
# 已存在则跳过(兼容 tif 重定向后的文件名)
|
||||||
|
if output_file and (
|
||||||
|
Path(output_file).exists()
|
||||||
|
or Path(output_file).with_suffix('.tif').exists()
|
||||||
|
):
|
||||||
|
self.log_message.emit(f" → 跳过(已存在)", "info")
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
mapper.process_data(
|
||||||
|
csv_file=csv_p,
|
||||||
|
shp_file=boundary_shp,
|
||||||
|
output_file=output_file,
|
||||||
|
resolution=resolution,
|
||||||
|
output_format='tif',
|
||||||
|
shared_context=shared_ctx,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self.log_message.emit(f" → 失败: {e}", "error")
|
||||||
|
continue
|
||||||
|
|
||||||
self.finished_ok.emit(n)
|
self.finished_ok.emit(n)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.failed.emit(f"{e}\n{traceback.format_exc()}")
|
self.failed.emit(f"{e}\n{traceback.format_exc()}")
|
||||||
@ -534,6 +584,7 @@ class Step11MapPanel(QWidget):
|
|||||||
|
|
||||||
# ── 智能自动路由:预测 CSV 目录 ──
|
# ── 智能自动路由:预测 CSV 目录 ──
|
||||||
if self.work_dir:
|
if self.work_dir:
|
||||||
|
from src.gui.core.event_bus import global_event_bus
|
||||||
wd = self.work_dir
|
wd = self.work_dir
|
||||||
done = False
|
done = False
|
||||||
|
|
||||||
@ -542,10 +593,18 @@ class Step11MapPanel(QWidget):
|
|||||||
pred_dir = resolve_subdir(wd, cand_dir_key)
|
pred_dir = resolve_subdir(wd, cand_dir_key)
|
||||||
if pred_dir and os.path.isdir(pred_dir):
|
if pred_dir and os.path.isdir(pred_dir):
|
||||||
csvs = list(Path(pred_dir).glob("*.csv"))
|
csvs = list(Path(pred_dir).glob("*.csv"))
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': f'[Step11 自动路由] 检查 Step9 目录: {pred_dir} → CSV 数量: {len(csvs)}',
|
||||||
|
'level': 'info',
|
||||||
|
})
|
||||||
if csvs:
|
if csvs:
|
||||||
self.prediction_csv_dir_edit.setText(pred_dir)
|
self.prediction_csv_dir_edit.setText(pred_dir)
|
||||||
self.batch_mode_combo.setCurrentIndex(1)
|
self.batch_mode_combo.setCurrentIndex(1)
|
||||||
done = True
|
done = True
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': f'[Step11 自动路由] ✓ 使用 Step9 预测结果目录 ({len(csvs)} 个 CSV)',
|
||||||
|
'level': 'info',
|
||||||
|
})
|
||||||
break
|
break
|
||||||
|
|
||||||
# Priority 2 (Fallback): Step 10 水色指数输出目录
|
# Priority 2 (Fallback): Step 10 水色指数输出目录
|
||||||
@ -554,12 +613,26 @@ class Step11MapPanel(QWidget):
|
|||||||
wc_dir = resolve_subdir(wd, cand_dir_key)
|
wc_dir = resolve_subdir(wd, cand_dir_key)
|
||||||
if wc_dir and os.path.isdir(wc_dir):
|
if wc_dir and os.path.isdir(wc_dir):
|
||||||
csvs = list(Path(wc_dir).glob("*.csv"))
|
csvs = list(Path(wc_dir).glob("*.csv"))
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': f'[Step11 自动路由] 检查 Step10 目录: {wc_dir} → CSV 数量: {len(csvs)}',
|
||||||
|
'level': 'info',
|
||||||
|
})
|
||||||
if csvs:
|
if csvs:
|
||||||
self.prediction_csv_dir_edit.setText(wc_dir)
|
self.prediction_csv_dir_edit.setText(wc_dir)
|
||||||
self.batch_mode_combo.setCurrentIndex(1)
|
self.batch_mode_combo.setCurrentIndex(1)
|
||||||
done = True
|
done = True
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': f'[Step11 自动路由] ✓ 使用 Step10 水色指数目录 ({len(csvs)} 个 CSV)',
|
||||||
|
'level': 'info',
|
||||||
|
})
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if not done:
|
||||||
|
global_event_bus.publish('LogMessage', {
|
||||||
|
'message': '[Step11 自动路由] ⚠ 未找到任何有效 CSV 目录(Step9 和 Step10 均为空或不存在)',
|
||||||
|
'level': 'warning',
|
||||||
|
})
|
||||||
|
|
||||||
# GeoTIFF 目录:指向 step10 水色指数输出
|
# GeoTIFF 目录:指向 step10 水色指数输出
|
||||||
geotiff_dir = resolve_subdir(wd, 'watercolor')
|
geotiff_dir = resolve_subdir(wd, 'watercolor')
|
||||||
if geotiff_dir and os.path.isdir(geotiff_dir) and not self.geotiff_dir_edit.text().strip():
|
if geotiff_dir and os.path.isdir(geotiff_dir) and not self.geotiff_dir_edit.text().strip():
|
||||||
|
|||||||
@ -503,8 +503,21 @@ class WaterQualityGUI(QMainWindow):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 1. 触发懒加载生成面板
|
# 1. 触发懒加载生成面板
|
||||||
self._panel_factory.get_panel(item_data)
|
panel = self._panel_factory.get_panel(item_data)
|
||||||
|
|
||||||
|
# ★ 2026-07-01:每次切页时刷新面板的自动路由
|
||||||
|
# 面板首次加载时 _replay_state_to_panel 会调 update_from_config,
|
||||||
|
# 但再次切回时 get_panel() 直接返回已有实例,不会重扫文件系统。
|
||||||
|
# 此处显式调用确保 Step11 等面板始终基于最新磁盘状态做文件夹自动导入。
|
||||||
|
if panel is not None and hasattr(panel, 'update_from_config'):
|
||||||
|
try:
|
||||||
|
panel.update_from_config(
|
||||||
|
work_dir=self._workspace_initializer.work_dir,
|
||||||
|
pipeline=None,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 🚨 核心防卡死补丁:如果目标 Tab 被后台任务异常永久锁定,强制撬开!
|
# 🚨 核心防卡死补丁:如果目标 Tab 被后台任务异常永久锁定,强制撬开!
|
||||||
if not self._tab_widget.isTabEnabled(tab_index):
|
if not self._tab_widget.isTabEnabled(tab_index):
|
||||||
self._log_manager.info(f"检测到 {item_data} 处于异常锁定状态,已执行强制解锁。")
|
self._log_manager.info(f"检测到 {item_data} 处于异常锁定状态,已执行强制解锁。")
|
||||||
|
|||||||
@ -2761,12 +2761,85 @@ class ContentMapper:
|
|||||||
print(f" NoData={nodata_value}, 有效像元: {int(valid_mask.sum())}/{grid_content.size}")
|
print(f" NoData={nodata_value}, 有效像元: {int(valid_mask.sum())}/{grid_content.size}")
|
||||||
return output_tif_path
|
return output_tif_path
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# ★ 2026-07-01:共享空间上下文 — 63 个 CSV 只算一次网格/掩膜
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
def prepare_shared_context(self, sample_csv: str, shp_file=None,
|
||||||
|
resolution=100, expand_ratio=0.05):
|
||||||
|
"""从首个 CSV 预计算所有子进程共用的空间基准数据。
|
||||||
|
|
||||||
|
63 个水色指数 CSV 坐标完全一致,以下数据只算一次:
|
||||||
|
- boundary_gdf (水域边界)
|
||||||
|
- grid_xx, grid_yy (插值网格)
|
||||||
|
- mask (水域掩膜布尔矩阵)
|
||||||
|
- bounds (空间范围)
|
||||||
|
|
||||||
|
子进程直接从 shared_context 解包复用,跳过 ②③④⑥,直入 Kriging。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: (grid_xx, grid_yy, mask, bounds, boundary_gdf)
|
||||||
|
"""
|
||||||
|
print(f"[共享上下文] 从 {Path(sample_csv).name} 预计算空间基准...")
|
||||||
|
|
||||||
|
# ② 读边界(只此一次)
|
||||||
|
if shp_file is None:
|
||||||
|
boundary_gdf = None
|
||||||
|
else:
|
||||||
|
boundary_gdf = self.read_boundary_shapefile(shp_file)
|
||||||
|
|
||||||
|
# ③ 边缘外扩(只此一次)—— 需要读第一个CSV获取坐标结构
|
||||||
|
points_gdf = self.read_csv_data(sample_csv)
|
||||||
|
points_gdf = self._expand_edge_points(
|
||||||
|
points_gdf, boundary_gdf, resolution=resolution, expand_ratio=expand_ratio
|
||||||
|
)
|
||||||
|
|
||||||
|
# ④ 计算网格几何
|
||||||
|
if boundary_gdf is None:
|
||||||
|
pts = np.column_stack((points_gdf['proj_x'], points_gdf['proj_y']))
|
||||||
|
minx, maxx = pts[:, 0].min(), pts[:, 0].max()
|
||||||
|
miny, maxy = pts[:, 1].min(), pts[:, 1].max()
|
||||||
|
else:
|
||||||
|
bnd = boundary_gdf.total_bounds
|
||||||
|
minx, miny, maxx, maxy = bnd
|
||||||
|
|
||||||
|
width = maxx - minx
|
||||||
|
height = maxy - miny
|
||||||
|
minx -= width * expand_ratio
|
||||||
|
maxx += width * expand_ratio
|
||||||
|
miny -= height * expand_ratio
|
||||||
|
maxy += height * expand_ratio
|
||||||
|
|
||||||
|
res = resolution / 111000.0 if self.output_crs == 'EPSG:4326' else resolution
|
||||||
|
nx = max(int(width / res), 100)
|
||||||
|
ny = max(int(height / res), 100)
|
||||||
|
grid_x = np.linspace(minx, maxx, nx)
|
||||||
|
grid_y = np.linspace(miny, maxy, ny)
|
||||||
|
grid_xx, grid_yy = np.meshgrid(grid_x, grid_y)
|
||||||
|
bounds = np.array([minx, miny, maxx, maxy])
|
||||||
|
|
||||||
|
print(f"[共享上下文] 网格: {nx}×{ny} = {nx*ny} 点")
|
||||||
|
|
||||||
|
# ⑥ 水域掩膜布尔矩阵(只此一次)
|
||||||
|
mask = None
|
||||||
|
if boundary_gdf is not None:
|
||||||
|
mask_pts = np.column_stack((grid_xx.ravel(), grid_yy.ravel()))
|
||||||
|
mask_gdf = gpd.GeoDataFrame(
|
||||||
|
geometry=[Point(x, y) for x, y in mask_pts], crs=self.output_crs
|
||||||
|
)
|
||||||
|
mask = mask_gdf.within(boundary_gdf.unary_union).values.reshape(grid_xx.shape)
|
||||||
|
print(f"[共享上下文] 水域掩膜: {int(mask.sum())}/{mask.size} 点在水域内")
|
||||||
|
|
||||||
|
return (grid_xx, grid_yy, mask, bounds, boundary_gdf)
|
||||||
|
|
||||||
|
|
||||||
def process_data(self, csv_file, shp_file=None, output_file='content_map.png',
|
def process_data(self, csv_file, shp_file=None, output_file='content_map.png',
|
||||||
resolution=100, show_sample_points=False, base_map_tif=None,
|
resolution=100, show_sample_points=False, base_map_tif=None,
|
||||||
use_distance_diffusion=True, max_diffusion_distance=None,
|
use_distance_diffusion=True, max_diffusion_distance=None,
|
||||||
diffusion_power=2, diffusion_n_neighbors=15, cmap=None,
|
diffusion_power=2, diffusion_n_neighbors=15, cmap=None,
|
||||||
expand_ratio=0.05,
|
expand_ratio=0.05,
|
||||||
output_format='tif'):
|
output_format='tif',
|
||||||
|
shared_context=None):
|
||||||
"""
|
"""
|
||||||
主处理函数
|
主处理函数
|
||||||
|
|
||||||
@ -2778,56 +2851,72 @@ class ContentMapper:
|
|||||||
CSV文件路径
|
CSV文件路径
|
||||||
shp_file : str, optional
|
shp_file : str, optional
|
||||||
水域掩膜/边界文件路径(.shp / .dat / .bsq / .tif 等)。
|
水域掩膜/边界文件路径(.shp / .dat / .bsq / .tif 等)。
|
||||||
★★★ None 时跳过所有边界相关逻辑,插值仅基于采样点自然扩展 ★★★
|
shared_context : tuple, optional (2026-07-01 批量优化)
|
||||||
base_map_tif : str, optional
|
由 prepare_shared_context() 返回的 (grid_xx, grid_yy, mask, bounds, boundary_gdf)。
|
||||||
TIF正射底图文件路径。如果提供,将在水域掩膜外显示底图
|
提供时跳过 读边界/边缘外扩/建网格/算掩膜,直入 Kriging 插值阶段。
|
||||||
use_distance_diffusion : bool, default=True
|
... (其他参数同上)
|
||||||
是否使用距离扩散方法填充边界空白区域(shp_file=None 时无效)
|
|
||||||
max_diffusion_distance : float, optional
|
|
||||||
最大扩散距离(单位与坐标相同)。如果为None,自动计算为网格分辨率的5倍
|
|
||||||
diffusion_power : float, default=2
|
|
||||||
距离扩散的IDW幂参数,值越大,距离衰减越快
|
|
||||||
diffusion_n_neighbors : int, default=15
|
|
||||||
距离扩散使用的最近邻点数
|
|
||||||
cmap : str, optional
|
|
||||||
颜色映射。如果为None,将从CSV文件名或内容中自动识别参数并选择对应的colormap
|
|
||||||
expand_ratio : float, default=0.05
|
|
||||||
边界外扩比例(5%),用于从采样点范围外扩出图像边界
|
|
||||||
output_format : str, default='tif'
|
|
||||||
输出格式:'tif'(GeoTIFF)或 'png'(渲染图)
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 自动识别参数名称并获取colormap
|
# 自动识别参数名称并获取colormap
|
||||||
if cmap is None:
|
if cmap is None:
|
||||||
param_name = self._extract_param_name(csv_file)
|
param_name = self._extract_param_name(csv_file)
|
||||||
cmap = self._get_colormap(param_name)
|
cmap = self._get_colormap(param_name)
|
||||||
else:
|
|
||||||
print(f"使用指定的颜色映射: {cmap}")
|
|
||||||
|
|
||||||
# 读取采样点数据
|
# 读取采样点数据
|
||||||
points_gdf = self.read_csv_data(csv_file)
|
points_gdf = self.read_csv_data(csv_file)
|
||||||
|
|
||||||
# ── Plan C: shp_file=None 时跳过所有水域掩膜逻辑 ───────────
|
# ── ★ 快速通道:复用预计算的共享上下文 ──
|
||||||
if shp_file is None:
|
if shared_context is not None:
|
||||||
print("[Plan C] shp_file=None,跳过水域掩膜读取,插值不依赖边界约束")
|
grid_xx, grid_yy, mask, bounds, boundary_gdf = shared_context
|
||||||
boundary_gdf = None
|
# ③ 仍需边缘扩展(值相关),但跳过 ②④⑥
|
||||||
|
points_gdf = self._expand_edge_points(
|
||||||
|
points_gdf, boundary_gdf, resolution=resolution,
|
||||||
|
expand_ratio=expand_ratio
|
||||||
|
)
|
||||||
|
# ⑤ 直接用共享网格执行 Kriging
|
||||||
|
pts = np.column_stack((points_gdf['proj_x'], points_gdf['proj_y']))
|
||||||
|
vals = points_gdf['content'].values
|
||||||
|
grid_content = self._perform_interpolation(pts, vals, grid_xx, grid_yy)
|
||||||
|
# ⑥ 复用共享掩膜裁剪
|
||||||
|
if mask is not None:
|
||||||
|
grid_content[~mask] = np.nan
|
||||||
|
# 边界内 NaN 填充
|
||||||
|
nan_mask = np.isnan(grid_content)
|
||||||
|
within_nan = nan_mask & mask
|
||||||
|
if np.any(within_nan):
|
||||||
|
valid_m = ~nan_mask & mask
|
||||||
|
if np.sum(valid_m) > 0:
|
||||||
|
v_pts = np.column_stack((grid_xx[valid_m], grid_yy[valid_m]))
|
||||||
|
v_vals = grid_content[valid_m]
|
||||||
|
n_pts = np.column_stack((grid_xx[within_nan], grid_yy[within_nan]))
|
||||||
|
try:
|
||||||
|
from scipy.interpolate import griddata
|
||||||
|
grid_content[within_nan] = griddata(
|
||||||
|
v_pts, v_vals, n_pts, method='nearest'
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
grid_content[within_nan] = np.nanmean(grid_content[mask])
|
||||||
else:
|
else:
|
||||||
boundary_gdf = self.read_boundary_shapefile(shp_file)
|
# ── 原有完整流程(单图模式)──────────
|
||||||
|
if shp_file is None:
|
||||||
|
print("[Plan C] shp_file=None,跳过水域掩膜读取")
|
||||||
|
boundary_gdf = None
|
||||||
|
else:
|
||||||
|
boundary_gdf = self.read_boundary_shapefile(shp_file)
|
||||||
|
|
||||||
# 对边缘采样点进行外扩处理(boundary_gdf=None 时基于采样点自身范围外扩)
|
points_gdf = self._expand_edge_points(
|
||||||
points_gdf = self._expand_edge_points(
|
points_gdf, boundary_gdf, resolution=resolution,
|
||||||
points_gdf, boundary_gdf, resolution=resolution, expand_ratio=expand_ratio
|
expand_ratio=expand_ratio
|
||||||
)
|
)
|
||||||
|
|
||||||
# 创建插值网格(boundary_gdf=None 时纯采样点插值,无掩膜裁剪)
|
grid_xx, grid_yy, grid_content, bounds = self.create_interpolation_grid(
|
||||||
grid_xx, grid_yy, grid_content, bounds = self.create_interpolation_grid(
|
points_gdf, boundary_gdf, resolution,
|
||||||
points_gdf, boundary_gdf, resolution,
|
expand_ratio=expand_ratio,
|
||||||
expand_ratio=expand_ratio,
|
use_distance_diffusion=use_distance_diffusion,
|
||||||
use_distance_diffusion=use_distance_diffusion,
|
max_diffusion_distance=max_diffusion_distance,
|
||||||
max_diffusion_distance=max_diffusion_distance,
|
diffusion_power=diffusion_power,
|
||||||
diffusion_power=diffusion_power,
|
diffusion_n_neighbors=diffusion_n_neighbors
|
||||||
diffusion_n_neighbors=diffusion_n_neighbors
|
)
|
||||||
)
|
|
||||||
|
|
||||||
# ── 按 output_format 分发落盘方式 ───────────────────────────
|
# ── 按 output_format 分发落盘方式 ───────────────────────────
|
||||||
if output_format == 'tif':
|
if output_format == 'tif':
|
||||||
|
|||||||
Reference in New Issue
Block a user