Пресичания

Предадени решения

Краен срок:
21.11.2018 17:00
Точки:
10

Срокът за предаване на решения е отминал

За това домашно ще трябва да избършете праха от знанията си по аналитична геометрия и да опитате да ги приложите в истинс... виртуалния свят на 3D графиката. Една от важните задачи за създаването на реалистични изображения е да се разбере дали даден лъч пресича фигура в триизмерното пространство. Както започвате да се усещате - ще ви накараме да я решите няколко пъти.

Като начало приемете, че имате за даденост следните типове:

type Vector struct {
    X, Y, Z float64
}

Vector е триизмерния вектор (X, Y, Z). В тази задача той може да дефинира точка с координати (X, Y, Z) или вектор-посока. Посоката е вектор с начало (0,0,0) и край (X, Y, Z).

type Ray struct {
    Origin    Vector
    Direction Vector
}

Ray е лъч, определен от своето начало Origin и посока Direction. Точките на един лъч могат да се зададат със следното параметрично уравнение:

P(t)=O+tD)

където

O:=ray.Origin, D:=ray.Direction

Тези типове са дефинирани в пакета github.com/fmi/go-homework/geom. Можете да видите документацията му на godoc.com.

От вас ще се иска да напишете функции създаващи триъгълник, четириъгълник и сфера, които да удовлетворяват интерфейса

type Intersectable interface {
    Intersect(ray Ray) bool
}

Метода Intersect(ray Ray) bool връща истина само когато лъча ray пресича съответния обект в пространството.

Пример за пресичане:

ray intersecting a triangle

Пример за липса на пресичане:

ray which does not intersect a quad

Триъгълник

Напишете функция от вида

func NewTriangle(a, b, c geom.Vector) Triangle

която връща триъгълник в пространството, определен от върховете си в точките a, b, и c. Не е необходимо типа ви да се нарича Triangle. Може да има всякакво име, стига да отговаря на интерфейса Intersectable. Разбира се, Triangle е хубаво име за този тип. Може да върнете и указател (*Triangle, *T или други) ако това е по - смислено за вашия тип.

Четириъгълник

Функцията за създаване на четириъгълник трябва да е от следния вид

func NewQuad(a, b, c, d geom.Vector) Quad

Отново, не е необходимо типа ви да се казва Quad. Просто трябва да отговаря на интерфейса Intersectable.

Забележка: точките a, b, c и d ще са в една равнина. Няма да даваме нищо друго на функцията в нашите тестове, така че няма нужда да проверявате за това.

Сфера

Подобно на другите, функцията за създаване на сфера която трябва да напишете е

func NewSphere(origin geom.Vector, r float64) Sphere

Тук origin е центъра на сферата, а r е нейния радиус.

Пример

a, b, c := geom.NewVector(-1, -1, 0), geom.NewVector(1, -1, 0), geom.NewVector(0, 1, 0)
tr := NewTriangle(a, b, c)

ray := geom.NewRay(geom.NewVector(0, 0, -1), geom.NewVector(0, 0, 1))

if tr.Intersect(ray) {
    fmt.Println("ray intersects tr")
}

Уточнения

Вашите обекти трябва да се пресичат и от двете им страни. Т.е. не трябва да правите back face culling.

Крайните ръбове, дефиниращи фигурите, са част от нея и съответно трябва да връщат true за пресичания.

Как да използвам Vector, Ray и Intersectable?

За тази задача ще позволим използването на пакет извън стандартната библиотека - github.com/fmi/go-homework/geom. Той ще е наличен по време на изпълнението на тестовете на сайта ни. Недейте да го копирате в домашните си или на други места. Не се опитвайте да го предавате като част от домашното ви. Просто го използвайте във вашето решение. За удобство в пакета са добавени функциите NewVector и NewRay.