Pure Python 3.6.3 - нахождение разницы в градусах между 2 3d векторами - PullRequest
0 голосов
/ 11 марта 2019

По какой-то безбожной причине я пытаюсь создать программу для отображения каркасной графики на чистом python 3.6.3 с библиотекой turtle.Я дошел до того, что хотел бы пропустить рисование ненужных трис в целях оптимизации.Ненужное значение трис, означающее трис, которое должно быть скрыто другими частями модели, т. Е. Нормаль, обращенная в сторону от 3d-камеры.

Данные модели, с которыми работает программа, представляют собой просто огромный трехмерный массив со следующимиформатирование для каждого три.

[[Vert],[Vert],[Vert],[Normal]]

Моя текущая версия кода имеет только одну модель (куб) и выглядит следующим образом:

from turtle import *

Cube = [[[-50,50,-50],[-50,50,50,],[50,50,50],[0,1,0]],
        [[-50,50,-50],[50,50,50,],[50,50,-50],[0,1,0]],
        [[-50,50,-50],[-50,50,50],[-50,-50,50],[1,0,0]],
        [[-50,50,-50],[-50,-50,-50],[-50,-50,50],[1,0,0]],
        [[-50,50,50],[50,50,50],[50,-50,50],[0,0,1]],
        [[-50,50,50],[50,-50,50],[-50,50,50],[0,0,1]],
        [[-50,-50,-50],[-50,-50,50,],[50,-50,50],[0,-1,0]],
        [[-50,-50,-50],[50,-50,50,],[50,-50,-50],[0,-1,0]],
        [[50,50,-50],[50,50,50],[50,-50,50],[-1,0,0]],
        [[50,50,-50],[50,-50,-50],[50,-50,50],[-1,0,0]],
        [[-50,50,-50],[50,50,-50],[50,-50,-50],[0,0,-1]],
        [[-50,50,-50],[50,-50,-50],[-50,50,-50],[0,0,-1]]]

CamVector = [0,1,0]

def DrawModel(Model):
    for i in range(0,len(Model)):
        goto(Model[i][0][0],Model[i][0][1])
        pd()
        goto(Model[i][1][0],Model[i][1][1])
        goto(Model[i][2][0],Model[i][2][1])
        goto(Model[i][0][0],Model[i][0][1])
        pu()

Model = Cube
DrawModel(Model)

Но я бы хотелсравните каждую тройку нормально с CamVector, чтобы код в конечном итоге выглядел так:

def DrawModel(Model):
    for i in range(0,len(Model)):
        AngleAwayFromCamera = *Math voodoo*
        if AngleAwayFromCamera <= 90:
            *draw tri*

Если у кого-нибудь есть идеи о том, как помочь, это можно объяснить кому-то с таким же размером мозга, как я,было бы замечательно.Я просмотрел много документации, но большая часть пролетела прямо у меня над головой - возможно, потому, что я не сдал экзамены GCSE.

1 Ответ

0 голосов
/ 11 марта 2019

Не вдаваясь слишком в математические детали, в математике есть нечто, называемое точечным произведением :

enter image description here

В основном,это способ объединения двух векторов (назовите их a и b ), чтобы получить одно число.Это число равно величине a , умноженной на величину b , умноженному на косинус угла между ними (который мы можем назвать θ).

Благодаря этому уравнению, изменяя положение вещей, мы в конечном итоге можем получить то, что хотим, то есть θ.

Скажем, у нас есть a : [1, 2, 3] и b.: [4, 5, 6].Мы можем вычислить их величины, возведя в квадрат их элементы и взяв квадратный корень из суммы.Следовательно, величина a равна (1 ** 2 + 2 ** 2 + 3 ** 2) ** 0.5 = 14 ** 0.5, а величина b равна (4 ** 2 + 5 ** 2 + 6 ** 2) ** 0.5 = 77 ** 0.5.

Умножение их вместе дает нам 1078 ** 0.5.Следовательно, скалярное произведение равно (1078 ** 0.5) * cos θ.

Оказывается, что скалярное произведение можно рассчитать путем умножения соответствующих элементов двух векторов и суммирования результата.Таким образом, для a и b выше, скалярное произведение равно 1 * 4 + 2 * 5 + 3 * 6 = 32.

. Учитывая эти два различных (но равных) выражения скалярного произведения, мы можемприравнять их для решения для θ следующим образом (arccos - это функция, которая превращает cos θ в θ):

(1078 ** 0.5) * cos θ = 32
cos θ = 32 / (1078 ** 0.5)
θ = arccos(32 / (1078 ** 0.5))
θ ≈ 12.93 (in degrees)

Теперь осталось только реализовать это в коде:

from numpy import arccos

def angle_between_vectors(v1, v2):
    def magnitude(v):
        return sum(e ** 2 for e in v) ** 0.5

    dot_product = sum(e1 * e2 for e1, e2 in zip(v1, v2))
    magnitudes = magnitude(v1) * magnitude(v2)
    angle = arccos(dot_product / magnitudes)
    return angle

Применение этой функции к a и b выше и преобразование из радиан в градусы (разделить на π и умножить на 180) дает нам 12,93, как и ожидалось.

...