当前位置: 首页 > backend >正文

trame实现双视图(返场版)

话不多说直接上代码,库直接自己装,主播懒死了,记得替换成自己的shape文件

实现shp文件并排比对,也可以是更多的视图自己调整,拖动一个视图,另一个视图同步移动有待实现

"""
Shapefile多视图可视化
使用GeoPandas读取数据,VTK进行三角化处理,Trame实现多视图交互
两个视图分别展示不同的shp文件
"""from trame.app import get_server
from trame.widgets import vuetify, vtk as vtk_widgets
from trame.ui.vuetify import SinglePageLayoutimport geopandas as gpd  # 读取shp文件
import numpy as np
from vtkmodules.vtkCommonCore import vtkPoints
from vtkmodules.vtkCommonDataModel import vtkPolyData, vtkCellArray
from vtkmodules.vtkFiltersCore import vtkTriangleFilter  # 三角化后用这个读取器读取
from vtkmodules.vtkRenderingCore import (vtkRenderer,vtkRenderWindow,vtkRenderWindowInteractor,vtkPolyDataMapper,vtkActor,
)# VTK初始化
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch  # noqa
import vtkmodules.vtkRenderingOpenGL2  # noqa# -----------------------------------------------------------------------------
# Trame初始化
# -----------------------------------------------------------------------------server = get_server(client_type="vue2")
state, ctrl = server.state, server.controllerstate.trame__title = "双vtp视图对比"
state.layout_mode = "horizontal"  # 默认水平布局# -----------------------------------------------------------------------------
# 数据处理函数
# -----------------------------------------------------------------------------def shp_to_vtk_polygon(gdf):"""将GeoDataFrame转换为VTK多边形数据"""points = vtkPoints()polys = vtkCellArray()for geom in gdf.geometry:if geom.geom_type == 'Polygon':coords = np.array(geom.exterior.coords)elif geom.geom_type == 'MultiPolygon':coords = np.concatenate([np.array(p.exterior.coords) for p in geom.geoms])else:continuepoint_ids = []for coord in coords:point_ids.append(points.InsertNextPoint(coord[0], coord[1], 0))polys.InsertNextCell(len(point_ids), point_ids)poly_data = vtkPolyData()poly_data.SetPoints(points)poly_data.SetPolys(polys)return poly_datadef load_and_process_shapefile(file_path, z_scale=1.0):"""使用GeoPandas加载并处理Shapefile"""gdf = gpd.read_file(file_path)poly_data = shp_to_vtk_polygon(gdf)# 如果有Z坐标,可以在这里进行缩放points = poly_data.GetPoints()for i in range(points.GetNumberOfPoints()):x, y, z = points.GetPoint(i)points.SetPoint(i, x, y, z * z_scale)triangle_filter = vtkTriangleFilter()triangle_filter.SetInputData(poly_data)triangle_filter.PassLinesOn()triangle_filter.PassVertsOn()triangle_filter.Update()return triangle_filter.GetOutput()# -----------------------------------------------------------------------------
# 主程序
# -----------------------------------------------------------------------------# 读取和处理两个不同的Shapefile
SHAPEFILE_PATHS = [r"D:\Data\1\1.shp",  # 替换为第一个文件的实际路径r"D:\Data\1\1.shp",  # 替换为第二个文件的实际路径
]# 为每个文件创建不同的视图配置
VIEW_CONFIGS = [{"name": "Shapefile 1","background": (0.9, 0.9, 0.9),"color": (0.2, 0.4, 0.8),"file_path": SHAPEFILE_PATHS[0],"z_scale": 1.0},{"name": "Shapefile 2","background": (0.8, 0.9, 1.0),"color": (0.4, 0.2, 0.6),"file_path": SHAPEFILE_PATHS[1],"z_scale": 1.0},
]render_windows = []
html_views = []for config in VIEW_CONFIGS:# 处理数据processed_data = load_and_process_shapefile(config["file_path"], config["z_scale"])# 创建Mappermapper = vtkPolyDataMapper()mapper.SetInputData(processed_data)# 创建Actoractor = vtkActor()actor.SetMapper(mapper)actor.GetProperty().SetColor(config["color"])actor.GetProperty().SetLineWidth(1.5)# 创建渲染器和窗口renderer = vtkRenderer()renderer.SetBackground(config["background"])render_window = vtkRenderWindow()render_window.AddRenderer(renderer)render_window.SetWindowName(config["name"])# 设置交互方式render_window_interactor = vtkRenderWindowInteractor()render_window_interactor.SetRenderWindow(render_window)render_window_interactor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()# 添加Actor并初始化视图renderer.AddActor(actor)renderer.ResetCamera()render_windows.append(render_window)# -----------------------------------------------------------------------------
# Trame用户界面
# -----------------------------------------------------------------------------with SinglePageLayout(server) as layout:layout.icon.click = ctrl.reset_cameralayout.title.set_text("并排shp视图对比")with layout.toolbar:vuetify.VSpacer()vuetify.VDivider(vertical=True, classes="mx-2")with vuetify.VBtn(icon=True, click=ctrl.reset_all_views):vuetify.VIcon("mdi-camera-reset")vuetify.VDivider(vertical=True, classes="mx-2")with vuetify.VBtn(icon=True, click=ctrl.update_all_views):vuetify.VIcon("mdi-refresh")vuetify.VDivider(vertical=True, classes="mx-2")vuetify.VSelect(label="视图布局",items=[{"text": "水平布局", "value": "horizontal"},{"text": "垂直布局", "value": "vertical"},],v_model=("layout_mode",),dense=True,hide_details=True,style="max-width: 120px;",)with layout.content:# 使用条件渲染实现布局切换with vuetify.VContainer(fluid=True, classes="pa-0 fill-height"):# 水平布局with vuetify.VRow(v_if="layout_mode === 'horizontal'", classes="pa-0 ma-0 fill-height"):with vuetify.VCol(classes="pa-1 ma-0 fill-height"):view1 = vtk_widgets.VtkRemoteView(render_windows[0],ref="view1",interactive_ratio=1,style="height: 100%;",)html_views.append(view1)with vuetify.VCol(classes="pa-1 ma-0 fill-height"):view2 = vtk_widgets.VtkRemoteView(render_windows[1],ref="view2",interactive_ratio=1,style="height: 100%;",)html_views.append(view2)# 垂直布局with vuetify.VCol(v_if="layout_mode === 'vertical'", classes="pa-0 ma-0 fill-height"):with vuetify.VRow(classes="pa-1 ma-0", style="height: 50%;"):view1 = vtk_widgets.VtkRemoteView(render_windows[0],ref="view1",interactive_ratio=1,style="height: 100%;",)html_views.append(view1)with vuetify.VRow(classes="pa-1 ma-0", style="height: 50%;"):view2 = vtk_widgets.VtkRemoteView(render_windows[1],ref="view2",interactive_ratio=1,style="height: 100%;",)html_views.append(view2)# 定义控制函数def reset_all_views():for view in html_views:view.reset_camera()def update_all_views():for view in html_views:view.update()ctrl.reset_all_views = reset_all_viewsctrl.update_all_views = update_all_views# -----------------------------------------------------------------------------
# 启动应用
# -----------------------------------------------------------------------------if __name__ == "__main__":server.start(port=1234)

http://www.xdnf.cn/news/6027.html

相关文章:

  • MySQL 日期计算方法 date_sub()、date_add()、datediff() 详解-文中有示例帮助理解
  • java基础-泛型
  • tails os系统详解
  • 实物工厂零件画图案例(上)
  • 进程与线程:09 进程同步与信号量
  • Linux的域名解析服务器
  • OAuth安全架构深度剖析:协议机制与攻防实践
  • 【Nacos】env NACOS_AUTH_IDENTITY_KEY must be set.
  • SparkSQL 连接 MySQL 并添加新数据:实战指南
  • uniapp+vue3中自动导入ref等依赖
  • 通义灵码2.5版本全新体验
  • CSP-J普及组第一轮真题单选题专项训练(二)
  • NumPy 2.x 完全指南【九】常量
  • 虹科应用 | 探索PCAN卡与医疗机器人的革命性结合
  • 软件测试(2)软件测试分类及流程
  • 【自学30天掌握AI开发】 - 课程简介
  • Spring事务失效的全面剖析
  • C++:重载>>和<<(输入和输出运算符)
  • [FA1C4] 博客链接
  • OpenTiny icons——超轻量的CSS图标库,引领图标库新风向
  • Weblogic 反序列化远程命令执行漏洞 CVE-2019-2725 详解
  • Eaton XV-102-BE-35TQRC-10是伊顿(Eaton)公司推出的一款高性能触摸屏人机界面(HMI)
  • Python | Dashboard制作
  • 【报错解决】服务器重启后vscode远程连接失败
  • MySQL推荐书单:从入门到精通
  • 3545. 不同字符数量最多为 K 时的最少删除数
  • 【登录认证】JWT令牌
  • RDD-自定义分区器案例
  • 3541. 找到频率最高的元音和辅音
  • mysql8创建用户并赋权