Димитър обнови решението на 17.11.2018 20:16 (преди 9 месеца)
+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+const epsilon = 0.000000000000000000000000000001
Това ми се вижда малко прекалено. До такава степен, че е дори да не работи.
+
+type ConvexPolygon interface {
+ NormalVector() geom.Vector
+ Inside(point geom.Vector) bool
+ Parallel(ray geom.Ray) bool
+ GetA() geom.Vector
+}
+
+type Triangle struct {
+ A geom.Vector
+ B geom.Vector
+ C geom.Vector
+}
+
+type Quad struct {
+ A geom.Vector
+ B geom.Vector
+ C geom.Vector
+ 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 ScalarProduct(a, b geom.Vector) float64 {
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+}
+
+func VectorProduct(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 MixedProduct(a, b, c geom.Vector) float64 {
+ return ScalarProduct(a, VectorProduct(b, c))
+}
+
+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 Sum(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 (t Triangle) NormalVector() geom.Vector {
+ return VectorProduct(Subtract(t.B, t.A), Subtract(t.C, t.B))
+}
+
+func (q Quad) NormalVector() geom.Vector {
+ return VectorProduct(Subtract(q.B, q.A), Subtract(q.C, q.B))
+}
+
+func (t Triangle) Inside(point geom.Vector) bool {
+ firstSide := Subtract(t.B, t.A)
+ secondSide := Subtract(t.C, t.B)
+ thirdSide := Subtract(t.A, t.C)
+
+ return MixedProduct(t.NormalVector(), firstSide, Subtract(point, t.A)) > 0 &&
+ MixedProduct(t.NormalVector(), secondSide, Subtract(point, t.B)) > 0 &&
+ MixedProduct(t.NormalVector(), thirdSide, Subtract(point, t.C)) > 0
+}
+
+func (q Quad) Inside(point geom.Vector) bool {
+ firstSide := Subtract(q.B, q.A)
+ secondSide := Subtract(q.C, q.B)
+ thirdSide := Subtract(q.D, q.C)
+ fourthSide := Subtract(q.A, q.D)
+
+ return MixedProduct(q.NormalVector(), firstSide, Subtract(point, q.A)) > 0 &&
+ MixedProduct(q.NormalVector(), secondSide, Subtract(point, q.B)) > 0 &&
+ MixedProduct(q.NormalVector(), thirdSide, Subtract(point, q.C)) > 0 &&
+ MixedProduct(q.NormalVector(), fourthSide, Subtract(point, q.D)) > 0
+}
+
+func (s Sphere) Inside(point geom.Vector) bool {
+ return ScalarProduct(Subtract(s.Origin, point), Subtract(s.Origin, point)) <= s.R
+}
+
+func (t Triangle) Parallel(ray geom.Ray) bool {
+ return math.Abs(ScalarProduct(t.NormalVector(), ray.Direction)) < epsilon
+}
+
+func (q Quad) Parallel(ray geom.Ray) bool {
+ return math.Abs(ScalarProduct(q.NormalVector(), ray.Direction)) < epsilon
+}
+
+func (s Sphere) DifferentHalfspaces(ray geom.Ray) bool {
+ return ScalarProduct(Subtract(s.Origin, ray.Origin), ray.Direction) < 0
+}
+
+func (s Sphere) MinDistance(ray geom.Ray) float64 {
+ if ScalarProduct(ray.Direction, ray.Direction) > 0 {
+ return ScalarProduct(VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin)),
+ VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin))) / ScalarProduct(ray.Direction, ray.Direction)
+ }
+ return ScalarProduct(Subtract(s.Origin, ray.Origin), Subtract(s.Origin, ray.Origin))
+}
+
+func (t Triangle) GetA() geom.Vector {
+ return t.A
+}
+
+func (q Quad) GetA() geom.Vector {
+ return q.A
+}
+
+func IntersectConvexPolygons(cp ConvexPolygon, ray geom.Ray) bool {
+ if cp.Parallel(ray) {
+ return false
+ }
+
+ distanceFromOrigin := ScalarProduct(cp.NormalVector(), cp.GetA()) // from Origin to the triangle's plane
+ distanceFromRay := (distanceFromOrigin - ScalarProduct(cp.NormalVector(), ray.Origin)) / ScalarProduct(cp.NormalVector(), ray.Direction)
+
+ if distanceFromRay < 0 {
+ return false
+ }
+
+ //here whe know that the ray intersects with triangle's plane
+ point := Sum(ray.Origin, geom.Vector{X: distanceFromRay * ray.Direction.X, Y: distanceFromRay * ray.Direction.Y, Z: distanceFromRay * ray.Direction.Z})
+ return cp.Inside(point)
+}
+
+func (t Triangle) Intersect(ray geom.Ray) bool {
+ return IntersectConvexPolygons(t, ray)
+}
+
+func (q Quad) Intersect(ray geom.Ray) bool {
+ return IntersectConvexPolygons(q, ray)
+}
+
+func (s Sphere) Intersect(ray geom.Ray) bool {
+ if s.Inside(ray.Origin) {
+ return true
+ }
+ if s.DifferentHalfspaces(ray) {
+ return false
+ }
+ return s.MinDistance(ray) <= s.R*s.R
+}
Помисли за уточненията в условието на задачата.
Също така, мисля че можеш да подредиш файла си по - добре. В момента различните методи на типовете са мешани един с друг. Много по - лесно за четене ще е ако ги групираш по тип.