Божидар обнови решението на 17.11.2018 11:25 (преди 9 месеца)
+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+func lengthSqr(v geom.Vector) float64 {
+
+ return v.X*v.X + v.Y*v.Y + v.Z*v.Z
+}
+
+func crossProd(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 dotProd(a, b geom.Vector) float64 {
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+}
+
+func det(a, b, c geom.Vector) float64 {
+ return dotProd(crossProd(a, b), c)
+}
+
+type Triangle struct {
+ A, B, C geom.Vector
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{a, b, c}
+}
+
+func (tr Triangle) Intersect(ray geom.Ray) bool {
+
+ AB := geom.Vector{X: tr.B.X - tr.A.X, Y: tr.B.Y - tr.A.Y, Z: tr.B.Z - tr.A.Z}
+ AC := geom.Vector{X: tr.C.X - tr.A.X, Y: tr.C.Y - tr.A.Y, Z: tr.C.Z - tr.A.Z}
+ D := geom.Vector{X: -ray.Direction.X, Y: -ray.Direction.Y, Z: -ray.Direction.Z}
+
+ Dcr := det(AB, AC, D)
+ if math.Abs(Dcr) < 1e-10 {
Помисли внимателно за уточненията в условието.
+ return false
+ }
+
+ H := geom.Vector{X: ray.Origin.X - tr.A.X, Y: ray.Origin.Y - tr.A.Y, Z: ray.Origin.Z - tr.A.Z}
+
+ lambda2 := det(H, AC, D) / Dcr
+ lambda3 := det(AB, H, D) / Dcr
+ gamma := det(AB, AC, H) / Dcr
+
+ lambda1 := 1 - (lambda2 + lambda3)
+
+ if lambda1 < 0 || gamma < 0 || lambda2 < 0 || lambda2 > 1 || lambda3 < 0 || lambda3 > 1 {
+ return false
+ }
+
+ return true
+}
+
+type Quad struct {
+ A, B Triangle
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{A: NewTriangle(a, b, c), B: NewTriangle(b, c, d)}
+}
+
+func (qd Quad) Intersect(ray geom.Ray) bool {
+
+ if qd.A.Intersect(ray) || qd.B.Intersect(ray) {
+ return true
+ } else {
Нямаш нужда от този else
. Можеш да оставиш return false
отвън и ще е същото нещо, но много по - лесно за четене.
+ return false
+ }
+}
+
+type Sphere struct {
+ origin geom.Vector
+ radius float64
+}
+
+func NewSphere(origin geom.Vector, radius float64) Sphere {
+ return Sphere{origin: origin, radius: radius}
+}
+
+func (sp Sphere) Intersect(ray geom.Ray) bool {
+
+ // p^2 * ray.dir.length^2 + p * (2 * dot(ray.dir, H)) + (H.length^2 - R^2) = 0
+
+ H := geom.Vector{X: ray.Origin.X - sp.origin.X, Y: ray.Origin.Y - sp.origin.Y, Z: ray.Origin.Z - sp.origin.Z}
+
+ A := lengthSqr(ray.Direction)
+ B := 2 * dotProd(ray.Direction, H)
+ C := lengthSqr(H) - sp.radius*sp.radius
+
+ Disc := B*B - 4*A*C
+
+ if Disc < 0 {
+ return false
+ }
+
+ sqrtDisc := math.Sqrt(Disc)
+ p1 := (-B + sqrtDisc) / (2 * A)
+ p2 := (-B - sqrtDisc) / (2 * A)
+
+ larger := math.Max(p1, p2)
+
+ if larger < 0 {
+ return false
+ }
+
+ return true
+}
Помисли внимателно за уточненията в условието.
Нямаш нужда от този
else
. Можеш да оставишreturn false
отвън и ще е същото нещо, но много по - лесно за четене.