Решение на Пресичания от Павел Хаджиев

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

Към профила на Павел Хаджиев

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 9 успешни тест(а)
  • 11 неуспешни тест(а)

Код

package main
import (
"math"
"github.com/fmi/go-homework/geom"
)
type Triangle struct {
A, B, C geom.Vector
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{A: a, B: b, C: c}
}
type Quad struct {
A, B, C, D geom.Vector
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{A: a, B: b, C: c, D: d}
}
type Sphere struct {
Origin geom.Vector
R float64
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{Origin: origin, R: r}
}
func (triangle Triangle) Intersect(ray geom.Ray) bool {
// Describing the triangle's plane - ax + by + cz = d
AB := geom.Sub(triangle.B, triangle.A)
BC := geom.Sub(triangle.C, triangle.B)
n := geom.Cross(AB, BC) // normal vector
d := geom.Dot(n, triangle.A) // same for triangle.B and triangle.C
denom := geom.Dot(n, ray.Direction)
if math.Abs(d - denom) < 0.0000001 { // check if line is in the plane
return true
}
if math.Abs(denom) < 0.0000001 { // check if line is parallel to the plane
return false
}
distance := geom.Dot(n, geom.Sub(triangle.A, ray.Origin)) // the distance from the
P := geom.Add(ray.Origin, geom.Mul(ray.Direction, distance)) // the intersection point
edge0 := geom.Sub(triangle.B, triangle.A)
edge1 := geom.Sub(triangle.C, triangle.B)
edge2 := geom.Sub(triangle.A, triangle.C)
c0 := geom.Sub(P, triangle.A)
c1 := geom.Sub(P, triangle.B)
c2 := geom.Sub(P, triangle.C)
if (geom.Dot(n, geom.Cross(edge0, c0)) > 0.0000001 &&
geom.Dot(n, geom.Cross(edge1, c1)) > 0.0000001 &&
geom.Dot(n, geom.Cross(edge2, c2)) > 0.0000001) {
return true;
}
return false
}
func (quad Quad) Intersect(ray geom.Ray) bool {
// Splitting the quadrangle into four triangles and seeing if the ray is intersecting any of them
// If two of the triangles are intersected, and they are adjacent, the ray intersects the quadrangle.
// If the quadrangle is concave, will also be two triangles but they won't be adjacent.
t1 := NewTriangle(quad.A, quad.B, quad.C)
t2 := NewTriangle(quad.B, quad.C, quad.D)
t3 := NewTriangle(quad.C, quad.D, quad.A)
t4 := NewTriangle(quad.D, quad.A, quad.B)
i1 := t1.Intersect(ray)
i2 := t2.Intersect(ray)
i3 := t3.Intersect(ray)
i4 := t4.Intersect(ray)
if (i1 && i2) || (i2 && i3) || (i3 && i4) || (i4 && i1) {
return true
}
return false
}
func (sphere Sphere) Intersect(ray geom.Ray) bool {
originSub := geom.Sub(ray.Origin, sphere.Origin)
originSubSquared := geom.Dot(originSub, originSub)
originSubRayDirectionDot := geom.Dot(originSub, ray.Direction)
determinant := math.Pow(originSubRayDirectionDot, 2) - originSubSquared - math.Pow(sphere.R, 2)
if determinant >= 0 {
return true // if determinant is 0, the ray touches the sphere, if larger it goes through it.
}
return false
}

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

PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
--- 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-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	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-18l1lh1	0.002s
--- FAIL: TestQuadSimpleIntersection (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-18l1lh1	0.002s
--- FAIL: TestQuadNoBackFaceCulling (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
--- 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-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
--- FAIL: TestQuadIrregularHit (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-18l1lh1	0.002s
--- FAIL: TestQuadSecondIrregularHit (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-18l1lh1	0.002s
--- FAIL: TestQuadThirdIrregularHit (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
PASS
ok  	_/tmp/d20181122-57-18l1lh1	0.002s
--- FAIL: TestSphereNoBackFaceCulling (0.00s)
    solution_test.go:206: Expected intersection to be true but it was not
FAIL
exit status 1
FAIL	_/tmp/d20181122-57-18l1lh1	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-18l1lh1	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-18l1lh1	0.002s

История (2 версии и 0 коментара)

Павел обнови решението на 21.11.2018 13:21 (преди 9 месеца)

+package main
+
+import (
+ "math"
+ "github.com/fmi/go-homework/geom"
+)
+
+type Triangle struct {
+ A, B, C geom.Vector
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{A: a, B: b, C: c}
+}
+
+type Quad struct {
+ A, B, C, D geom.Vector
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{A: a, B: b, C: c, D: d}
+}
+
+type Sphere struct {
+ Origin geom.Vector
+ R float64
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{Origin: origin, R: r}
+}
+
+func (triangle Triangle) Intersect(ray geom.Ray) bool {
+ // Describing the triangle's plane - ax + by + cz = d
+ AB := geom.Sub(triangle.B, triangle.A)
+ BC := geom.Sub(triangle.C, triangle.B)
+ n := geom.Cross(AB, BC) // normal vector
+ d := geom.Dot(n, triangle.A) // same for triangle.B and triangle.C
+
+ denom := geom.Dot(n, ray.Direction)
+
+ if math.Abs(d - denom) < 0.0000001 { // check if line is in the plane
+ return true
+ }
+
+ if math.Abs(denom) < 0.0000001 { // check if line is parallel to the plane
+ return false
+ }
+
+ distance := geom.Dot(n, geom.Sub(triangle.A, ray.Origin)) // the distance from the
+ P := geom.Add(ray.Origin, geom.Mul(ray.Direction, distance)) // the intersection point
+
+ edge0 := geom.Sub(triangle.B, triangle.A)
+ edge1 := geom.Sub(triangle.C, triangle.B)
+ edge2 := geom.Sub(triangle.A, triangle.C)
+
+ c0 := geom.Sub(P, triangle.A)
+ c1 := geom.Sub(P, triangle.B)
+ c2 := geom.Sub(P, triangle.C)
+
+ if (geom.Dot(n, geom.Cross(edge0, c0)) > 0.0000001 &&
+ geom.Dot(n, geom.Cross(edge1, c1)) > 0.0000001 &&
+ geom.Dot(n, geom.Cross(edge2, c2)) > 0.0000001) {
+ return true;
+ }
+
+ return false
+}
+
+func (quad Quad) Intersect(ray geom.Ray) bool {
+ // TODO
+ return true
+}
+
+func (sphere Sphere) Intersect(ray geom.Ray) bool {
+ originSub := geom.Sub(ray.Origin, sphere.Origin)
+ originSubSquared := geom.Dot(originSub, originSub)
+ originSubRayDirectionDot := geom.Dot(originSub, ray.Direction)
+ determinant := math.Pow(originSubRayDirectionDot, 2) - originSubSquared - math.Pow(sphere.R, 2)
+ if determinant >= 0 {
+ return true // if determinant is 0, the ray touches the sphere, if larger it goes through it.
+ }
+ return false
+}

Павел обнови решението на 21.11.2018 14:35 (преди 9 месеца)

package main
import (
"math"
"github.com/fmi/go-homework/geom"
)
type Triangle struct {
A, B, C geom.Vector
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{A: a, B: b, C: c}
}
type Quad struct {
A, B, C, D geom.Vector
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{A: a, B: b, C: c, D: d}
}
type Sphere struct {
Origin geom.Vector
R float64
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{Origin: origin, R: r}
}
func (triangle Triangle) Intersect(ray geom.Ray) bool {
// Describing the triangle's plane - ax + by + cz = d
AB := geom.Sub(triangle.B, triangle.A)
BC := geom.Sub(triangle.C, triangle.B)
n := geom.Cross(AB, BC) // normal vector
d := geom.Dot(n, triangle.A) // same for triangle.B and triangle.C
denom := geom.Dot(n, ray.Direction)
if math.Abs(d - denom) < 0.0000001 { // check if line is in the plane
return true
}
if math.Abs(denom) < 0.0000001 { // check if line is parallel to the plane
return false
}
distance := geom.Dot(n, geom.Sub(triangle.A, ray.Origin)) // the distance from the
P := geom.Add(ray.Origin, geom.Mul(ray.Direction, distance)) // the intersection point
edge0 := geom.Sub(triangle.B, triangle.A)
edge1 := geom.Sub(triangle.C, triangle.B)
edge2 := geom.Sub(triangle.A, triangle.C)
c0 := geom.Sub(P, triangle.A)
c1 := geom.Sub(P, triangle.B)
c2 := geom.Sub(P, triangle.C)
if (geom.Dot(n, geom.Cross(edge0, c0)) > 0.0000001 &&
geom.Dot(n, geom.Cross(edge1, c1)) > 0.0000001 &&
geom.Dot(n, geom.Cross(edge2, c2)) > 0.0000001) {
return true;
}
return false
}
func (quad Quad) Intersect(ray geom.Ray) bool {
- // TODO
- return true
+ // Splitting the quadrangle into four triangles and seeing if the ray is intersecting any of them
+ // If two of the triangles are intersected, and they are adjacent, the ray intersects the quadrangle.
+ // If the quadrangle is concave, will also be two triangles but they won't be adjacent.
+
+ t1 := NewTriangle(quad.A, quad.B, quad.C)
+ t2 := NewTriangle(quad.B, quad.C, quad.D)
+ t3 := NewTriangle(quad.C, quad.D, quad.A)
+ t4 := NewTriangle(quad.D, quad.A, quad.B)
+
+ i1 := t1.Intersect(ray)
+ i2 := t2.Intersect(ray)
+ i3 := t3.Intersect(ray)
+ i4 := t4.Intersect(ray)
+
+ if (i1 && i2) || (i2 && i3) || (i3 && i4) || (i4 && i1) {
+ return true
+ }
+
+ return false
}
func (sphere Sphere) Intersect(ray geom.Ray) bool {
originSub := geom.Sub(ray.Origin, sphere.Origin)
originSubSquared := geom.Dot(originSub, originSub)
originSubRayDirectionDot := geom.Dot(originSub, ray.Direction)
determinant := math.Pow(originSubRayDirectionDot, 2) - originSubSquared - math.Pow(sphere.R, 2)
if determinant >= 0 {
return true // if determinant is 0, the ray touches the sphere, if larger it goes through it.
}
return false
}