Blender для начинающих/Python практика: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
Нет описания правки
м Откат правок Владислав Молдован (обс.) к версии Volobuev Ilya
Строка 1: Строка 1:
{{К быстрому удалению|неточное изложение материала, множество ошибок}}
{{BlenderBook|BlenderLogo Python}}
{{BlenderBook|BlenderLogo Python}}
=Алгебраические задачи=
=Алгебраические задачи=

Версия от 18:46, 26 октября 2017



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

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. Если считать от нечетного индекса, то у нечетных элементов будут нечетные индексы, а у четных - четные.