Решение на Пресичания от Ангел Александров

Обратно към всички решения

Към профила на Ангел Александров

Резултати

  • 10 точки от тестове
  • 1 отнета точка
  • 9 точки общо
  • 19 успешни тест(а)
  • 1 неуспешни тест(а)

Код

package main
import (
"math"
"sync"
"github.com/fmi/go-homework/geom"
)
type Triangle struct {
A, B, C geom.Vector
}
type Quad struct {
A, B, C, D geom.Vector
}
type Sphere struct {
Origin geom.Vector
R float64
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{
A: a,
B: b,
C: c,
}
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{
A: a,
B: b,
C: c,
D: d,
}
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{
Origin: origin,
R: r,
}
}
func (tr Triangle) Intersect(ray geom.Ray) bool {
// a.k.a Möller–Trumbore intersection algorithm
const EPSILON float64 = 0.0000001
e1 := Subtract(tr.B, tr.A)
e2 := Subtract(tr.C, tr.A)
p := CrossProduct(ray.Direction, e2)
det := DotProduct(e1, p)
if det > -EPSILON && det < EPSILON {
return false
}
f := 1.0 / det
s := Subtract(ray.Origin, tr.A)
u := f * DotProduct(s, p)
if u < 0.0 || u > 1.0 {
return false
}
q := CrossProduct(s, e1)
v := f * DotProduct(ray.Direction, q)
if v < 0.0 || u+v > 1.0 {
return false
}
t := f * DotProduct(e2, q)
return t > EPSILON
}
func (quad Quad) Intersect(ray geom.Ray) bool {
// Disclaimer: doesn't work for complex quads :( (had no time to implement "Triangulating")
var wg sync.WaitGroup
const CNT int = 2
ch := make(chan bool, CNT)
defer close(ch)
for i := 0; i < CNT; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
var tr Triangle
if i == 0 {
tr = Triangle{quad.A, quad.B, quad.C}
} else {
tr = Triangle{quad.A, quad.C, quad.D}
}
ch <- tr.Intersect(ray)
}(i)
}
wg.Wait()
return <-ch || <-ch
}
func (sph Sphere) Intersect(ray geom.Ray) bool {
L := Subtract(ray.Origin, sph.Origin)
a := DotProduct(ray.Direction, ray.Direction)
b := 2 * DotProduct(ray.Direction, L)
c := DotProduct(L, L) - math.Pow(sph.R, 2)
const scaleNum = 0.01
closeDirectionPoint := Add(ray.Origin, Multiply(ray.Direction, scaleNum))
return b*b-4*a*c >= 0 && Distance(sph.Origin, ray.Origin) > Distance(sph.Origin, closeDirectionPoint)
}
func Distance(a, b geom.Vector) float64 {
return math.Sqrt(math.Pow(a.X-b.X, 2) + math.Pow(a.Y-b.Y, 2) + math.Pow(a.Z-b.Z, 2))
}
func DotProduct(a, b geom.Vector) float64 {
return (a.X * b.X) + (a.Y * b.Y) + (a.Z * b.Z)
}
func CrossProduct(a, b geom.Vector) geom.Vector {
return geom.Vector{
X: a.Y*b.Z - a.Z*b.Y,
Y: a.Z*b.X - a.X*b.Z,
Z: a.X*b.Y - a.Y*b.X,
}
}
func Add(a, b geom.Vector) geom.Vector {
return geom.Vector{
X: a.X + b.X,
Y: a.Y + b.Y,
Z: a.Z + b.Z,
}
}
func Subtract(a, b geom.Vector) geom.Vector {
return geom.Vector{
X: a.X - b.X,
Y: a.Y - b.Y,
Z: a.Z - b.Z,
}
}
func Multiply(a geom.Vector, f float64) geom.Vector {
return geom.Vector{
X: a.X * f,
Y: a.Y * f,
Z: a.Z * f,
}
}

Лог от изпълнението

PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.003s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.003s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
--- FAIL: TestSphereNoBackFaceCulling (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s
PASS
ok  	_/tmp/d20181122-57-1g8lsgi	0.002s

История (2 версии и 1 коментар)

Ангел обнови решението на 20.11.2018 22:59 (преди 9 месеца)

+package main
+
+import (
+ "math"
+ "sync"
+
+ "github.com/fmi/go-homework/geom"
+)
+
+type Triangle struct {
+ A, B, C geom.Vector
+}
+
+type Quad struct {
+ A, B, C, D geom.Vector
+}
+
+type Sphere struct {
+ Origin geom.Vector
+ R float64
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{
+ A: a,
+ B: b,
+ C: c,
+ }
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{
+ A: a,
+ B: b,
+ C: c,
+ D: d,
+ }
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{
+ Origin: origin,
+ R: r,
+ }
+}
+
+func (tr Triangle) Intersect(ray geom.Ray) bool {
+ // a.k.a Möller–Trumbore intersection algorithm
+ const EPSILON float64 = 0.0000001
+ e1 := Subtract(tr.B, tr.A)
+ e2 := Subtract(tr.C, tr.A)
+ p := CrossProduct(ray.Direction, e2)
+ det := DotProduct(e1, p)
+
+ if det > -EPSILON && det < EPSILON {
+ return false
+ }
+
+ f := 1.0 / det
+ s := Subtract(ray.Origin, tr.A)
+ u := f * DotProduct(s, p)
+
+ if u < 0.0 || u > 1.0 {
+ return false
+ }
+
+ q := CrossProduct(s, e1)
+ v := f * DotProduct(ray.Direction, q)
+
+ if v < 0.0 || u+v > 1.0 {
+ return false
+ }
+ t := f * DotProduct(e2, q)
+
+ return t > EPSILON
+
+}
+
+func (quad Quad) Intersect(ray geom.Ray) bool {
+ // Disclaimer: doesn't work for complex quads :( (had no time to implement "Triangulating")
+ var wg sync.WaitGroup
+ const CNT int = 2
+ ch := make(chan bool, CNT)
+ defer close(ch)
+ for i := 0; i < CNT; i++ {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+ var tr Triangle
+ if i == 0 {
+ tr = Triangle{quad.A, quad.B, quad.C}
+ } else {
+ tr = Triangle{quad.A, quad.C, quad.D}
+ }
+ ch <- tr.Intersect(ray)
+ }(i)
+ }
+ wg.Wait()
+
+ return <-ch || <-ch
+}
+
+func (sph Sphere) Intersect(ray geom.Ray) bool {
+ L := Subtract(ray.Origin, sph.Origin)
+ a := DotProduct(ray.Direction, ray.Direction)
+ b := 2 * DotProduct(ray.Direction, L)
+ c := DotProduct(L, L) - math.Pow(sph.R, 2)
+ const SCALE_NUM float64 = 0.01
+ closeDirectionPoint := Add(ray.Origin, Multiply(ray.Direction, SCALE_NUM))
+ return b*b-4*a*c >= 0 && Distance(sph.Origin, ray.Origin) > Distance(sph.Origin, closeDirectionPoint)
+}
+
+func Distance(a, b geom.Vector) float64 {
+ return math.Sqrt(math.Pow(a.X-b.X, 2) + math.Pow(a.Y-b.Y, 2) + math.Pow(a.Z-b.Z, 2))
+}
+
+func DotProduct(a, b geom.Vector) float64 {
+ return (a.X * b.X) + (a.Y * b.Y) + (a.Z * b.Z)
+}
+
+func CrossProduct(a, b geom.Vector) geom.Vector {
+ return geom.Vector{
+ X: a.Y*b.Z - a.Z*b.Y,
+ Y: a.Z*b.X - a.X*b.Z,
+ Z: a.X*b.Y - a.Y*b.X,
+ }
+}
+
+func Add(a, b geom.Vector) geom.Vector {
+ return geom.Vector{
+ X: a.X + b.X,
+ Y: a.Y + b.Y,
+ Z: a.Z + b.Z,
+ }
+}
+
+func Subtract(a, b geom.Vector) geom.Vector {
+ return geom.Vector{
+ X: a.X - b.X,
+ Y: a.Y - b.Y,
+ Z: a.Z - b.Z,
+ }
+}
+
+func Multiply(a geom.Vector, f float64) geom.Vector {
+ return geom.Vector{
+ X: a.X * f,
+ Y: a.Y * f,
+ Z: a.Z * f,
+ }
+}

Ангел обнови решението на 21.11.2018 11:46 (преди 9 месеца)

package main
import (
"math"
"sync"
"github.com/fmi/go-homework/geom"
)
type Triangle struct {
A, B, C geom.Vector
}
type Quad struct {
A, B, C, D geom.Vector
}
type Sphere struct {
Origin geom.Vector
R float64
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{
A: a,
B: b,
C: c,
}
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{
A: a,
B: b,
C: c,
D: d,
}
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{
Origin: origin,
R: r,
}
}
func (tr Triangle) Intersect(ray geom.Ray) bool {
// a.k.a Möller–Trumbore intersection algorithm
const EPSILON float64 = 0.0000001
e1 := Subtract(tr.B, tr.A)
e2 := Subtract(tr.C, tr.A)
p := CrossProduct(ray.Direction, e2)
det := DotProduct(e1, p)
if det > -EPSILON && det < EPSILON {
return false
}
f := 1.0 / det
s := Subtract(ray.Origin, tr.A)
u := f * DotProduct(s, p)
if u < 0.0 || u > 1.0 {
return false
}
q := CrossProduct(s, e1)
v := f * DotProduct(ray.Direction, q)
if v < 0.0 || u+v > 1.0 {
return false
}
t := f * DotProduct(e2, q)
return t > EPSILON
}
func (quad Quad) Intersect(ray geom.Ray) bool {
// Disclaimer: doesn't work for complex quads :( (had no time to implement "Triangulating")
var wg sync.WaitGroup
const CNT int = 2
ch := make(chan bool, CNT)
defer close(ch)
for i := 0; i < CNT; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
var tr Triangle
if i == 0 {
tr = Triangle{quad.A, quad.B, quad.C}
} else {
tr = Triangle{quad.A, quad.C, quad.D}
}
ch <- tr.Intersect(ray)
}(i)
}
wg.Wait()
return <-ch || <-ch
}
func (sph Sphere) Intersect(ray geom.Ray) bool {
L := Subtract(ray.Origin, sph.Origin)
a := DotProduct(ray.Direction, ray.Direction)
b := 2 * DotProduct(ray.Direction, L)
c := DotProduct(L, L) - math.Pow(sph.R, 2)
- const SCALE_NUM float64 = 0.01
- closeDirectionPoint := Add(ray.Origin, Multiply(ray.Direction, SCALE_NUM))
+ const scaleNum = 0.01
+ closeDirectionPoint := Add(ray.Origin, Multiply(ray.Direction, scaleNum))
return b*b-4*a*c >= 0 && Distance(sph.Origin, ray.Origin) > Distance(sph.Origin, closeDirectionPoint)
}
func Distance(a, b geom.Vector) float64 {
return math.Sqrt(math.Pow(a.X-b.X, 2) + math.Pow(a.Y-b.Y, 2) + math.Pow(a.Z-b.Z, 2))
}
func DotProduct(a, b geom.Vector) float64 {
return (a.X * b.X) + (a.Y * b.Y) + (a.Z * b.Z)
}
func CrossProduct(a, b geom.Vector) geom.Vector {
return geom.Vector{
X: a.Y*b.Z - a.Z*b.Y,
Y: a.Z*b.X - a.X*b.Z,
Z: a.X*b.Y - a.Y*b.X,
}
}
func Add(a, b geom.Vector) geom.Vector {
return geom.Vector{
X: a.X + b.X,
Y: a.Y + b.Y,
Z: a.Z + b.Z,
}
}
func Subtract(a, b geom.Vector) geom.Vector {
return geom.Vector{
X: a.X - b.X,
Y: a.Y - b.Y,
Z: a.Z - b.Z,
}
}
func Multiply(a geom.Vector, f float64) geom.Vector {
return geom.Vector{
X: a.X * f,
Y: a.Y * f,
Z: a.Z * f,
}
}