Web-учебник по курсу "Визуальная аналитика"

Иллюстративный материал к практическому заданию "Анализ физических данных" на примере варианта №1

Для работы с Python в Blender существует Python консоль для ввода команд. Данная консоль может быть вызвана с помощью комбинации shift+F4.

В данной консоли можно вводить команды в интерактивном и последовательном режиме. После ввода комманды, результат выполнения будет выведен сразу после окончания ввода команды.

Примечание: Перед выполнением задания, необходимо знать точный и полный путь до файла с данными.

Пример программы

# Считываем бибилиотеки относящиеся к маетматическим функциям и процедурам
import itertools
import math
# Очищаем пространственную сцену от объектов
for mesh in bpy.data.meshes:
    bpy.data.meshes.remove(mesh)

# Очищаем пространственную сцену от камер
for cam in bpy.data.cameras:
    bpy.data.cameras.remove(cam)

# Sourcing
data_file_path = "data/c20.txt" # Путь до файла с данными
data_array = []
with open(data_file_path) as data_file: # Считываем данные из файла
    for line in data_file:
        data_array.append([float(number) for number in line.split()])

# Filtering
filtered_data_array = data_array # Filtering пуст

# Mapping
sphere_radius = 0.1 # Задаем радиус сфер
minimal_distance = 1.5 # Задаем минимальное расстояние для цилиндров
sphere_material = bpy.data.materials.new(name="SphereMaterial") 
sphere_material.diffuse_color = [0.5, 0.9, 0.3, 1] # Задаем цвет сфер
for point in filtered_data_array:
    # Создаем сферу
    bpy.ops.mesh.primitive_uv_sphere_add(radius=sphere_radius, location=point)
    sphere = bpy.context.object
    # Добавляем материал для сферы
    sphere.data.materials.append(sphere_material)

cylinder_radius = sphere_radius / 2 # Задаем радиус цилиндра
cylinder_material = bpy.data.materials.new(name="SphereMaterial")
cylinder_material.diffuse_color = [1, 1, 1, 1] # Задаем цвет цилиндров
for start, end in itertools.combinations(filtered_data_array, 2):
    # Считаем расстояние между точками
    distance = math.dist(start, end)
    if distance < minimal_distance:
        diff = [start[i] - end[i] for i in range(3)]
        middle = [(start[i] + end[i]) / 2 for i in range(3)]
        # Создаем цилиндр
        bpy.ops.mesh.primitive_cylinder_add(
            radius=cylinder_radius, depth=distance, location=middle
        )
        cylinder = bpy.context.object
        # Поварачиваем цилиндр
        cylinder.rotation_euler[1] = math.acos(diff[2] / distance)
        cylinder.rotation_euler[2] = math.atan2(diff[1], diff[0])
        cylinder.data.materials.append(cylinder_material)

# Rendering
camera_location = [5, 5, 5]
camera_target = [0, 0, 0]
# Задаем ветор для камеры
camera_view_vector = [camera_target[i] - camera_location[i] for i in range(3)]
# Создаем камеру
camera = bpy.data.objects.new("Camera", bpy.data.cameras.new("Camera"))
# Помещаем и поварачиваем камеру
camera.location = camera_location
camera.rotation_euler = Vector(camera_view_vector).to_track_quat('-Z', 'Y').to_euler()
# Помещаем камеру на сцену и выбираем её в качестве активной камеры
bpy.context.scene.collection.objects.link(camera)
bpy.context.scene.camera = camera
for area in bpy.context.screen.areas:
    if area.type == "VIEW_3D":
        area.spaces.active.region_3d.view_perspective = "CAMERA"
        break

Программа вводится и выполняется по частям.

Часть 1 Sourcing

Вводим текст отвечающий за Sourcing. Большая часть команд в Python не возвращает результатов, видимых в консоли.

Если ввести в консоли переменную, содержащую данные, то можно увидеть следующее:

>>> data_array
[[-1.219094, -0.6134905, 1.568064], [-1.219048, 0.7947012, 1.568227],
[0.1202303, 1.229807, 1.568158], [0.9479346, 0.09052898, 1.567944],
[0.1201712, -1.048725, 1.567888], [-1.818241, -1.048416, 0.3701912],
[-2.188474, 0.09094238, -0.369963], [-1.818136, 1.23007, 0.3704882],
[-0.8492718, -1.752463, -0.3703749], [0.3487037, -1.752652, 0.3698422],
[-0.8491096, 1.934269, -0.3698732], [0.3488672, 1.934088, 0.3703492],
[1.317876, 1.230073, -0.370188], [1.688112, 0.09069566, 0.3699504],
[1.317813, -1.048485, -0.3704498], [-1.448331, 0.091057, -1.567983],
[-0.6205603, 1.230299, -1.567894], [0.7187238, 0.7951232, -1.568042],
[0.7187231, -0.6130653, -1.568167], [-0.620568, -1.048182, -1.568168]]

Что означает что данные были успешно считаны из файла

Часть 2 Filtering

Постольку поскольку filtering пуст, данная часть не меняет данные. Если ввести в консоли переменную, отвечающую за отфильтрованные данные, чтобы убедится что ничего не изменилось:

>>> filtered_data_array
[[-1.219094, -0.6134905, 1.568064], [-1.219048, 0.7947012, 1.568227],
[0.1202303, 1.229807, 1.568158], [0.9479346, 0.09052898, 1.567944],
[0.1201712, -1.048725, 1.567888], [-1.818241, -1.048416, 0.3701912],
[-2.188474, 0.09094238, -0.369963], [-1.818136, 1.23007, 0.3704882],
[-0.8492718, -1.752463, -0.3703749], [0.3487037, -1.752652, 0.3698422],
[-0.8491096, 1.934269, -0.3698732], [0.3488672, 1.934088, 0.3703492],
[1.317876, 1.230073, -0.370188], [1.688112, 0.09069566, 0.3699504],
[1.317813, -1.048485, -0.3704498], [-1.448331, 0.091057, -1.567983],
[-0.6205603, 1.230299, -1.567894], [0.7187238, 0.7951232, -1.568042],
[0.7187231, -0.6130653, -1.568167], [-0.620568, -1.048182, -1.568168]]

Часть 3 Mapping

Запускаем часть отвечаю за Mapping. После создания каждой сферы и каждого цилиндра, Blender выведет следующее сообщение в консоль: {'FINISHED'}

В окне отвечающем за пространственную сцену, мы видим текующее проекционное изображение пространстенной сцены с созданными сферами и цилиндрами.

Часть 4 Rendering

Запускаем часть отвечаю за Rendering. После задания и активации камеры, мы видим проекционное графическое изображение, полученное с помощью созданной нами камеры.

Часть 5 Backloop

Если аналитик хочет поменять цвет цилиндров, можно ввести следующую команду для изменения цвета цилиндров с белого на красный и сделать их слегка прозрачными: cylinder_material.diffuse_color = [0.9,0,0,0.8]

Мы рекомендуем ознакомится с основами Python на официальном сайте, а так же с основами использования Blender библиотек.


Наверх