Решение на Пресичания от Добромир Иванов

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

Към профила на Добромир Иванов

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 12 успешни тест(а)
  • 8 неуспешни тест(а)

Код

package main
import (
"github.com/fmi/go-homework/geom"
"math"
)
type triangle struct {
a, b, c geom.Vector
}
type quad struct {
a, b, c, d geom.Vector
}
type sphere struct {
center geom.Vector
radius float64
}
func NewTriangle(a, b, c geom.Vector) geom.Intersectable {
return triangle{a, b, c}
}
func (tr triangle) Intersect(ray geom.Ray) bool {
normal := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(tr.c, tr.a))
nDotProductDir := dotProduct(normal, ray.Direction)
if nDotProductDir == 0 {
return false
}
d := dotProduct(normal, tr.a)
t := (d - dotProduct(normal, ray.Origin)) / nDotProductDir
// So point is behind ray's origin?
if t < 0 {
return false
}
// Intersection point
p := addVectors(ray.Origin, scalarMultiply(ray.Direction, t))
vertex := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(p, tr.a))
if dotProduct(vertex, normal) <= 0 {
return false
}
vertex = crossProduct(subtractVectors(tr.c, tr.b), subtractVectors(p, tr.b))
if dotProduct(vertex, normal) <= 0 {
return false
}
vertex = crossProduct(subtractVectors(tr.a, tr.c), subtractVectors(p, tr.c))
if dotProduct(vertex, normal) <= 0 {
return false
}
return true
}
func NewQuad(a, b, c, d geom.Vector) geom.Intersectable {
return quad{a, b, c, d}
}
func (q quad) Intersect(ray geom.Ray) bool {
return NewTriangle(q.a, q.b, q.d).Intersect(ray) ||
NewTriangle(q.d, q.b, q.c).Intersect(ray)
}
func NewSphere(center geom.Vector, radius float64) geom.Intersectable {
return sphere{center, radius}
}
func (s sphere) Intersect(ray geom.Ray) bool {
l := subtractVectors(s.center, ray.Origin)
tca := dotProduct(l, ray.Direction)
d := math.Sqrt(dotProduct(l, l) - tca*tca)
if d > s.radius {
return false
}
thc := math.Sqrt(s.radius*s.radius - d*d)
t0 := tca - thc
t1 := tca + thc
if t0 > t1 {
t0, t1 = t1, t0
}
if t0 < 0 || t1 < 0 {
return false
}
return true
}
func dotProduct(a geom.Vector, b geom.Vector) float64 {
return a.X*b.X + a.Y*b.Y + a.Z*b.Z
}
func crossProduct(a geom.Vector, b geom.Vector) geom.Vector {
return geom.NewVector(
a.Y*b.Z-a.Z*b.Y,
a.Z*b.X-a.X*b.Z,
a.X*b.Y-a.Y*b.X)
}
func addVectors(a, b geom.Vector) geom.Vector {
return geom.NewVector(a.X+b.X, a.Y+b.Y, a.Z+b.Z)
}
func subtractVectors(a, b geom.Vector) geom.Vector {
return geom.NewVector(a.X-b.X, a.Y-b.Y, a.Z-b.Z)
}
func scalarMultiply(vector geom.Vector, b float64) geom.Vector {
return geom.NewVector(vector.X*b, vector.Y*b, vector.Z*b)
}

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

PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.003s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
--- FAIL: TestQuadSimpleIntersection (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-g97spe	0.002s
--- FAIL: TestQuadNoBackFaceCulling (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
--- FAIL: TestQuadNonAxisAligned (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
--- FAIL: TestQuadIrregularHit (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-g97spe	0.002s
--- FAIL: TestQuadSecondIrregularHit (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.002s
PASS
ok  	_/tmp/d20181122-57-g97spe	0.003s
--- 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-g97spe	0.002s
--- FAIL: TestSphereRayOppositeDirection (0.00s)
    solution_test.go:206: Expected intersection to be false but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-g97spe	0.002s
--- FAIL: TestSphereNearMiss (0.00s)
    solution_test.go:206: Expected intersection to be false but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-g97spe	0.002s

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

Добромир обнови решението на 20.11.2018 19:29 (преди 9 месеца)

+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+type triangle struct {
+ a, b, c geom.Vector
+}
+
+type quad struct {
+ a, b, c, d geom.Vector
+}
+
+type sphere struct {
+ center geom.Vector
+ radius float64
+}
+
+func NewTriangle(a, b, c geom.Vector) geom.Intersectable {
+ return triangle{a, b, c}
+}
+
+func (tr triangle) Intersect(ray geom.Ray) bool {
+ normal := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(tr.c, tr.a))
+
+ nDotProductDir := dotProduct(normal, ray.Direction)
+ if nDotProductDir == 0 {
+ return false
+ }
+
+ d := dotProduct(normal, tr.a)
+ t := (d - dotProduct(normal, ray.Origin)) / nDotProductDir
+
+ // So point is behind ray's origin?
+ if t < 0 {
+ return false
+ }
+
+ // Intersection point
+ p := addVectors(ray.Origin, scalarMultiply(ray.Direction, t))
+
+ vertex := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(p, tr.a))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
+
+ vertex = crossProduct(subtractVectors(tr.c, tr.b), subtractVectors(p, tr.b))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
+
+ vertex = crossProduct(subtractVectors(tr.a, tr.c), subtractVectors(p, tr.c))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
+
+ return true
+}
+
+func NewQuad(a, b, c, d geom.Vector) geom.Intersectable {
+ return quad{a, b, c, d}
+}
+
+func (q quad) Intersect(ray geom.Ray) bool {
+ return NewTriangle(q.a, q.b, q.d).Intersect(ray) ||
+ NewTriangle(q.d, q.b, q.c).Intersect(ray)

Напиши си няколко теста за този случай. Но наистина няколко, не само вариация на един и същи тест. По какво могат да се различават четириъгълниците?

+}
+
+func NewSphere(center geom.Vector, radius float64) geom.Intersectable {
+ return sphere{center, radius}
+}
+
+func (s sphere) Intersect(ray geom.Ray) bool {
+ L := subtractVectors(s.center, ray.Origin)
+ tca := dotProduct(L, ray.Direction)
+
+ d2 := dotProduct(L, L) - tca*tca
+ if d2 > s.radius {
+ return false
+ }
+
+ thc := math.Sqrt(s.radius - d2)
+ t0 := tca - thc
+ t1 := tca + thc
+ if t0 > t1 {
+ t0, t1 = t1, t0
+ }
+
+ if t0 < 0 || t1 < 0 {
+ return false
+ }
+
+ return true
+}
+
+func dotProduct(a geom.Vector, b geom.Vector) float64 {
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+}
+
+func crossProduct(a geom.Vector, b geom.Vector) geom.Vector {
+ return geom.NewVector(
+ a.Y*b.Z-a.Z*b.Y,
+ a.Z*b.X-a.X*b.Z,
+ a.X*b.Y-a.Y*b.X)
+}
+
+func addVectors(a, b geom.Vector) geom.Vector {
+ return geom.NewVector(a.X+b.X, a.Y+b.Y, a.Z+b.Z)
+}
+
+func subtractVectors(a, b geom.Vector) geom.Vector {
+ return geom.NewVector(a.X-b.X, a.Y-b.Y, a.Z-b.Z)
+}
+
+func scalarMultiply(vector geom.Vector, b float64) geom.Vector {
+ return geom.NewVector(vector.X*b, vector.Y*b, vector.Z*b)
+}

Добромир обнови решението на 21.11.2018 15:17 (преди 9 месеца)

package main
import (
- "github.com/fmi/go-homework/geom"
- "math"
+ "github.com/fmi/go-homework/geom"
+ "math"
)
type triangle struct {
- a, b, c geom.Vector
+ a, b, c geom.Vector
}
type quad struct {
- a, b, c, d geom.Vector
+ a, b, c, d geom.Vector
}
type sphere struct {
- center geom.Vector
- radius float64
+ center geom.Vector
+ radius float64
}
func NewTriangle(a, b, c geom.Vector) geom.Intersectable {
- return triangle{a, b, c}
+ return triangle{a, b, c}
}
func (tr triangle) Intersect(ray geom.Ray) bool {
- normal := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(tr.c, tr.a))
+ normal := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(tr.c, tr.a))
- nDotProductDir := dotProduct(normal, ray.Direction)
- if nDotProductDir == 0 {
- return false
- }
+ nDotProductDir := dotProduct(normal, ray.Direction)
+ if nDotProductDir == 0 {
+ return false
+ }
- d := dotProduct(normal, tr.a)
- t := (d - dotProduct(normal, ray.Origin)) / nDotProductDir
+ d := dotProduct(normal, tr.a)
+ t := (d - dotProduct(normal, ray.Origin)) / nDotProductDir
- // So point is behind ray's origin?
- if t < 0 {
- return false
- }
+ // So point is behind ray's origin?
+ if t < 0 {
+ return false
+ }
- // Intersection point
- p := addVectors(ray.Origin, scalarMultiply(ray.Direction, t))
+ // Intersection point
+ p := addVectors(ray.Origin, scalarMultiply(ray.Direction, t))
- vertex := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(p, tr.a))
- if dotProduct(vertex, normal) <= 0 {
- return false
- }
+ vertex := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(p, tr.a))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
- vertex = crossProduct(subtractVectors(tr.c, tr.b), subtractVectors(p, tr.b))
- if dotProduct(vertex, normal) <= 0 {
- return false
- }
+ vertex = crossProduct(subtractVectors(tr.c, tr.b), subtractVectors(p, tr.b))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
- vertex = crossProduct(subtractVectors(tr.a, tr.c), subtractVectors(p, tr.c))
- if dotProduct(vertex, normal) <= 0 {
- return false
- }
+ vertex = crossProduct(subtractVectors(tr.a, tr.c), subtractVectors(p, tr.c))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
- return true
+ return true
}
func NewQuad(a, b, c, d geom.Vector) geom.Intersectable {
- return quad{a, b, c, d}
+ return quad{a, b, c, d}
}
func (q quad) Intersect(ray geom.Ray) bool {
- return NewTriangle(q.a, q.b, q.d).Intersect(ray) ||
- NewTriangle(q.d, q.b, q.c).Intersect(ray)
+ return NewTriangle(q.a, q.b, q.d).Intersect(ray) ||
+ NewTriangle(q.d, q.b, q.c).Intersect(ray)
}
func NewSphere(center geom.Vector, radius float64) geom.Intersectable {
- return sphere{center, radius}
+ return sphere{center, radius}
}
func (s sphere) Intersect(ray geom.Ray) bool {
- L := subtractVectors(s.center, ray.Origin)
- tca := dotProduct(L, ray.Direction)
+ l := subtractVectors(s.center, ray.Origin)
+ tca := dotProduct(l, ray.Direction)
- d2 := dotProduct(L, L) - tca*tca
- if d2 > s.radius {
- return false
- }
+ d := math.Sqrt(dotProduct(l, l) - tca*tca)
+ if d > s.radius {
+ return false
+ }
- thc := math.Sqrt(s.radius - d2)
- t0 := tca - thc
- t1 := tca + thc
- if t0 > t1 {
- t0, t1 = t1, t0
- }
+ thc := math.Sqrt(s.radius*s.radius - d*d)
+ t0 := tca - thc
+ t1 := tca + thc
+ if t0 > t1 {
+ t0, t1 = t1, t0
+ }
- if t0 < 0 || t1 < 0 {
- return false
- }
+ if t0 < 0 || t1 < 0 {
+ return false
+ }
- return true
+ return true
}
func dotProduct(a geom.Vector, b geom.Vector) float64 {
- return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
}
func crossProduct(a geom.Vector, b geom.Vector) geom.Vector {
- return geom.NewVector(
- a.Y*b.Z-a.Z*b.Y,
- a.Z*b.X-a.X*b.Z,
- a.X*b.Y-a.Y*b.X)
+ return geom.NewVector(
+ a.Y*b.Z-a.Z*b.Y,
+ a.Z*b.X-a.X*b.Z,
+ a.X*b.Y-a.Y*b.X)
}
func addVectors(a, b geom.Vector) geom.Vector {
- return geom.NewVector(a.X+b.X, a.Y+b.Y, a.Z+b.Z)
+ return geom.NewVector(a.X+b.X, a.Y+b.Y, a.Z+b.Z)
}
func subtractVectors(a, b geom.Vector) geom.Vector {
- return geom.NewVector(a.X-b.X, a.Y-b.Y, a.Z-b.Z)
+ return geom.NewVector(a.X-b.X, a.Y-b.Y, a.Z-b.Z)
}
func scalarMultiply(vector geom.Vector, b float64) geom.Vector {
- return geom.NewVector(vector.X*b, vector.Y*b, vector.Z*b)
+ return geom.NewVector(vector.X*b, vector.Y*b, vector.Z*b)
}