Решение на Пресичания от Георги Божинов

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

Към профила на Георги Божинов

Резултати

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

Код

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)
}

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

PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
--- FAIL: TestTriangleNoBackFaceCulling (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-7046iw	0.003s
--- FAIL: TestTriangleRayOppositeDirection (0.00s)
    solution_test.go:206: Expected intersection to be false but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
--- FAIL: TestTriangleRayOriginReallyCloseToObject (0.00s)
    solution_test.go:206: Expected intersection to be false but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
--- FAIL: TestQuadRayOppositeDirection (0.00s)
    solution_test.go:206: Expected intersection to be false but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.003s
--- 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-7046iw	0.002s
--- FAIL: TestQuadOriginReallyClosedToObject (0.00s)
    solution_test.go:206: Expected intersection to be false but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	0.002s
PASS
ok  	_/tmp/d20181122-57-7046iw	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-7046iw	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-7046iw	0.002s

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

Георги обнови решението на 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)
+}

О, извинявай! Направил съм напълно обратното. Възнамерявах да ти дам допълнителна точка, точно заради добрата документация. Дори ако не беше и твоето решени, което ме накара да започна това. Оправих го :)