八月 5

python VTK 笔记:几何的旋转和平移

在python vtk中,我们可以使用transform进行转换,也可以直接使用actor.SetUserMatrix方法对原几何进行旋转和平移

import vtk
import numpy as np

# create two cones, rotate one of them.

# create a rendering window and renderer
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
WIDTH = 640
HEIGHT = 480
renWin.SetSize(WIDTH, HEIGHT)

# create a renderwindowinteractor
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

# create cone
source = vtk.vtkConeSource()
source.SetResolution(60)
source.SetCenter(-2, 0, 0)

# create a transform that rotates the cone
transform = vtk.vtkTransform()

matrix = np.array([[1, 0, 0, 0],
                   [0, 1, 0, 0],
                   [0, 0, 1, 2],
                   [0, 0, 0, 1]])
obj_mat = vtk.vtkMatrix4x4()
for i in range(4):
    for j in range(4):
        obj_mat.SetElement(i, j, matrix[i, j])

transform.SetMatrix(obj_mat)
transformFilter = vtk.vtkTransformPolyDataFilter()
transformFilter.SetTransform(transform)
transformFilter.SetInputConnection(source.GetOutputPort())
transformFilter.Update()

# mapper for original cone
coneMapper1 = vtk.vtkPolyDataMapper()
coneMapper1.SetInputConnection(source.GetOutputPort())

# another mapper for the rotated cone
coneMapper2 = vtk.vtkPolyDataMapper()
coneMapper2.SetInputConnection(transformFilter.GetOutputPort())

matrix2 = np.array([[0, 1, 0, 0],
                   [1, 0, 0, 0],
                   [0, 0, 1, 0],
                   [0, 0, 0, 1]])
obj_mat2 = vtk.vtkMatrix4x4()
for i in range(4):
    for j in range(4):
        obj_mat2.SetElement(i, j, matrix2[i, j])
# actor for original cone
actor1 = vtk.vtkActor()

# 直接使用变换矩阵进行旋转和平移
actor1.SetUserMatrix(obj_mat2)
actor1.SetMapper(coneMapper1)

# actor for rotated cone
actor2 = vtk.vtkActor()
actor2.SetMapper(coneMapper2)

# color the original cone red
actor1.GetProperty().SetColor(1, 0, 0)  # (R,G,B)
# color rotated cone blue
actor2.GetProperty().SetColor(0, 0, 1)  # (R,G,B)

# assign actor to the renderer
ren.AddActor(actor1)
ren.AddActor(actor2)

# enable user interface interactor
iren.Initialize()
renWin.Render()
iren.Start()
八月 5

python VTK 笔记: vtkOrientationMarkerWidget 不显示的问题

值得注意的是,vtkOrientationMarkerWidget必须实例化给实例变量,换句话说

axes = vtk.vtkOrientationMarkerWidget() # 会导致不显示
self.axes = vtk.vtkOrientationMarkerWidget() # 会正常显示

一个完整的代码案例:

import sys
import vtk
from PySide2 import QtCore, QtWidgets
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.frame = QtWidgets.QFrame()
        self.vl = QtWidgets.QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)
        self.ren = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()

        # Create source
        source = vtk.vtkSphereSource()
        source.SetCenter(0, 0, 0)
        source.SetRadius(5.0)

        # Create a mapper
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(source.GetOutputPort())

        # Create an actor
        actor = vtk.vtkActor()
        actor.SetMapper(mapper)
        self.ren.AddActor(actor)

        # Add axes
        axesActor = vtk.vtkAxesActor()
        self.axes = vtk.vtkOrientationMarkerWidget()
        self.axes.SetOrientationMarker(axesActor)
        self.axes.SetInteractor(self.iren)
        self.axes.EnabledOn()
        self.axes.InteractiveOn()
        self.ren.ResetCamera()
        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)
        self.show()
        self.iren.Initialize()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())
八月 1

matplotlib教程:极坐标

import numpy as np
import matplotlib.pyplot as plt

r = np.arange(1, 6)
theta = [0, np.pi/2, np.pi, np.pi*3/2, np.pi*2]

fig = plt.figure()
# projection='polar',把轴定义为极坐标
ax = fig.add_subplot(111, projection='polar')
# 极坐标画图,参数为先角度后半径
ax.plot(theta, r, color='r', linewidth=3)

# 例2
r = np.ones(5) * 5
theta = [0, np.pi/2, np.pi, np.pi*3/2, np.pi*2]
ax.plot(theta, r, color='r', linewidth=3)

ax.grid(True)

fig.show()
八月 1

matplotlib教程:样式美化

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

fig = plt.figure()
# 打印matplotlib中所有的样式
print(plt.style.available)
# 设置style,其中ggplot是R语言中默认的样式
plt.style.use('ggplot')

x, y = np.random.normal(size=(2, 100))
ax1 = fig.add_subplot(221)
ax1.plot(x, y, 'o')

x = np.arange(0, 10)
y = np.arange(0, 10)
ax2 = fig.add_subplot(222)
# plt.rcParams['axes.prop_cycle']指的是画出图形的属性循环
ncolors = len(plt.rcParams['axes.prop_cycle'])
# 线与线之间在y轴方向上的间隔
shift = np.linspace(0, 10, ncolors)
for s in shift:
    ax2.plot(x, y+s)

x = np.arange(5)
y1, y2, y3 = np.random.randint(1, 25, size=(3,5))
ax3 = fig.add_subplot(223)
width = 0.25
ax3.bar(x, y1, width)
ax3.bar(x+width, y2, width)
ax3.bar(x+2*width, y3, width)

ax4 = fig.add_subplot(224)
for prop in plt.rcParams['axes.prop_cycle']:
    xy = np.random.normal(size=2)
    ax4.add_patch(mpatches.Circle(xy, radius=0.3, color=prop['color']))
ax4.axis('equal')

fig.show()
八月 1

matplotlib教程:形状

import numpy as np
import matplotlib.pyplot as plt
# 引入图形类
import matplotlib.patches as mpatches

fig = plt.figure()
ax = fig.add_subplot(111)

# 添加圆形
center = np.array([0.2, 0.2])
# 创建圆形图形。第一个参数为圆心,第二个参数为半径
circle = mpatches.Circle(center, 0.1)
# 将创建的圆形图形添加到轴上
ax.add_patch(circle)

# 添加长方形
bottom_left = np.array([0.2, 0.8])
# 创建长方形,第一个参数为左下角,第二个参数为宽度,第三个参数为高度
rect = mpatches.Rectangle(bottom_left, 0.2, 0.1, color='r')
# 将创建的长方形图形添加到轴上
ax.add_patch(rect)

# 添加多边形
poly_center = np.array([0.8, 0.2])
# 创建多边形,第一个参数为圆心,第二个参数为边数,第三个参数为半径
polygon = mpatches.RegularPolygon(poly_center, 5, 0.1, color='g')
# 将创建的多边形图形添加到轴上
ax.add_patch(polygon)

# 添加椭圆
oval_center = np.array([0.8, 0.8])
# 创建椭圆,第一个参数为椭圆中心,第二个参数为长直径,第三个参数为短直径。
# 注意和圆形不同,这里的参数都是直径,而不是半径!
oval = mpatches.Ellipse(oval_center, 0.4, 0.2, color='y')
# 将创建的椭圆图形添加到轴上
ax.add_patch(oval)

# 此时的圆形看起来像椭圆,这是因为坐标轴不相等。我们可以设置坐标轴相等
ax.axis('equal')

plt.show()
七月 31

matplotlib教程:区域填充

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 5*np.pi, 1000)

y1 = np.sin(x)
y2 = np.sin(2*x)

fig = plt.figure()
ax = fig.add_subplot(111)

# 一次性画多条曲线
ax.plot(x, y1, x, y2)

# # 使用fill方法填充曲线和x轴之间的区域
# ax.fill(x, y1, 'b', alpha=0.3)
# ax.fill(x, y2, 'r', alpha=0.3)

# 填充两条曲线之间的区域
# 注意这里的where表达式,表示填充的位置
# inteporlate 表示填充由于数值精度不够引起的未填充空白区域
ax.fill_between(x, y1, y2, where=y1>y2, facecolor='y', interpolate=True)
ax.fill_between(x, y1, y2, where=y1<y2, facecolor='g', interpolate=True)

fig.show()
七月 31

matplotlib教程:编辑数学公式

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

ax.set_xlim(1, 7)
ax.set_ylim(1, 5)

ax.text(2, 4, r'$ \alpha_i \beta_j \pi \lambda \omega $', size=25)
ax.text(4, 4, r'$ \sin(0)=\cos(\frac{\pi}{2}) $', size=25)
ax.text(2, 2, r'$ \lim_{x \rightarrow y} \frac{1}{x^3} $', size=25)
ax.text(4, 2, r'$ \sqrt[4]{x}=\sqrt{y} $', size=25)

fig.show()
七月 31

matplotlib教程:文字

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-10, 11)

y = x * x

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)

# 前两个参数为添加文字的坐标
# 第三个参数为要添加的文字
# family 字体
# size大小
# color 颜色
# style 样式:normal或italic
# weight 宽度 normal,bold,ultralight和ultrabold
# bbox 设置边框
ax.text(0, 40, 'function: y = x ^ 2',
        family='serif', size=20, color='b',
        style='italic', weight='heavy', bbox=dict(facecolor='r', alpha=0.2))
ax.text(0, 20, 'function: y = x ^ 2')

# 除了用plt.show(),也可以使用fig.show方法
fig.show()
七月 31

matplotlib教程:注释

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-10, 11)

y = x * x

fig = plt.figure()
ax = fig.add_subplot(111)

ax.plot(x, y)

# xy 元组,表示箭头尖的坐标
# xytext 表示文字的位置
# arrowprops 用于配置箭头的样式
## facecolor 箭头颜色
## headlength headwidth 箭头的长度和箭头的宽度
## width 箭尾的宽度
ax.annotate('this is the bottom', xy=(0, 0), xytext=(0, 20),
            arrowprops=dict(facecolor='r', headlength=10, headwidth=10, width=5))

# 设置ax的标题
ax.set_title('annotation example')
plt.show()
七月 31

matplotlib教程:双坐标轴

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(2, 20)
y1 = x * x
y2 = np.log(x)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(x, y1)
# 设置y轴的名称
ax1.set_ylabel('y1')

# 添加右侧坐标轴,对应的还有twiny方法
ax2 = ax1.twinx()
ax2.plot(x, y2, 'r')
ax2.set_ylabel('y2')

# 设置x轴名称
ax1.set_xlabel('compare y1 and y2')

plt.show()