Решение на Пресичания от Божидар Каменов

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

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

Резултати

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

Код

package main
import (
"github.com/fmi/go-homework/geom"
"math"
)
func lengthSqr(v geom.Vector) float64 {
return v.X*v.X + v.Y*v.Y + v.Z*v.Z
}
func crossProd(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 dotProd(a, b geom.Vector) float64 {
return a.X*b.X + a.Y*b.Y + a.Z*b.Z
}
func det(a, b, c geom.Vector) float64 {
return dotProd(crossProd(a, b), c)
}
type Triangle struct {
A, B, C geom.Vector
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{a, b, c}
}
func (tr Triangle) Intersect(ray geom.Ray) bool {
AB := geom.Vector{X: tr.B.X - tr.A.X, Y: tr.B.Y - tr.A.Y, Z: tr.B.Z - tr.A.Z}
AC := geom.Vector{X: tr.C.X - tr.A.X, Y: tr.C.Y - tr.A.Y, Z: tr.C.Z - tr.A.Z}
D := geom.Vector{X: -ray.Direction.X, Y: -ray.Direction.Y, Z: -ray.Direction.Z}
Dcr := det(AB, AC, D)
if math.Abs(Dcr) < 1e-10 {
return false
}
H := geom.Vector{X: ray.Origin.X - tr.A.X, Y: ray.Origin.Y - tr.A.Y, Z: ray.Origin.Z - tr.A.Z}
lambda2 := det(H, AC, D) / Dcr
lambda3 := det(AB, H, D) / Dcr
gamma := det(AB, AC, H) / Dcr
lambda1 := 1 - (lambda2 + lambda3)
if lambda1 < 0 || gamma < 0 || lambda2 < 0 || lambda2 > 1 || lambda3 < 0 || lambda3 > 1 {
return false
}
return true
}
type Quad struct {
A, B Triangle
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{A: NewTriangle(a, b, c), B: NewTriangle(b, c, d)}
}
func (qd Quad) Intersect(ray geom.Ray) bool {
if qd.A.Intersect(ray) || qd.B.Intersect(ray) {
return true
} else {
return false
}
}
type Sphere struct {
origin geom.Vector
radius float64
}
func NewSphere(origin geom.Vector, radius float64) Sphere {
return Sphere{origin: origin, radius: radius}
}
func (sp Sphere) Intersect(ray geom.Ray) bool {
// p^2 * ray.dir.length^2 + p * (2 * dot(ray.dir, H)) + (H.length^2 - R^2) = 0
H := geom.Vector{X: ray.Origin.X - sp.origin.X, Y: ray.Origin.Y - sp.origin.Y, Z: ray.Origin.Z - sp.origin.Z}
A := lengthSqr(ray.Direction)
B := 2 * dotProd(ray.Direction, H)
C := lengthSqr(H) - sp.radius*sp.radius
Disc := B*B - 4*A*C
if Disc < 0 {
return false
}
sqrtDisc := math.Sqrt(Disc)
p1 := (-B + sqrtDisc) / (2 * A)
p2 := (-B - sqrtDisc) / (2 * A)
larger := math.Max(p1, p2)
if larger < 0 {
return false
}
return true
}

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

PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s
PASS
ok  	_/tmp/d20181122-57-19qvig1	0.002s

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

Божидар обнови решението на 17.11.2018 11:25 (преди 9 месеца)

+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+func lengthSqr(v geom.Vector) float64 {
+
+ return v.X*v.X + v.Y*v.Y + v.Z*v.Z
+}
+
+func crossProd(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 dotProd(a, b geom.Vector) float64 {
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+}
+
+func det(a, b, c geom.Vector) float64 {
+ return dotProd(crossProd(a, b), c)
+}
+
+type Triangle struct {
+ A, B, C geom.Vector
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{a, b, c}
+}
+
+func (tr Triangle) Intersect(ray geom.Ray) bool {
+
+ AB := geom.Vector{X: tr.B.X - tr.A.X, Y: tr.B.Y - tr.A.Y, Z: tr.B.Z - tr.A.Z}
+ AC := geom.Vector{X: tr.C.X - tr.A.X, Y: tr.C.Y - tr.A.Y, Z: tr.C.Z - tr.A.Z}
+ D := geom.Vector{X: -ray.Direction.X, Y: -ray.Direction.Y, Z: -ray.Direction.Z}
+
+ Dcr := det(AB, AC, D)
+ if math.Abs(Dcr) < 1e-10 {
+ return false
+ }
+
+ H := geom.Vector{X: ray.Origin.X - tr.A.X, Y: ray.Origin.Y - tr.A.Y, Z: ray.Origin.Z - tr.A.Z}
+
+ lambda2 := det(H, AC, D) / Dcr
+ lambda3 := det(AB, H, D) / Dcr
+ gamma := det(AB, AC, H) / Dcr
+
+ lambda1 := 1 - (lambda2 + lambda3)
+
+ if lambda1 < 0 || gamma < 0 || lambda2 < 0 || lambda2 > 1 || lambda3 < 0 || lambda3 > 1 {
+ return false
+ }
+
+ return true
+}
+
+type Quad struct {
+ A, B Triangle
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{A: NewTriangle(a, b, c), B: NewTriangle(b, c, d)}
+}
+
+func (qd Quad) Intersect(ray geom.Ray) bool {
+
+ if qd.A.Intersect(ray) || qd.B.Intersect(ray) {
+ return true
+ } else {
+ return false
+ }
+}
+
+type Sphere struct {
+ origin geom.Vector
+ radius float64
+}
+
+func NewSphere(origin geom.Vector, radius float64) Sphere {
+ return Sphere{origin: origin, radius: radius}
+}
+
+func (sp Sphere) Intersect(ray geom.Ray) bool {
+
+ // p^2 * ray.dir.length^2 + p * (2 * dot(ray.dir, H)) + (H.length^2 - R^2) = 0
+
+ H := geom.Vector{X: ray.Origin.X - sp.origin.X, Y: ray.Origin.Y - sp.origin.Y, Z: ray.Origin.Z - sp.origin.Z}
+
+ A := lengthSqr(ray.Direction)
+ B := 2 * dotProd(ray.Direction, H)
+ C := lengthSqr(H) - sp.radius*sp.radius
+
+ Disc := B*B - 4*A*C
+
+ if Disc < 0 {
+ return false
+ }
+
+ sqrtDisc := math.Sqrt(Disc)
+ p1 := (-B + sqrtDisc) / (2 * A)
+ p2 := (-B - sqrtDisc) / (2 * A)
+
+ larger := math.Max(p1, p2)
+
+ if larger < 0 {
+ return false
+ }
+
+ return true
+}