Георги обнови решението на 18.11.2018 22:01 (преди 9 месеца)
+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+// Triangle represents a triangle in 3D space
+type Triangle struct {
+ A, B, C geom.Vector
+}
+
+// NewTriangle creates a new triangle
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{
+ a, b, c,
+ }
+}
+
+// Intersect returns true when `ray` intersects this object
+func (t Triangle) Intersect(ray geom.Ray) bool {
+ // normal of plane
+ normal := CrossProduct(Minus(t.B, t.A), Minus(t.C, t.A))
+
+ // are ray and plane parallel - find dot product of ray direction and normal
+ dot := DotProduct(normal, ray.Direction)
+ // small enough number, then they are parallel
+ if dot < 1e-6 {
+ return false
+ }
+
+ // calculate the free member of the plane ( Ax + By + Cz + D )
+ d := DotProduct(normal, t.A)
+
+ // ray eq is O + r*D - we rename t to r here because of triangle param
+ r := (DotProduct(normal, ray.Origin) + d) / dot
+
+ // intersection point between triangle plane and ray
+ p := Add(ray.Origin, Mul(ray.Direction, r))
+
+ // vector to determine if is p inside or outside the triangle
+ var intersect geom.Vector
+
+ // edge AB
+ ab := Minus(t.B, t.A)
+ intersect = CrossProduct(ab, Minus(p, t.A))
+ if DotProduct(normal, intersect) < 0 {
+ return false // intersect point is to the right of the edge
+ }
+
+ // edge BC
+ bc := Minus(t.C, t.B)
+ intersect = CrossProduct(bc, Minus(p, t.B))
+ if DotProduct(normal, intersect) < 0 {
+ return false // intersect point is to the right of the edge
+ }
+
+ // edge CA
+ ac := Minus(t.A, t.C)
+ intersect = CrossProduct(ac, Minus(p, t.C))
+ if DotProduct(normal, intersect) < 0 {
+ return false // intersect point is to the right of the edge
+ }
+
+ return true
+}
+
+// Sphere represents a sphere in 3D space
+type Sphere struct {
+ Origin geom.Vector
+ Radius float64
+}
+
+// NewSphere creates a new sphere
+func NewSphere(origin geom.Vector, radius float64) Sphere {
+ return Sphere{
+ origin,
+ radius,
+ }
+}
+
+// Intersect returns true when `ray` intersects this object
+func (s Sphere) Intersect(ray geom.Ray) bool {
+ // line segment between origin of ray and center of the sphere
+ line := Minus(s.Origin, ray.Origin)
+
+ // line is hypothenuse, finding length of adjacent side
+ adjacent := DotProduct(line, ray.Direction)
+
+ // opposite side - pythagorean theorem
+ opposite := Length(line)*Length(line) - adjacent*adjacent
+
+ return opposite < s.Radius*s.Radius
+}
+
+// Quad represents a four side polygon in 3D space
+type Quad struct {
+ A, B, C, D geom.Vector
+}
+
+// NewQuad creates a new quad
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{
+ a, b, c, d,
+ }
+}
+
+// Intersect returns true when `ray` intersects this object
+func (q Quad) Intersect(ray geom.Ray) bool {
+ t1 := NewTriangle(q.A, q.B, q.D)
+ t2 := NewTriangle(q.B, q.D, q.C)
+
+ return t1.Intersect(ray) || t2.Intersect(ray)
+}
+
+// Add adds two vectors
+func Add(v geom.Vector, other geom.Vector) geom.Vector {
+ return geom.NewVector(v.X+other.X, v.Y+other.Y, v.Z+other.Z)
+}
+
+// Minus subtracts two vectors
+func Minus(v geom.Vector, other geom.Vector) geom.Vector {
+ return geom.NewVector(v.X-other.X, v.Y-other.Y, v.Z-other.Z)
+}
+
+// CrossProduct calculates the cross product of two vectors
+func CrossProduct(v geom.Vector, other geom.Vector) geom.Vector {
+ return geom.NewVector(v.Y*other.Z-v.Z*other.Y, v.Z*other.X-v.X*other.Z, v.X*other.Y-v.Y*other.X)
+}
+
+// DotProduct calculates the dor product of two vectors
+func DotProduct(v geom.Vector, other geom.Vector) float64 {
+ return v.X*other.X + v.Y*other.Y + v.Z*other.Z
+}
+
+// Mul multiplies a vector by a constant value
+func Mul(v geom.Vector, c float64) geom.Vector {
+ return geom.NewVector(v.X*c, v.Y*c, v.Z*c)
+}
+
+// Length finds the length of a vector
+func Length(v geom.Vector) float64 {
+ return math.Sqrt(v.X*v.X + v.Y*v.Y + v.Z*v.Z)
+}
Разгледай уточненията на задачата и помисли дали наистина си ги спазил.
Кое точно налага махането на точка? Мисля, че е добре документирано всичко. Поне някакво обяснение ще е хубаво. :)
О, извинявай! Направил съм напълно обратното. Възнамерявах да ти дам допълнителна точка, точно заради добрата документация. Дори ако не беше и твоето решени, което ме накара да започна това. Оправих го :)
Благодаря. :)