使用python的第三方繪圖庫mayavi繪制不同尺寸的球


使用 python 的第三方繪圖庫 mayavi 繪制不同尺寸的球

“萬惡”的 mayavi 庫,琢磨了老半天,才弄清楚怎么根據球心坐標和半徑繪制出一個球。

解決方案

mayavi 的 mlab 類似 matplotlib 的 pyplot, 其中points3d函數用來繪制一些三維空間的離散點,在實際情況中,一個點必然需要一種“表示方式”,在points3d函數中,提供了"sphere", "point", "cylinder", "cone", "cube", "2darrow", "2dcircle"等很多模式,即用“球、點、圓柱、圓錐、方塊、二維箭頭、二維圓”等來表示一個點,當選擇"point"時,往往可能由於點的可視感太低而顯示出來的結果“啥都沒有”,所以此函數默認的圖例模式為"sphere"。由此引發感想,若可控制每個球的大小,那么不就可以用這些球來表示出自己想畫的一些球了嘛。

於是通過研究mlab.points3d()函數發現,可以傳入若干球的球心坐標對應的x,y,z,以及相應的半徑r,然后設置好scale_factorresolutionmode參數即可。這三個參數和r參數的說明如下:

  1. scale_factor:縮放因子,mayavi 的官方文檔說得很含糊,其到底怎么發揮作用的完全沒有說清楚,這里經過多次試驗總結為:將其設置為scale_factor=1的話,即會按傳入的“大小參數”r進行一比一縮放,這個參數可視為不存在。
  2. resolution:每一個點(球)的解析度/分辨率,為整數,默認值為 8,默認值為 8 時可明顯看出用球表示點時球有“棱角”,這里將其設置為 30。

    觀察這里的坐標,顯然,resolution參數還會一定程度上影響計算的精度吧,畢竟表面是計算后渲染出來的!咳,這點以后再說吧,目前只是需要繪制圖形效果。

  3. mode:其實可以不設置,默認情況即是用 sphere 作為點的的圖例,這里拿出來只是作為強調,應該設置為mode="sphere"
  4. r:按照官方文檔,嚴格來說這不是r參數,其形參名為s,但不管叫什么,它就是表示points3d函數繪制出來的點的大小的一個參數。這里經過多次試驗,發現它的數值表示的“大小含義”,對於mode="sphere"來說就是球的直徑,對於mode="cube"來說就是立方體的邊長,對於mode="cone"來說就是圓錐的高,對於mode="cylinder"來說就是圓柱的高。概括而言,在內部實現中,這種對應關系是否有統一理論指導其代碼實現尚不得而知。

於是,這樣繪制你的球:mlab.points3d(x, y, z, r*2, scale_factor=1, resolution=30)

示例

設置一個位於原點的單位球,然后在其上、下、左、右、前、后再各放置 1 個球,檢驗他們的相切情況。

import numpy as np
from mayavi import mlab


points = np.array([[0, 0, 0, 1],
                   [4, 0, 0, 3],
                   [-4, 0, 0, 3],
                   [0, 2, 0, 1],
                   [0, -2, 0, 1],
                   [0, 0, 2, 0.5],
                   [0, 0, -2, 0.5]])

x, y, z, r = points[:, 0], points[:, 1], points[:, 2], points[:, 3]

mlab.points3d(x, y, z, r*2, scale_factor=1, resolution=30, mode="sphere")
mlab.outline()
mlab.axes()
mlab.show()



附1:我本來想要畫的球堆積顆粒模型:

附2:原本我采用的繪球函數:

若要在一張圖上繪制很多球的話,這種方式只能使用for循環一個球一個球地進行繪制,效率比較低,硬件成本也比較高。也是為此一直在研究points3d函數的。

import random
import numpy as np


class Plotter:
    random.seed(3.14)

    @classmethod
    def randomColor(cls):
        color = (random.random(), random.random(), random.random())
        return color

    @classmethod
    def sphere(cls, center, radius, nPoints=100, opacity=1.0, color=None):
        """Draw a sphere according to given center and radius.

        Parameters:
        -----------
        center(tuple): (x, y, z) coordinate
        radius(float): radius of the sphere
        """
        u = np.linspace(0, 2 * np.pi, nPoints)
        v = np.linspace(0, np.pi, nPoints)
        x = radius * np.outer(np.cos(u), np.sin(v)) + center[0]
        y = radius * np.outer(np.sin(u), np.sin(v)) + center[1]
        z = radius * np.outer(np.ones(np.size(u)), np.cos(v)) + center[2]
        from mayavi import mlab
        color = cls.randomColor() if color is None else color
        scene = mlab.mesh(x, y, z, color=color, opacity=opacity)
        return scene

附3:mlab.points3d函數的官方文檔


mayavi.mlab.points3d(*args, **kwargs)

Plots glyphs (like points) at the position of the supplied data.

Function signatures:

points3d(x, y, z...)
points3d(x, y, z, s, ...)
points3d(x, y, z, f, ...)

x, y and z are numpy arrays, or lists, all of the same shape, giving the positions of the points.

If only 3 arrays x, y, z are given, all the points are drawn with the same size and color.

In addition, you can pass a fourth array s of the same shape as x, y, and z giving an associated scalar value for each point, or a function f(x, y, z) returning the scalar value. This scalar value can be used to modulate the color and the size of the points.

Keyword arguments:


color: the color of the vtk object. Overides the colormap, if any, when specified. This is specified as a triplet of float ranging from 0 to 1, eg (1, 1, 1) for white.
colormap: type of colormap to use.
extent: [xmin, xmax, ymin, ymax, zmin, zmax] Default is the x, y, z arrays extent. Use this to change the extent of the object created.
figure: Figure to populate.
line_width: The width of the lines, if any used. Must be a float. Default: 2.0
mask_points: If supplied, only one out of ‘mask_points’ data point is displayed. This option is useful to reduce the number of points displayed on large datasets Must be an integer or None.
mode: the mode of the glyphs. Must be ‘2darrow’ or ‘2dcircle’ or ‘2dcross’ or ‘2ddash’ or ‘2ddiamond’ or ‘2dhooked_arrow’ or ‘2dsquare’ or ‘2dthick_arrow’ or ‘2dthick_cross’ or ‘2dtriangle’ or ‘2dvertex’ or ‘arrow’ or ‘axes’ or ‘cone’ or ‘cube’ or ‘cylinder’ or ‘point’ or ‘sphere’. Default: sphere
name: the name of the vtk object created.
opacity: The overall opacity of the vtk object. Must be a float. Default: 1.0
reset_zoom: Reset the zoom to accomodate the data newly added to the scene. Defaults to True.
resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and phi. Must be an integer. Default: 8
scale_factor: The scaling applied to the glyphs. the size of the glyph is by default calculated from the inter-glyph spacing. Specify a float to give the maximum glyph size in drawing units
scale_mode: the scaling mode for the glyphs (‘vector’, ‘scalar’, or ‘none’).
transparent: make the opacity of the actor depend on the scalar.
vmax: vmax is used to scale the colormap. If None, the max of the data will be used
vmin: vmin is used to scale the colormap. If None, the min of the data will be used


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM