Blender для начинающих/Python практика

Материал из Викиучебника — открытых книг для открытого мира



- перейти к комбинациям клавиш.
- перейти к первому необязательному для изучения разделу.
- переход к следующей по курсу главе (порядок глав не совпадает с порядком глав по содержанию).

CTRL+ALT+U

CTRL+U

SHIFT+S

CTRL+Q

A

R

G

S

SHIFT+D

ALT+D

CTRL+NUMPAD+

CTRL+NUMPAD-

SHIFT+L

SHIFT+G

ALT+M

F

CTRL+ALT+SHIFT+C

SHIFT+S

D

T

I

Shift+B

B

C

Одни из главных классов Python: bpy.ops | bpy.data | bpy.types.ID

Рендеринг Рендер-ферма
Отсечение Шейдер
Трассировка лучей Сжатие текстур

Расположение элементов интерфейса


Ссылки на материалы
Возможно, Вас заинтересует следующее:
О Blender 2.76 Скачать Blender 2.76

Алгебраические задачи[править]

Перестановка значений переменных[править]

def Swap(a, b):
    a = a + b
    b = a - b
    a = a - b

Циклы[править]

Пусть, имеется переменная a, значение которой после цикла while надо узнать. Пусть, inc - число, на которое увеличивается a. B - переменная, задающая условие в цикле:

while a знак B:
    a = a + inc

inc - независимая переменная. Значение a приближается к значению B.

  1. Если неравенство нестрогое, то после цикла a = a + inc*(abs(B - a) // inc + 1).
  2. Если неравенство строгое, то рассматриваются два случая:
    1. Если B % inc != 0, то a = a + inc*(abs(B - a) // inc + 1).
    2. Если B % inc == 0, то a = a + inc*(abs(B - a) // inc).

Таким образом, если неравенство нестрогое или неравенство строгое и остаток от деления B на inc не равен 0, то a = a + inc*(abs(B - a) // inc + 1), а во всех остальных случаях a = a + inc*(abs(B - a) // inc)

Если a = B и неравенство нестрогое, то переменная a = a + inc.

Геометрические задачи[править]

Расположение точки на диагонали[править]

Пусть, имеется точка A(x, y), то будет или нет она располагается на диагонали, можно будет узнать так:

if math.fabs(x) == math.fabs(y):
    print("Точка на диагонали")

math.fabs(x) возвращает модуль числа x.

Точка находится под прямой[править]

Пусть, имеется точка A(x, y), где x, y - нецелые числа. Уравнение прямой y = kx + b. Функция, возвращающая y в зависимости от x:

def getY(x, k, b):
    return k*x+b

Узнать ниже ли точка прямой или нет, можно, подставив ее x в уравнение прямой:

if y < getY(x, y, k):
    print("Точка под прямой.")

Точка на прямой[править]

Пусть, имеется точка A(x, y), где x, y - нецелые числа. Узнать на прямой ли точка или нет, можно, подставив ее x в уравнение прямой:

if y == getY(x, y, k):
    print("Точка на прямой.")

Точка над прямой[править]

Пусть, имеется точка A(x, y), где x, y - нецелые числа. Узнать выше прямой ли точка или нет, можно, подставив ее x в уравнение прямой:

if y > getY(x, y, k):
    print("Точка над прямой.")

Вычисление k перпендикулярной прямой[править]

Пусть, имеется точки A(x, y) и A(x2, y2), задающие прямые, где x, y - нецелые числа. То зная k первой прямой вычислить k для второй можно следующим образом:

import math
k2 = math.tan(math.atan(k)+90)

Вычисление координат точки пересечения прямых[править]

Пусть, прямые задаются такими уравнениями:

  1. y1 = k1*x + b1
  2. y2 = k2*x + b2

Приравняв их, получим: k1*x + b1 = k2*x + b2.

  1. k1*x - k2*x = b2 - b1
  2. x(k1 - k2) = b2 - b1

Следовательно, x = (b2 - b1)/(k1 - k2). Таким образом, узнать координаты точки пересечения прямых можно так:

x = (b2 - b1)/(k1 - k2)
y = k1*x + b1 # Без разницы, в уравнение какой прямой подставлять.

Вычисление коэффициента наклона прямой[править]

Пусть, прямая проходит через две точки: A(x, y) и B(x1, y1). Причем, точка B лежит правее и выше точки A. Тогда вычисление коэффициента k для уравнения прямой будет выглядеть следующим образом:

k = (y1 - y)/(x1 - x)

Столкновения[править]

Окружность с окружностью[править]

Если расстояние между радиусами окружностей больше суммы их радиусов, то они не пересекаются:

import math
if (math.sqrt((circle1.x - circle2.x)**2 + (circle1.y - circle2.y)**2) >= circle1.r + circle2.r):
    print("Окружности не пересекаются.")

Здесь circle1 и circle2 - окружности.

Пересечение отрезков[править]


Схема определения пересечения отрезков выглядит так:

Если проекции отрезков на ось X пересекаются:

Найти точку пересечения прямых, на которых лежат отрезки.
Если координата точки пересечения принадлежит одновременно двум проекциям отрезков на ось X, то:
Отрезки пересекаются.
Иначе:
Отрезки не пересекаются.

Пусть, есть две точки, составляющих первый отрезок: A(x, y) и B(x1, y1). Пусть, есть две точки, составляющие второй отрезок: C(x2, y2) и D(x3, y3). Пусть, точки расположены по оси +X в таком порядке: A, B, C, D.

if ((x1 >= x3) and (x1 <= x4)) or ((x >= x3) and (x <= x4)):
    intersectX = (b2 - b1)/(k1 - k2)
    if ((intersectX >= x) and (intersectX <= x1)) or ((intersectX >= x2) and (intersectX <= x3)):
        print('Отрезки пересекаются.')
    else:
        print('Отрезки не пересекаются.')
else:
    print('Отрезки не пересекаются.')

Данная схема будет корректно работать лишь в том случае, если ни один из отрезков не перпендикулярен оси X.

Принципы написания UI[править]

Аббревиатура «UI» расшифровывается на русский язык как «пользовательский интерфейс».

Кнопки[править]


Границей любой кнопки обычно является прямоугольник, поэтому проверка на принадлежность точки A(x, y) этому прямоугольнику можно задать следующим условием:

if (A.x >= button.x) and (A.y >= button.y) and (A.x <= button.x + button.width) and (A.y <= button.y + button.heigth):
  1. A.x - X координата точки
  2. A.y - Y координата точки
  3. button.x - X координата левого верхнего угла прямоугольника
  4. button.y - Y координата левого верхнего угла прямоугольника
  5. button.width - ширина прямоугольника
  6. button.height - высота прямоугольника

Ползунки[править]

Любой ползунок представляет собой два прямоугольника. Первый - границы ползунка, второй - значение ползунка. Напишем функцию, которая определит лежит ли точка в границах первого прямоугольника «border»:

def intersect(A, border):
    if (A.x >= border.x) and (A.y >= border.y) and (A.x <= border.x + border.width) and (A.y <= border.y + border.heigth):
        return True
    else:
        return False

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

if cursor.x < border.x:
    value.x = border.x
elif cursor.x > border.x + border.width:
    value.x = border.x + border.width
else:
    value.x = cursor.x

Архитектура игровых классов[править]

При написании проекта следует определить будет ли он 2D или 3D игрой. С учетом этого, следует строить архетиктуру классов проекта.

2D игры - пример архитектуры классов[править]

class Object
    # свойства
    x_position, y_position, width, height, fill_color, border_color, border_width, filled, bordered
    class Lamp(Object)
        # свойства
        energy, distance
    class Dynamic(Object)
        # свойства
        mass, radius

Здесь основные свойства объекта занесены в один класс «Object», так как их мало.

3D игры - пример архитектуры[править]

Так как 3D игры - игры с более навороченной графикой, то было бы предпочтительнее использовать такую систему классов:

class Material
    # свойства
    fill_color, border_color, border_width, filled, bordered
class Object
    # свойства
    x_position, y_position, width, height
    # ссылка на объект:
    material
    class Lamp(Object)
        # свойства
        energy, distance
    class Dynamic(Object)
        # свойства
        mass, radius

Калькулятор[править]

Пусть, наш калькулятор поддерживает выражения вида a±b, a/b и a*b. Пусть, a, b € [0; 9]. Код калькулятора будет следующий:

while True:
    text = input()
    if len(text) != 3:
        print("Длина строки не равна 3.")
    else:
        a = int(text[0])
        b = int(text[2])
        if text[1] == "+":
            print(a + b)
        elif text[1] == "-":
            print(a - b)
        elif text[1] == "/":
            print(a / b)
        elif text[1] == "*":
            print(a * b)
        else:
            print("Недопустимая операция.")

Сортировки[править]

Диски[править]

Пусть, имеем три палки «A», «B» и «C», причем изначально все диски лежат на «A». Следует отсортировать диски по возрастанию (от верхнего к нижниму), если мы можем видеть только верхние диски.

Пока на палке «A» находится не ноль дисков:

Перекинуть верхний диск с «A» на «B».
Повторить цикл такое количество раз, которое равно n (n - количество дисков на «A»):
Если диск на «B» меньше, чем на «A», то скинуть диск с «A» на «B».
Перекинуть диск с «B» на «C».
Перекинуть такое количество дисков с «B» на «A», которое равно n - m (n - количество всех дисков на «B», а m - количество циклов, уменьшенное на единицу).
Перекинуть диск с «C» на «B».

Сортировка при помощи функций списков[править]

Самый неудачный, но возможный вариант сортировки представлен ниже:

def SortList(a):
    b = list()
    for i in range(0, len(a)):
        m = a.min(a)
        b.append(m)
        a.remove(m)
    return b

Недостатки:

  1. Используется два списка.
  2. Слишком много используется встроенных функций.
  3. Медленная сортировка.

Использование встроенных в Python функций не гарантирует быструю скорость работы алгоритма.

Сортировка пузырьком[править]

  1. Проходим по списку несколько раз, чтобы правильно отсортировать все элементы в правильном порядке. Не всегда после n-ной итерации все элементы списка будут отсортированы.
  2. Сначала мы ищем минимальный элемент во всем списке, потом - в его оставшейся части.
def SortList(a):
    for i in range(0, len(a)):
        for j in range(len(a) - 1, i, -1):
            if a[j] < a[j-1]:
                a[j], a[j - 1] = a[j - 1], a[j]
    return a
def SortList(a):
    for i in range(len(a) - 1, -1):
        for j in range(0, i):
            if a[j] < a[j + 1]:
                a[j], a[j + 1] = a[j + 1], a[j]
    return a

Сортировка выбором[править]

def SortList(a):
    for i in range(0, len(a)):
        for j in range(i + 1, len(a)):
            if a[i] > a[j]:
                a[i], a[j] = a[j], a[i]
    return a
  1. Переменные i и j изменяются в одном направлении - увеличиваются.
  2. Сравнивая с все элементы списка, стоящие после a[i], с a[i], мы находим минимум из множества значений (a[i], a[len(a)-1]]. При следующей итерации новый минимум будет искаться из оставшихся элементов, поэтому следующий минимум будет больше предыдущего минимума.

Сортировка вставками[править]

Отличается от сортировки пузырьком тем, что:

  1. Переменные i и j изменяются в разных направлениях.
  2. Осуществляем меньше итераций, чем в сортировке пузырьком, так как мы не проходим уже отсортированные пары элементов, поскольку отсортировали их на более ранних итерациях цикла for.
def SortList(a):
    for i in range(1, len(a)):
        j = i
        while (j > 0) and (a[j] < a[j - 1]):
            a[i], a[j] = a[j], a[i]
            j -= 1
    return a
  1. В «range(1, len(a))» первым элементом множества значений установил 1, чтобы не проверять лишний раз условие «while j > 0 and a[j] < a[j - 1]».
  2. Условие «j > 0» требуется для того, чтобы предотвратить выход j - 1 за границы списка.

Алгоритм создания множеств[править]

def NewSet(a):
    for i in range(0, len(a)):
        j = i + 1
        while j < len(a):
            if a[j] == a[i]:
                a.remove(a[j])
            else:
                j += 1
    return a

Пусть, мы должны сравнивать все элементы списка с a[j]. Из этого следует то, что не все элементы со значением a[j] были удалены. Но это противоречит тому, что написано в теле цикла:

while j < len(a):
    if a[j] == a[i]:
        a.remove(a[j])
    else:
        j += 1

Таким образом, мы должны сравнивать все элементы с a[i], стоящие после a[i].

Другие алгоритмы[править]

Разделение строки по символам[править]

sym = []
sym.append(' ')
sym.append(';')
words = []
wI = 0
s = input()
i = 0
while i < len(s):
    while (i < len(s)) and (s[i] in sym):
        i += 1
    while (i < len(s)) and not (s[i] in sym):
        sym[wI] = sym[wI] + s[i]
        i += 1
    wI += 1

Алгоритм нахождения НОК[править]

НОК - наибольший общий делитель чисел M и N.

  1. def NOK(a, b):
        while a != 0 and b != 0:
            if a > b:
                a = a % b
            else:
                b = b % a
        return a + b
    
    Выводим сумму, так не знаем в какой переменной именно хранится НОК. Значение одной из двух переменных после последней итерации будет равно 0.
  2. Ниже используется правило «Если M>N, то НОД(М, N) = НОД(М - N, N)». Докажем правило. Пусть, K - один из общих делителей двух чисел, а m и n - числа, на которые умножается K, то M = mK, N = nK. Следовательно:
    1. M - N = mK - nK
    2. M - N = K(m - n)
    def NOK(a, b):
        while a != b:
            if a > b:
                a = a - b
            else:
                b = b - a
        return a
    
    Выводим a, так как a == b после последней итерации цикла.

Выборка элементов[править]

Пусть, a - список, состоящий из чисел. Следует выбрать только те числа, которые лежат в диапазонах: [1; 10], [21; 30] и т. д. Количество интервалов определяется переменной inters.

def Get(a, inters):
    for i in range(len(a)):
        for j in range(i + 1, len(a)):
            if a[j - 1] > a[j]:
                a[j], a[j - 1] = a[j - 1], a[j]
    
    i = 1
    count = 0
    while i <= inters*20:
        j = 0
        while (j < len(a)) and (a[j] <= i + 9):
            if (a[j] >= i) and (a[j] <= i + 9):
                count += 1
            j += 1
        i += 20
    return count

Сортируем список для того, чтобы не выполнять во второй группе циклов лишние итерации.

Удаление элементов[править]

Пусть, есть список a, из которого надо удалить n элементов, начиная с i-ого элемента. Код удаления элементов будет следующий:

def Delete(a, i, n):
    b = []
    
    for i2 in range(0, len(a)):
        b.append(a[i2])
    
    for i2 in range(i, len(b) - n):
        b[i2] = b[i2 + n]
    
    return ''.join(b)[:len(b) - n:]

Сортировка по алфавиту[править]

Пусть, a - список, который следует отсортировать по алфавиту. Алгоритм:

  1. Создать список, определяющий номер каждой первой буквы каждой строки в алфавите.
  2. Отсортировать два списка.
def SortList(a):
    alph = 'abcdefgijklmnopqrstuvwxyz'
    b = []
    for s in a:
        i = 0
        while s[0].lower() != alph[i]:
            i += 1
        b.append(i)
    
    for i in range(0, len(a)):
        for j in range(i + 1, len(a)):
            if b[i] > b[j]:
                b[i], b[j] = b[j], b[i]
                a[i], a[j] = a[j], a[i]
    return a

Вариант с кэшированием уже найденных символов:

def SortList(a):
    alph = 'abcdefgijklmnopqrstuvwxyz'
    K = {}
    b = []
    
    for s in a:
        i = 0
        try:
            b.append(K[s[0]])
        except KeyError:
            while s[0].lower() != alph[i]:
                i += 1
            K[s[0]] = alph[i]
            b.append(i)
    
    for i in range(0, len(a)):
        for j in range(i + 1, len(a)):
            if b[i] > b[j]:
                b[i], b[j] = b[j], b[i]
                a[i], a[j] = a[j], a[i]
    return a

Сортировка словаря[править]

Сам словарь отсортировать невозможно напрямую.

def SortList(d):
    a = d.keys()
    alph = 'abcdefgijklmnopqrstuvwxyz'
    b = []
    for s in a:
        i = 0
        while s[0].lower() != alph[i]:
            i += 1
        b.append(i)
    
    for i in range(0, len(a)):
        for j in range(i + 1, len(a)):
            if b[i] > b[j]:
                b[i], b[j] = b[j], b[i]
                a[i], a[j] = a[j], a[i]
    return a

Поиск подстроки[править]

def Find(Str, substr):
    k = 0 # Количество равных символов.
    if (len(Str) > len(substr)) and (len(substr) != 0):
        for i in range(0, len(Str) - len(substr) + 1):
            if k != len(substr):
                for j in range(0, len(substr)):
                    if substr[j] != Str[j + i]:
                        break
                    else:
                        k += 1
                if k == len(substr):
                    return i
                else:
                    k = 0
        return -1
    else:
        return -1

Поиск подстроки по шаблону[править]

Для каждого символа строки Str мы задаем список допустимых для него значений.

def Find(Str, patternL):
    k = 0 # Количество равных символов.
    if (len(Str) > len(patternL)) and (len(patternL) != 0):
        for i in range(0, len(Str) - len(patternL) + 1):
            if k != len(patternL):
                for j in range(0, len(patternL)):
                    if not Str[j + i] in patternL[j]:
                        break
                    else:
                        k += 1
                if k == len(patternL):
                    return i
                else:
                    k = 0
        return -1
    else:
        return -1

Пример использования:

Find('a1b324a2b124',[['a', 'b'], ['1']])

Удаление подстроки[править]

  1. В условии «(len(Str) > len(substr)) and (len(substr) != 0)» не пишем «and (len(Str) != 0)», так как часть условия «len(Str) > len(substr)» исключает это условие.
  2. i меняется от 0 до суммы разности длин строк и единицы, так как последнее значение в функции «range(0, len(Str) - len(substr) + 1)» не включается.
def DeleteSubstr(Str, substr):
    k = 0 # Количество равных символов.
    if (len(Str) > len(substr)) and (len(substr) != 0):
        for i in range(0, len(Str) - len(substr) + 1):
            if k != len(substr):
                for j in range(0, len(substr)):
                    if substr[j] != Str[j + i]:
                        break
                    else:
                        k += 1
                if k == len(substr):
                    b = []
                    
                    for i2 in range(0, len(Str)):
                        b.append(Str[i2])
                    
                    for i2 in range(i, len(Str) - len(substr)):
                        b[i2] = b[i2 + len(substr)]
                    
                    return ''.join(b)[:len(b) - len(substr):]
                else:
                    k = 0
        return -1
    else:
        return -1
def DeleteSubstrs(Str, substr):
    k = 0 # Количество равных символов.
    if (len(Str) > len(substr)) and (len(substr) != 0):
        for i in range(0, len(Str) - len(substr) + 1):
            if k != len(substr):
                for j in range(0, len(substr)):
                    if substr[j] != Str[j + i]:
                        break
                    else:
                        k += 1
                if k == len(substr):
                    b = []
                    
                    for i2 in range(0, len(Str)):
                        b.append(Str[i2])
                    
                    for i2 in range(i, len(Str) - len(substr)):
                        b[i2] = b[i2 + len(substr)]
                    
                    Str = ''.join(b)[:len(b) - len(substr):]
                else:
                    k = 0
        return Str
    else:
        return -1
def DeleteSubstrs(Str, substr):
    s = Str
    while DeleteSubstr(s, substr) != -1:
        s = DeleteSubstr(s, substr)
    return s

Поиск корня[править]

Нахождение квадратного корня:

import math
def Sqrt(x):
    a = 0.5*x
    if 
    while math.floor(a**2) != x:
        if a**2 > x:
            a = a*0.5
        elif a**2 < x:
            a = a*1.5
    return a

Нахождение корня n-ной степени:

import math
def Sqrt(x, n):
    a = 0.5*x
    while math.floor(a**n) != x:
        if a**n > x:
            a = a*0.5
        elif a**n < x:
            a = a*1.5
    return a

Четность и нечетность элемента в списке[править]

Индекс, с которого начинается отсчет Формула для нечетных элементов Формула для четных элементов
четный индекс % 2 == 0 индекс % 2 != 0
нечетный индекс % 2 != 0 индекс % 2 == 0
  1. Если считать от четного индекса, то у нечетных элементов будут четные индексы, а у четных - нечетные.
  2. Если считать от нечетного индекса, то у нечетных элементов будут нечетные индексы, а у четных - четные.