mayavi_view.py 6.3 KB
Newer Older
M
march3 已提交
1
# -*- coding:utf-8 -*-
M
march3 已提交
2 3
# title           :Mayavi天体视图
# description     :Mayavi天体视图(天体效果展示用,需要安装 mayavi)
M
march3 已提交
4
# author          :Python超人
M
march3 已提交
5 6
# date            :2023-02-11
# link            :https://gitcode.net/pythoncr/
M
march3 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
# python_version  :3.8
# ==============================================================================
from mayavi import mlab
from tvtk.api import tvtk
import os
import matplotlib.pyplot as plt
from common.func import get_dominant_colors

from simulators.views.body_view import BodyView
import numpy as np


class MayaviView(BodyView):
    """
    Mayavi天体视图(天体效果展示用)
    """

    def update(self):
        """
        更新天体信息和数据,比如:更新天体的位置
        :return:
        """
        if hasattr(self.sphere, "mlab_source"):
M
march3 已提交
30 31 32 33 34 35
            # self.sphere.mlab_source.x 的位置是已经和 distance_scale 进行了相乘
            # body.position 是真实位置,所以需要和 distance_scale 相乘
            x_offset = self.body.position[0] * self.body.distance_scale - self.sphere.mlab_source.x
            y_offset = self.body.position[1] * self.body.distance_scale - self.sphere.mlab_source.y
            z_offset = self.body.position[2] * self.body.distance_scale - self.sphere.mlab_source.z
            # self.position 的位置是已经和 distance_scale 进行了相乘
M
march3 已提交
36 37
            self.sphere.mlab_source.set(x=self.position[0], y=self.position[1], z=self.position[2])

M
march3 已提交
38 39 40 41 42 43 44 45 46 47
            if hasattr(self, "rings"):
                if hasattr(self.rings, "mlab_source"):
                    if hasattr(self, "rings") and self.body.has_rings:
                        x = self.rings.mlab_source.x
                        y = self.rings.mlab_source.y
                        z = self.rings.mlab_source.z
                        x = x + x_offset[0]
                        y = y + y_offset[0]
                        z = z + z_offset[0]
                        self.rings.mlab_source.set(x=x, y=y, z=z)
M
march3 已提交
48 49 50 51 52 53

        # return x_offset[0], y_offset[0], z_offset[0]

    def build_rings(self):
        if not hasattr(self, "rings") or self.rings is None:

M
march3 已提交
54 55
            R = 2.2
            r = 0.5
M
march3 已提交
56 57 58 59 60 61
            rings_scale = 0.5e5
            resolution = 50
            theta = np.linspace(0, 2 * np.pi, resolution)
            phi = np.linspace(0, 2 * np.pi, resolution)
            torus = np.zeros((3, resolution, resolution))

M
march3 已提交
62
            # # body.position 是真实位置,所以需要和 distance_scale 相乘
M
march3 已提交
63 64 65
            for i in range(0, resolution):
                for j in range(0, resolution):  # size_scale=8.0e2
                    torus[0][i][j] = (R + r * np.cos(phi[j])) * np.cos(theta[i]) * \
M
march3 已提交
66 67 68
                                     self.body.size_scale * rings_scale + \
                                     self.body.position[0]  # * self.body.distance_scale

M
march3 已提交
69
                    torus[1][i][j] = (R + r * np.cos(phi[j])) * np.sin(theta[i]) * \
M
march3 已提交
70 71 72 73 74 75
                                     self.body.size_scale * rings_scale + \
                                     self.body.position[1]  # * self.body.distance_scale
                    # 带环的厚度
                    thicknesses_scale = self.body.raduis * 20
                    torus[2][i][j] = thicknesses_scale * np.sin(phi[j]) + \
                                     self.body.position[2]  # * self.body.distance_scale
M
march3 已提交
76 77 78 79 80 81 82 83 84 85 86 87
            rings_color = (173 / 255, 121 / 255, 92 / 255)
            if hasattr(self.body, "rings_color"):
                rings_color = tuple(np.array(self.body.rings_color) / 255)
            self.rings = mlab.mesh(torus[0], torus[1], torus[2], color=rings_color,
                                   representation='surface')
        return self.rings

    def appear(self):
        """
        天体显示的操作,比如:构建天体视图对象
        :return:
        """
三月三net's avatar
三月三net 已提交
88 89 90 91
        if hasattr(self.body, "torus_stars"):
            # 暂不支持环状小行星群
            return

M
march3 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
        if not hasattr(self, "sphere") or self.sphere is None:
            scale_factor = self.body.size_scale * self.body.diameter
            sphere = mlab.points3d(self.body.position[0], self.body.position[1], self.body.position[2],
                                   scale_factor=scale_factor,
                                   color=self.color,
                                   resolution=50,
                                   opacity=1,
                                   name=self.body.name)
            # # 调整镜面反射参数
            sphere.actor.property.specular = 0.5  # 0.1
            sphere.actor.property.specular_power = 128
            # 设置背面剔除,以更好的显示透明效果
            sphere.actor.property.backface_culling = True
            # sphere.actor.property.lighting_ = 10
            sphere.actor.property.lighting = False
            sphere.scene.disable_render = False
            # sphere_earth.scene.disable_render = False

            sphere.scene.anti_aliasing_frames = 10
            # sphere_earth.scene.anti_aliasing_frames = 0
            self.sphere = sphere

M
march3 已提交
114 115 116
        if hasattr(self, "texture"):
            if self.texture is not None and self.texture != '':
                self.__set_texture(self.texture)
M
march3 已提交
117 118 119

        if self.body.has_rings:
            self.build_rings()
M
march3 已提交
120
            # return self.sphere, self.rings
M
march3 已提交
121

M
march3 已提交
122
        # return self.sphere,
M
march3 已提交
123

M
march3 已提交
124 125 126 127 128 129 130
    def disappear(self):
        if hasattr(self, "sphere"):
            self.sphere.visible = False

        if hasattr(self, "rings"):
            self.rings.visible = False

M
march3 已提交
131 132 133 134 135 136
    def __set_texture(self, image_file):
        """
        设置纹理图片到天体
        :param image_file:
        :return:
        """
三月三net's avatar
三月三net 已提交
137
        outfile = image_file.replace('.jpg', '_flipped.jpg').replace('.png', '_flipped.jpg')
M
march3 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
        if os.path.exists(outfile):
            image_file = outfile
        else:
            if not os.path.exists(image_file):
                return
            img = plt.imread(image_file)
            img = img[::-1, ...]
            plt.imsave(outfile, img)
            image_file = outfile

        img = tvtk.JPEGReader(file_name=image_file)
        texture = tvtk.Texture(input_connection=img.output_port, interpolate=0, repeat=0)
        self.sphere.actor.actor.texture = texture
        self.sphere.actor.tcoord_generator_mode = 'sphere'
        cylinder_mapper = self.sphere.actor.tcoord_generator
        cylinder_mapper.prevent_seam = 0