VisPy教程:创建自定义可视化组件之物理尺寸测量

VisPy教程:创建自定义可视化组件之物理尺寸测量

vispy Main repository for Vispy vispy 项目地址: https://gitcode.com/gh_mirrors/vi/vispy

概述

本教程将深入讲解如何在VisPy中创建具有固定像素宽度边框的矩形可视化组件。这是VisPy可视化系统教程系列的第二部分,重点介绍如何处理不同坐标系之间的转换,确保可视化元素在不同缩放级别下保持精确的物理尺寸。

核心问题

在交互式可视化中,我们经常需要确保某些视觉元素(如边框、线条等)保持固定的像素宽度,无论用户如何缩放视图。这看似简单,但在实现上需要考虑多个坐标系的转换:

  1. 视觉坐标系(Visual):用户定义的逻辑坐标
  2. 文档坐标系(Document):与物理像素对应的坐标
  3. 帧缓冲区坐标系(Framebuffer):处理高DPI显示
  4. 渲染坐标系(Render):最终输出坐标

解决方案架构

顶点布局设计

为了实现矩形边框效果,我们采用10个顶点构成的三角形带(triangle_strip):

1--------------3
|              |
|   2------4   |     [注意点9和10与点1和2相同]
|   |      |   |
|   8------6   |
|              |
7--------------5

坐标系转换流程

  1. 首先将顶点从视觉坐标转换到文档坐标
  2. 在文档坐标空间调整边框宽度
  3. 最后转换到渲染坐标进行绘制

关键技术点

  • 使用visual_to_docdoc_to_render两个变换矩阵
  • 在文档坐标空间计算正确的边框偏移量
  • 处理非均匀缩放和旋转情况下的边框宽度校正

实现详解

顶点着色器关键逻辑

// 1. 转换到文档坐标
vec4 doc_pos = $visual_to_doc(vec4($position, 0, 1));

// 2. 计算调整方向向量
vec4 doc_x = $visual_to_doc(vec4($adjust_dir.x, 0, 0, 0)) - 
            $visual_to_doc(vec4(0, 0, 0, 0));
vec4 doc_y = $visual_to_doc(vec4(0, $adjust_dir.y, 0, 0)) - 
            $visual_to_doc(vec4(0, 0, 0, 0));

// 3. 归一化并计算当前权重
doc_x = normalize(doc_x);
doc_y = normalize(doc_y);
vec4 proj_y_x = dot(doc_x, doc_y) * doc_x;
float cur_width = length(doc_y - proj_y_x);

// 4. 调整顶点位置
adjusted = doc_pos + ($line_width / cur_width) * (doc_x + doc_y);

// 5. 最终转换到渲染坐标
gl_Position = $doc_to_render(adjusted);

Python类实现

class MyRectVisual(visuals.Visual):
    def __init__(self, x, y, w, h, weight=4.0):
        # 初始化顶点和调整方向缓冲区
        self.vert_buffer = gloo.VertexBuffer(...)
        self.adj_buffer = gloo.VertexBuffer(...)
        
        # 设置着色器变量
        self.shared_program.vert['position'] = self.vert_buffer
        self.shared_program.vert['adjust_dir'] = self.adj_buffer
        self.shared_program.vert['line_width'] = weight
        self.shared_program.frag['color'] = (1, 0, 0, 1)
        
    def _prepare_transforms(self, view):
        # 设置坐标变换
        tr = view.transforms
        view_vert = view.view_program.vert
        view_vert['visual_to_doc'] = tr.get_transform('visual', 'document')
        view_vert['doc_to_render'] = tr.get_transform('document', 'render')

实际应用

在场景图中测试我们的可视化组件:

canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()
view.camera = 'panzoom'

# 创建两个矩形,其中一个旋转25度
rects = [MyRect(100, 100, 200, 300, parent=view.scene),
         MyRect(500, 100, 200, 300, parent=view.scene)]
rects[1].transform = tr

关键知识点总结

  1. 坐标系理解:掌握VisPy的四层坐标系系统是开发高级可视化的基础
  2. 变换顺序:正确的变换顺序对保持视觉元素的物理特性至关重要
  3. 性能考量:在着色器中完成复杂计算比在CPU端处理更高效
  4. 通用性:这种技术可以推广到其他需要固定物理尺寸的可视化元素

扩展思考

读者可以尝试扩展这个示例:

  • 实现圆角矩形边框
  • 添加渐变填充效果
  • 支持虚线边框样式
  • 实现动态调整边框宽度

通过本教程,我们不仅实现了一个具体的可视化组件,更重要的是掌握了在VisPy中处理物理尺寸测量的通用方法,这为开发更复杂、更精确的可视化效果奠定了基础。

vispy Main repository for Vispy vispy 项目地址: https://gitcode.com/gh_mirrors/vi/vispy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白威东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值