Даяна обнови решението на 21.11.2018 09:29 (преди 9 месеца)
+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+type Vector struct {
+ X, Y, Z float64
+}
+
+type Ray struct {
+ Origin Vector
+ Direction Vector
+}
+
+type Intersectable interface {
+ Intersect(ray Ray) bool
+}
+
+type Triangle struct {
+ A, B, C float64
+ a, b, c geom.Vector
+}
+
+type Sphere struct {
+ rad float64
+ origin geom.Vector
+}
+
+type Quad struct {
+ tr, tr2 Triangle
+ a, b, c, d geom.Vector
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ var sideA = math.Sqrt(math.Pow((c.X-b.X), 2) + math.Pow((c.Y-b.Y), 2) + math.Pow((c.Z-b.Z), 2))
+ var sideB = math.Sqrt(math.Pow((a.X-b.X), 2) + math.Pow((a.Y-b.Y), 2) + math.Pow((a.Z-b.Z), 2))
+ var sideC = math.Sqrt(math.Pow((a.X-c.X), 2) + math.Pow((a.Y-c.Y), 2) + math.Pow((a.Z-c.Z), 2))
+
+ if sideA+sideB > sideC && sideB+sideC > sideA && sideA+sideC > sideB {
+ return Triangle{sideA, sideB, sideC, a, b, c}
+ }
+
+ return Triangle{0, 0, 0, geom.NewVector(0, 0, 0), geom.NewVector(0, 0, 0), geom.NewVector(0, 0, 0)}
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ tr := NewTriangle(a, b, c)
+ tr2 := NewTriangle(a, b, d)
+
+ return Quad{tr, tr2, a, b, c, d}
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{r, origin}
+}
+
+func (tr Triangle) Intersect(ray geom.Ray) bool {
+ var norm geom.Vector
+ originNorm := geom.NewVector(0, 0, 0)
+ norm = geom.Cross(geom.Sub(tr.b, tr.a), geom.Sub(tr.c, tr.a))
+ dir := geom.NewVector(ray.Direction.X, ray.Direction.Y, ray.Direction.Z)
+ origin := geom.NewVector(ray.Origin.X, ray.Origin.Y, ray.Origin.Z)
+
+ denom := geom.Dot(norm, dir)
+
+ if denom > 1e-7 {
+ t := geom.Dot(geom.Sub(originNorm, origin), norm) / denom
+ return (t >= 0)
+ }
+
+ return false
+
+}
+
+func (qu Quad) Intersect(ray geom.Ray) bool {
+ if qu.tr.Intersect(ray) || qu.tr2.Intersect(ray) {
+ return true
+ }
+
+ return false
+}
+
+func (sp Sphere) Intersect(ray geom.Ray) bool {
+ originNorm := ray.Origin
+ tr := NewTriangle(geom.NewVector(sp.rad, 0, 0), geom.NewVector(0, sp.rad, 0), geom.NewVector(0, 0, sp.rad))
+ tr2 := NewTriangle(geom.NewVector(sp.rad, sp.rad, 0), geom.NewVector(0, sp.rad, sp.rad), geom.NewVector(sp.rad, 0, sp.rad))
+ norm := geom.Cross(geom.Sub(tr.b, tr.a), geom.Sub(tr.c, tr.a))
+ norm2 := geom.Cross(geom.Sub(tr2.b, tr2.a), geom.Sub(tr2.c, tr2.a))
+ t := geom.Dot(geom.Sub(originNorm, ray.Origin), norm) / geom.Dot(ray.Direction, norm)
+ t2 := geom.Dot(geom.Sub(originNorm, ray.Origin), norm2) / geom.Dot(ray.Direction, norm2)
+
+ if tr.Intersect(ray) {
+ newVec := geom.Sub(geom.Add(ray.Origin, geom.Mul(ray.Direction, t)), originNorm)
+ return (math.Sqrt(geom.Dot(newVec, newVec)) <= sp.rad)
+ } else if tr2.Intersect(ray) {
+ newVec := geom.Sub(geom.Add(ray.Origin, geom.Mul(ray.Direction, t2)), originNorm)
+ return (math.Sqrt(geom.Dot(newVec, newVec)) <= sp.rad)
+ }
+
+ return false
+}
Прочети внимателно уточненията в условието. Пресечи фигурите си от двете страни, например.