Решение на Пресичания от Хакан Халил

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

Към профила на Хакан Халил

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 20 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
import (
"github.com/fmi/go-homework/geom"
"math"
)
const epsilon float64 = 0.0000001
type Triangle struct {
a, b, c geom.Vector
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{a, b, c}
}
func (my Triangle) Intersect(ray geom.Ray) bool {
edge1 := subVectors(my.b, my.a)
edge2 := subVectors(my.c, my.a)
h := cross(ray.Direction, edge2)
a := dot(edge1, h)
if a > -epsilon && a < epsilon {
return false // parallel
}
f := 1.0 / a
s := subVectors(ray.Origin, my.a)
u := f * (dot(s, h))
if u < 0.0 || u > 1.0 {
return false
}
q := cross(s, edge1)
v := f * dot(ray.Direction, q)
if v < 0.0 || v > 1.0 {
return false
}
t := f * dot(edge2, q)
if t > epsilon {
return true
}
return false
}
type Quad struct {
a, b, c, d geom.Vector
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{a, b, c, d}
}
func (my Quad) Intersect(ray geom.Ray) bool {
if res, tr1, tr2 := hasConcave(&my); !res {
firstTriangle, secondTriangle, thirdTriangle := separateRect(my)
return firstTriangle.Intersect(ray) || secondTriangle.Intersect(ray) || thirdTriangle.Intersect(ray)
} else {
return tr1.Intersect(ray) || tr2.Intersect(ray)
}
}
func separateRect(rect Quad) (Triangle, Triangle, Triangle) {
return Triangle{rect.a, rect.b, rect.c},
Triangle{rect.a, rect.d, rect.c},
Triangle{rect.a, rect.d, rect.b}
}
type Sphere struct {
origin geom.Vector
r float64
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{origin, r}
}
func (my Sphere) Intersect(ray geom.Ray) bool {
vecL := subVectors(ray.Origin, my.origin)
a := dot(ray.Direction, ray.Direction)
b := 2 * dot(ray.Direction, vecL)
c := dot(vecL, vecL) - (my.r * my.r)
return solveQuadratic(a, b, c)
}
func dot(first, second geom.Vector) float64 {
return first.X*second.X + first.Y*second.Y + first.Z*second.Z
}
func cross(first, second geom.Vector) geom.Vector {
return geom.NewVector(first.Y*second.Z-first.Z*second.Y,
first.Z*second.X-first.X*second.Z,
first.X*second.Y-first.Y*second.X)
}
func subVectors(first, second geom.Vector) geom.Vector {
return geom.NewVector(first.X-second.X,
first.Y-second.Y,
first.Z-second.Z)
}
func solveQuadratic(a, b, c float64) bool {
discriminant := b*b - 4*a*c
x1 := (math.Sqrt(discriminant) - b) / (2 * a)
x2 := (-b - math.Sqrt(discriminant)) / (2 * a)
if discriminant < 0 || (x1 < 0 && x2 < 0) {
return false
}
return true
}
func hasConcave(myQuad *Quad) (bool, Triangle, Triangle) {
if dot(subVectors(myQuad.a, myQuad.b), subVectors(myQuad.c, myQuad.b)) < 0 {
return true, Triangle{myQuad.b, myQuad.d, myQuad.a},
Triangle{myQuad.b, myQuad.d, myQuad.c}
} else if dot(subVectors(myQuad.b, myQuad.c), subVectors(myQuad.d, myQuad.c)) < 0 {
return true, Triangle{myQuad.c, myQuad.a, myQuad.b},
Triangle{myQuad.c, myQuad.a, myQuad.d}
} else if dot(subVectors(myQuad.a, myQuad.d), subVectors(myQuad.c, myQuad.d)) < 0 {
return true, Triangle{myQuad.d, myQuad.b, myQuad.a},
Triangle{myQuad.d, myQuad.b, myQuad.c}
} else if dot(subVectors(myQuad.d, myQuad.a), subVectors(myQuad.b, myQuad.a)) < 0 {
return true, Triangle{myQuad.a, myQuad.c, myQuad.d},
Triangle{myQuad.a, myQuad.c, myQuad.b}
}
return false, Triangle{}, Triangle{}
}

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

PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.003s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s
PASS
ok  	_/tmp/d20181122-57-e5f76n	0.002s

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

Хакан обнови решението на 18.11.2018 14:50 (преди 9 месеца)

+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+const epsilon float64 = 0.0000001
+
+type Triangle struct {
+ a, b, c geom.Vector
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{a, b, c}
+}
+
+func (my Triangle) Intersect(ray geom.Ray) bool {
+ edge1 := subVectors(my.b, my.a)
+ edge2 := subVectors(my.c, my.a)
+ h := cross(ray.Direction, edge2)
+ a := dot(edge1, h)
+ if a > -epsilon && a < epsilon {
+ return false // parallel
+ }
+ f := 1.0 / a
+ s := subVectors(ray.Origin, my.a)
+ u := f * (dot(s, h))
+ if u < 0.0 || u > 1.0 {
+ return false
+ }
+ q := cross(s, edge1)
+ v := f * dot(ray.Direction, q)
+ if v < 0.0 || v > 1.0 {
+ return false
+ }
+ return true
+}
+
+type Quad struct {
+ a, b, c, d geom.Vector
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{a, b, c, d}
+}
+
+func (my Quad) Intersect(ray geom.Ray) bool {
+ firstTriangle, secondTriangle := separateRect(my)
+ return firstTriangle.Intersect(ray) || secondTriangle.Intersect(ray)
+}
+
+func separateRect(rect Quad) (Triangle, Triangle) {
+ return Triangle{rect.a, rect.b, rect.c}, Triangle{rect.a, rect.d, rect.c}
+}
+
+type Sphere struct {
+ origin geom.Vector
+ r float64
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{origin, r}
+}
+
+func (my Sphere) Intersect(ray geom.Ray) bool {
+ vecL := subVectors(ray.Origin, my.origin)
+ a := dot(ray.Direction, ray.Direction)
+ b := 2 * dot(ray.Direction, vecL)
+ c := dot(vecL, vecL) - (my.r * my.r)
+ return solveQuadratic(a, b, c)
+}
+
+func dot(first, second geom.Vector) float64 {
+ return first.X*second.X + first.Y*second.Y + first.Z*second.Z
+}
+
+func cross(first, second geom.Vector) geom.Vector {
+ return geom.NewVector(first.Y*second.Z-first.Z*second.Y,
+ first.Z*second.X-first.X*second.Z,
+ first.X*second.Y-first.Y*second.X)
+}
+
+func subVectors(first, second geom.Vector) geom.Vector {
+ return geom.NewVector(first.X-second.X,
+ first.Y-second.Y,
+ first.Z-second.Z)
+}
+
+func solveQuadratic(a, b, c float64) bool {
+ discriminant := b*b - 4*a*c
+ x1 := (math.Sqrt(discriminant) - b) / (2 * a)
+ x2 := (-b - math.Sqrt(discriminant)) / (2 * a)
+ if discriminant < 0 || (x1 < 0 && x2 < 0) {
+ return false
+ }
+ return true
+}

Хакан обнови решението на 20.11.2018 19:16 (преди 9 месеца)

package main
import (
"github.com/fmi/go-homework/geom"
"math"
)
const epsilon float64 = 0.0000001
type Triangle struct {
a, b, c geom.Vector
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{a, b, c}
}
func (my Triangle) Intersect(ray geom.Ray) bool {
edge1 := subVectors(my.b, my.a)
edge2 := subVectors(my.c, my.a)
h := cross(ray.Direction, edge2)
a := dot(edge1, h)
if a > -epsilon && a < epsilon {
return false // parallel
}
f := 1.0 / a
s := subVectors(ray.Origin, my.a)
u := f * (dot(s, h))
if u < 0.0 || u > 1.0 {
return false
}
q := cross(s, edge1)
v := f * dot(ray.Direction, q)
if v < 0.0 || v > 1.0 {
return false
}
- return true
+ t := f * dot(edge2, q)
+ if t > epsilon {
+ return true
+ }
+ return false
}
type Quad struct {
a, b, c, d geom.Vector
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{a, b, c, d}
}
func (my Quad) Intersect(ray geom.Ray) bool {
firstTriangle, secondTriangle := separateRect(my)
return firstTriangle.Intersect(ray) || secondTriangle.Intersect(ray)
}
func separateRect(rect Quad) (Triangle, Triangle) {
return Triangle{rect.a, rect.b, rect.c}, Triangle{rect.a, rect.d, rect.c}
}
type Sphere struct {
origin geom.Vector
r float64
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{origin, r}
}
func (my Sphere) Intersect(ray geom.Ray) bool {
vecL := subVectors(ray.Origin, my.origin)
a := dot(ray.Direction, ray.Direction)
b := 2 * dot(ray.Direction, vecL)
c := dot(vecL, vecL) - (my.r * my.r)
return solveQuadratic(a, b, c)
}
func dot(first, second geom.Vector) float64 {
return first.X*second.X + first.Y*second.Y + first.Z*second.Z
}
func cross(first, second geom.Vector) geom.Vector {
return geom.NewVector(first.Y*second.Z-first.Z*second.Y,
first.Z*second.X-first.X*second.Z,
first.X*second.Y-first.Y*second.X)
}
func subVectors(first, second geom.Vector) geom.Vector {
return geom.NewVector(first.X-second.X,
first.Y-second.Y,
first.Z-second.Z)
}
func solveQuadratic(a, b, c float64) bool {
discriminant := b*b - 4*a*c
x1 := (math.Sqrt(discriminant) - b) / (2 * a)
x2 := (-b - math.Sqrt(discriminant)) / (2 * a)
if discriminant < 0 || (x1 < 0 && x2 < 0) {
return false
}
return true
}

Хакан обнови решението на 20.11.2018 22:15 (преди 9 месеца)

package main
import (
"github.com/fmi/go-homework/geom"
"math"
)
const epsilon float64 = 0.0000001
type Triangle struct {
a, b, c geom.Vector
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{a, b, c}
}
func (my Triangle) Intersect(ray geom.Ray) bool {
edge1 := subVectors(my.b, my.a)
edge2 := subVectors(my.c, my.a)
h := cross(ray.Direction, edge2)
a := dot(edge1, h)
if a > -epsilon && a < epsilon {
return false // parallel
}
f := 1.0 / a
s := subVectors(ray.Origin, my.a)
u := f * (dot(s, h))
if u < 0.0 || u > 1.0 {
return false
}
q := cross(s, edge1)
v := f * dot(ray.Direction, q)
if v < 0.0 || v > 1.0 {
return false
}
t := f * dot(edge2, q)
if t > epsilon {
return true
}
return false
}
type Quad struct {
a, b, c, d geom.Vector
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{a, b, c, d}
}
func (my Quad) Intersect(ray geom.Ray) bool {
- firstTriangle, secondTriangle := separateRect(my)
- return firstTriangle.Intersect(ray) || secondTriangle.Intersect(ray)
+ if res, tr1, tr2 := hasConcave(&my); !res {
+ firstTriangle, secondTriangle, thirdTriangle := separateRect(my)
+ return firstTriangle.Intersect(ray) || secondTriangle.Intersect(ray) || thirdTriangle.Intersect(ray)
+ } else {
+ return tr1.Intersect(ray) || tr2.Intersect(ray)
+ }
}
-func separateRect(rect Quad) (Triangle, Triangle) {
- return Triangle{rect.a, rect.b, rect.c}, Triangle{rect.a, rect.d, rect.c}
+func separateRect(rect Quad) (Triangle, Triangle, Triangle) {
+ return Triangle{rect.a, rect.b, rect.c},
+ Triangle{rect.a, rect.d, rect.c},
+ Triangle{rect.a, rect.d, rect.b}
}
type Sphere struct {
origin geom.Vector
r float64
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{origin, r}
}
func (my Sphere) Intersect(ray geom.Ray) bool {
vecL := subVectors(ray.Origin, my.origin)
a := dot(ray.Direction, ray.Direction)
b := 2 * dot(ray.Direction, vecL)
c := dot(vecL, vecL) - (my.r * my.r)
return solveQuadratic(a, b, c)
}
func dot(first, second geom.Vector) float64 {
return first.X*second.X + first.Y*second.Y + first.Z*second.Z
}
func cross(first, second geom.Vector) geom.Vector {
return geom.NewVector(first.Y*second.Z-first.Z*second.Y,
first.Z*second.X-first.X*second.Z,
first.X*second.Y-first.Y*second.X)
}
func subVectors(first, second geom.Vector) geom.Vector {
return geom.NewVector(first.X-second.X,
first.Y-second.Y,
first.Z-second.Z)
}
func solveQuadratic(a, b, c float64) bool {
discriminant := b*b - 4*a*c
x1 := (math.Sqrt(discriminant) - b) / (2 * a)
x2 := (-b - math.Sqrt(discriminant)) / (2 * a)
if discriminant < 0 || (x1 < 0 && x2 < 0) {
return false
}
return true
+}
+
+func hasConcave(myQuad *Quad) (bool, Triangle, Triangle) {
+ if dot(subVectors(myQuad.a, myQuad.b), subVectors(myQuad.c, myQuad.b)) < 0 {
+ return true, Triangle{myQuad.b, myQuad.d, myQuad.a},
+ Triangle{myQuad.b, myQuad.d, myQuad.c}
+ } else if dot(subVectors(myQuad.b, myQuad.c), subVectors(myQuad.d, myQuad.c)) < 0 {
+ return true, Triangle{myQuad.c, myQuad.a, myQuad.b},
+ Triangle{myQuad.c, myQuad.a, myQuad.d}
+ } else if dot(subVectors(myQuad.a, myQuad.d), subVectors(myQuad.c, myQuad.d)) < 0 {
+ return true, Triangle{myQuad.d, myQuad.b, myQuad.a},
+ Triangle{myQuad.d, myQuad.b, myQuad.c}
+ } else if dot(subVectors(myQuad.d, myQuad.a), subVectors(myQuad.b, myQuad.a)) < 0 {
+ return true, Triangle{myQuad.a, myQuad.c, myQuad.d},
+ Triangle{myQuad.a, myQuad.c, myQuad.b}
+ }
+ return false, Triangle{}, Triangle{}
}