Решение на Пресичания от Димитър Петров

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

Към профила на Димитър Петров

Резултати

  • 10 точки от тестове
  • 1 отнета точка
  • 9 точки общо
  • 19 успешни тест(а)
  • 1 неуспешни тест(а)

Код

package main
import (
"github.com/fmi/go-homework/geom"
"math"
)
const epsilon = 1e-7
type Triangle struct {
A geom.Vector
B geom.Vector
C geom.Vector
}
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{A: a, B: b, C: c}
}
func (t Triangle) NormalVector() geom.Vector {
return VectorProduct(Subtract(t.B, t.A), Subtract(t.C, t.B))
}
func (t Triangle) Inside(point geom.Vector) bool {
firstSide := Subtract(t.B, t.A)
secondSide := Subtract(t.C, t.B)
thirdSide := Subtract(t.A, t.C)
return MixedProduct(t.NormalVector(), firstSide, Subtract(point, t.A)) > 0 &&
MixedProduct(t.NormalVector(), secondSide, Subtract(point, t.B)) > 0 &&
MixedProduct(t.NormalVector(), thirdSide, Subtract(point, t.C)) > 0
}
func (t Triangle) Parallel(ray geom.Ray) bool {
return math.Abs(ScalarProduct(t.NormalVector(), ray.Direction)) < epsilon
}
func (t Triangle) GetA() geom.Vector {
return t.A
}
func (t Triangle) Intersect(ray geom.Ray) bool {
return IntersectConvexPolygons(t, ray)
}
type Quad struct {
A geom.Vector
B geom.Vector
C geom.Vector
D geom.Vector
}
func NewQuad(a, b, c, d geom.Vector) Quad {
return Quad{A: a, B: b, C: c, D: d}
}
func (q Quad) NormalVector() geom.Vector {
return VectorProduct(Subtract(q.B, q.A), Subtract(q.C, q.B))
}
func (q Quad) Inside(point geom.Vector) bool {
firstSide := Subtract(q.B, q.A)
secondSide := Subtract(q.C, q.B)
thirdSide := Subtract(q.D, q.C)
fourthSide := Subtract(q.A, q.D)
return MixedProduct(q.NormalVector(), firstSide, Subtract(point, q.A)) > 0 &&
MixedProduct(q.NormalVector(), secondSide, Subtract(point, q.B)) > 0 &&
MixedProduct(q.NormalVector(), thirdSide, Subtract(point, q.C)) > 0 &&
MixedProduct(q.NormalVector(), fourthSide, Subtract(point, q.D)) > 0
}
func (q Quad) Parallel(ray geom.Ray) bool {
return math.Abs(ScalarProduct(q.NormalVector(), ray.Direction)) < epsilon
}
func (q Quad) GetA() geom.Vector {
return q.A
}
func (q Quad) Intersect(ray geom.Ray) bool {
return IntersectConvexPolygons(q, ray)
}
type Sphere struct {
Origin geom.Vector
R float64
}
func NewSphere(origin geom.Vector, r float64) Sphere {
return Sphere{Origin: origin, R: r}
}
func (s Sphere) Inside(point geom.Vector) bool {
return ScalarProduct(Subtract(s.Origin, point), Subtract(s.Origin, point)) <= s.R
}
func (s Sphere) DifferentHalfspaces(ray geom.Ray) bool {
return ScalarProduct(Subtract(s.Origin, ray.Origin), ray.Direction) < 0
}
func (s Sphere) MinDistance(ray geom.Ray) float64 {
if ScalarProduct(ray.Direction, ray.Direction) > 0 {
return ScalarProduct(VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin)),
VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin))) / ScalarProduct(ray.Direction, ray.Direction)
}
return ScalarProduct(Subtract(s.Origin, ray.Origin), Subtract(s.Origin, ray.Origin))
}
func (s Sphere) Intersect(ray geom.Ray) bool {
if s.Inside(ray.Origin) {
return true
}
if s.DifferentHalfspaces(ray) {
return false
}
return s.MinDistance(ray) <= s.R*s.R
}
type ConvexPolygon interface {
NormalVector() geom.Vector
Inside(point geom.Vector) bool
Parallel(ray geom.Ray) bool
GetA() geom.Vector
}
func IntersectConvexPolygons(cp ConvexPolygon, ray geom.Ray) bool {
if cp.Parallel(ray) {
return false
}
distanceFromOrigin := ScalarProduct(cp.NormalVector(), cp.GetA()) // from Origin to the triangle's plane
distanceFromRay := (distanceFromOrigin - ScalarProduct(cp.NormalVector(), ray.Origin)) / ScalarProduct(cp.NormalVector(), ray.Direction)
if distanceFromRay < 0 {
return false
}
//here whe know that the ray intersects with triangle's plane
point := Sum(ray.Origin, geom.Vector{X: distanceFromRay * ray.Direction.X, Y: distanceFromRay * ray.Direction.Y, Z: distanceFromRay * ray.Direction.Z})
return cp.Inside(point)
}
func ScalarProduct(a, b geom.Vector) float64 {
return a.X*b.X + a.Y*b.Y + a.Z*b.Z
}
func VectorProduct(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 MixedProduct(a, b, c geom.Vector) float64 {
return ScalarProduct(a, VectorProduct(b, c))
}
func Subtract(a, b geom.Vector) geom.Vector {
return geom.Vector{X: a.X - b.X, Y: a.Y - b.Y, Z: a.Z - b.Z}
}
func Sum(a, b geom.Vector) geom.Vector {
return geom.Vector{X: a.X + b.X, Y: a.Y + b.Y, Z: a.Z + b.Z}
}

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

PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.003s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	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-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s
PASS
ok  	_/tmp/d20181122-57-z5y8yz	0.002s

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

Димитър обнови решението на 17.11.2018 20:16 (преди 9 месеца)

+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+const epsilon = 0.000000000000000000000000000001
+
+type ConvexPolygon interface {
+ NormalVector() geom.Vector
+ Inside(point geom.Vector) bool
+ Parallel(ray geom.Ray) bool
+ GetA() geom.Vector
+}
+
+type Triangle struct {
+ A geom.Vector
+ B geom.Vector
+ C geom.Vector
+}
+
+type Quad struct {
+ A geom.Vector
+ B geom.Vector
+ C geom.Vector
+ D geom.Vector
+}
+
+type Sphere struct {
+ Origin geom.Vector
+ R float64
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{A: a, B: b, C: c}
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{A: a, B: b, C: c, D: d}
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{Origin: origin, R: r}
+}
+
+func ScalarProduct(a, b geom.Vector) float64 {
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+}
+
+func VectorProduct(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 MixedProduct(a, b, c geom.Vector) float64 {
+ return ScalarProduct(a, VectorProduct(b, c))
+}
+
+func Subtract(a, b geom.Vector) geom.Vector {
+ return geom.Vector{X: a.X - b.X, Y: a.Y - b.Y, Z: a.Z - b.Z}
+}
+
+func Sum(a, b geom.Vector) geom.Vector {
+ return geom.Vector{X: a.X + b.X, Y: a.Y + b.Y, Z: a.Z + b.Z}
+}
+
+func (t Triangle) NormalVector() geom.Vector {
+ return VectorProduct(Subtract(t.B, t.A), Subtract(t.C, t.B))
+}
+
+func (q Quad) NormalVector() geom.Vector {
+ return VectorProduct(Subtract(q.B, q.A), Subtract(q.C, q.B))
+}
+
+func (t Triangle) Inside(point geom.Vector) bool {
+ firstSide := Subtract(t.B, t.A)
+ secondSide := Subtract(t.C, t.B)
+ thirdSide := Subtract(t.A, t.C)
+
+ return MixedProduct(t.NormalVector(), firstSide, Subtract(point, t.A)) > 0 &&
+ MixedProduct(t.NormalVector(), secondSide, Subtract(point, t.B)) > 0 &&
+ MixedProduct(t.NormalVector(), thirdSide, Subtract(point, t.C)) > 0
+}
+
+func (q Quad) Inside(point geom.Vector) bool {
+ firstSide := Subtract(q.B, q.A)
+ secondSide := Subtract(q.C, q.B)
+ thirdSide := Subtract(q.D, q.C)
+ fourthSide := Subtract(q.A, q.D)
+
+ return MixedProduct(q.NormalVector(), firstSide, Subtract(point, q.A)) > 0 &&
+ MixedProduct(q.NormalVector(), secondSide, Subtract(point, q.B)) > 0 &&
+ MixedProduct(q.NormalVector(), thirdSide, Subtract(point, q.C)) > 0 &&
+ MixedProduct(q.NormalVector(), fourthSide, Subtract(point, q.D)) > 0
+}
+
+func (s Sphere) Inside(point geom.Vector) bool {
+ return ScalarProduct(Subtract(s.Origin, point), Subtract(s.Origin, point)) <= s.R
+}
+
+func (t Triangle) Parallel(ray geom.Ray) bool {
+ return math.Abs(ScalarProduct(t.NormalVector(), ray.Direction)) < epsilon
+}
+
+func (q Quad) Parallel(ray geom.Ray) bool {
+ return math.Abs(ScalarProduct(q.NormalVector(), ray.Direction)) < epsilon
+}
+
+func (s Sphere) DifferentHalfspaces(ray geom.Ray) bool {
+ return ScalarProduct(Subtract(s.Origin, ray.Origin), ray.Direction) < 0
+}
+
+func (s Sphere) MinDistance(ray geom.Ray) float64 {
+ if ScalarProduct(ray.Direction, ray.Direction) > 0 {
+ return ScalarProduct(VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin)),
+ VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin))) / ScalarProduct(ray.Direction, ray.Direction)
+ }
+ return ScalarProduct(Subtract(s.Origin, ray.Origin), Subtract(s.Origin, ray.Origin))
+}
+
+func (t Triangle) GetA() geom.Vector {
+ return t.A
+}
+
+func (q Quad) GetA() geom.Vector {
+ return q.A
+}
+
+func IntersectConvexPolygons(cp ConvexPolygon, ray geom.Ray) bool {
+ if cp.Parallel(ray) {
+ return false
+ }
+
+ distanceFromOrigin := ScalarProduct(cp.NormalVector(), cp.GetA()) // from Origin to the triangle's plane
+ distanceFromRay := (distanceFromOrigin - ScalarProduct(cp.NormalVector(), ray.Origin)) / ScalarProduct(cp.NormalVector(), ray.Direction)
+
+ if distanceFromRay < 0 {
+ return false
+ }
+
+ //here whe know that the ray intersects with triangle's plane
+ point := Sum(ray.Origin, geom.Vector{X: distanceFromRay * ray.Direction.X, Y: distanceFromRay * ray.Direction.Y, Z: distanceFromRay * ray.Direction.Z})
+ return cp.Inside(point)
+}
+
+func (t Triangle) Intersect(ray geom.Ray) bool {
+ return IntersectConvexPolygons(t, ray)
+}
+
+func (q Quad) Intersect(ray geom.Ray) bool {
+ return IntersectConvexPolygons(q, ray)
+}
+
+func (s Sphere) Intersect(ray geom.Ray) bool {
+ if s.Inside(ray.Origin) {
+ return true
+ }
+ if s.DifferentHalfspaces(ray) {
+ return false
+ }
+ return s.MinDistance(ray) <= s.R*s.R
+}

Помисли за уточненията в условието на задачата.

Също така, мисля че можеш да подредиш файла си по - добре. В момента различните методи на типовете са мешани един с друг. Много по - лесно за четене ще е ако ги групираш по тип.

Димитър обнови решението на 21.11.2018 13:56 (преди 9 месеца)

package main
import (
"github.com/fmi/go-homework/geom"
"math"
)
-const epsilon = 0.000000000000000000000000000001
+const epsilon = 1e-7
-type ConvexPolygon interface {
- NormalVector() geom.Vector
- Inside(point geom.Vector) bool
- Parallel(ray geom.Ray) bool
- GetA() geom.Vector
-}
-
type Triangle struct {
A geom.Vector
B geom.Vector
C geom.Vector
}
-type Quad struct {
- A geom.Vector
- B geom.Vector
- C geom.Vector
- D geom.Vector
-}
-
-type Sphere struct {
- Origin geom.Vector
- R float64
-}
-
func NewTriangle(a, b, c geom.Vector) Triangle {
return Triangle{A: a, B: b, C: c}
}
-func NewQuad(a, b, c, d geom.Vector) Quad {
- return Quad{A: a, B: b, C: c, D: d}
+func (t Triangle) NormalVector() geom.Vector {
+ return VectorProduct(Subtract(t.B, t.A), Subtract(t.C, t.B))
}
-func NewSphere(origin geom.Vector, r float64) Sphere {
- return Sphere{Origin: origin, R: r}
-}
+func (t Triangle) Inside(point geom.Vector) bool {
+ firstSide := Subtract(t.B, t.A)
+ secondSide := Subtract(t.C, t.B)
+ thirdSide := Subtract(t.A, t.C)
-func ScalarProduct(a, b geom.Vector) float64 {
- return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+ return MixedProduct(t.NormalVector(), firstSide, Subtract(point, t.A)) > 0 &&
+ MixedProduct(t.NormalVector(), secondSide, Subtract(point, t.B)) > 0 &&
+ MixedProduct(t.NormalVector(), thirdSide, Subtract(point, t.C)) > 0
}
-func VectorProduct(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 (t Triangle) Parallel(ray geom.Ray) bool {
+ return math.Abs(ScalarProduct(t.NormalVector(), ray.Direction)) < epsilon
}
-func MixedProduct(a, b, c geom.Vector) float64 {
- return ScalarProduct(a, VectorProduct(b, c))
+func (t Triangle) GetA() geom.Vector {
+ return t.A
}
-func Subtract(a, b geom.Vector) geom.Vector {
- return geom.Vector{X: a.X - b.X, Y: a.Y - b.Y, Z: a.Z - b.Z}
+func (t Triangle) Intersect(ray geom.Ray) bool {
+ return IntersectConvexPolygons(t, ray)
}
-func Sum(a, b geom.Vector) geom.Vector {
- return geom.Vector{X: a.X + b.X, Y: a.Y + b.Y, Z: a.Z + b.Z}
+type Quad struct {
+ A geom.Vector
+ B geom.Vector
+ C geom.Vector
+ D geom.Vector
}
-func (t Triangle) NormalVector() geom.Vector {
- return VectorProduct(Subtract(t.B, t.A), Subtract(t.C, t.B))
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{A: a, B: b, C: c, D: d}
}
func (q Quad) NormalVector() geom.Vector {
return VectorProduct(Subtract(q.B, q.A), Subtract(q.C, q.B))
}
-func (t Triangle) Inside(point geom.Vector) bool {
- firstSide := Subtract(t.B, t.A)
- secondSide := Subtract(t.C, t.B)
- thirdSide := Subtract(t.A, t.C)
-
- return MixedProduct(t.NormalVector(), firstSide, Subtract(point, t.A)) > 0 &&
- MixedProduct(t.NormalVector(), secondSide, Subtract(point, t.B)) > 0 &&
- MixedProduct(t.NormalVector(), thirdSide, Subtract(point, t.C)) > 0
-}
-
func (q Quad) Inside(point geom.Vector) bool {
firstSide := Subtract(q.B, q.A)
secondSide := Subtract(q.C, q.B)
thirdSide := Subtract(q.D, q.C)
fourthSide := Subtract(q.A, q.D)
return MixedProduct(q.NormalVector(), firstSide, Subtract(point, q.A)) > 0 &&
MixedProduct(q.NormalVector(), secondSide, Subtract(point, q.B)) > 0 &&
MixedProduct(q.NormalVector(), thirdSide, Subtract(point, q.C)) > 0 &&
MixedProduct(q.NormalVector(), fourthSide, Subtract(point, q.D)) > 0
}
-func (s Sphere) Inside(point geom.Vector) bool {
- return ScalarProduct(Subtract(s.Origin, point), Subtract(s.Origin, point)) <= s.R
+func (q Quad) Parallel(ray geom.Ray) bool {
+ return math.Abs(ScalarProduct(q.NormalVector(), ray.Direction)) < epsilon
}
-func (t Triangle) Parallel(ray geom.Ray) bool {
- return math.Abs(ScalarProduct(t.NormalVector(), ray.Direction)) < epsilon
+func (q Quad) GetA() geom.Vector {
+ return q.A
}
-func (q Quad) Parallel(ray geom.Ray) bool {
- return math.Abs(ScalarProduct(q.NormalVector(), ray.Direction)) < epsilon
+func (q Quad) Intersect(ray geom.Ray) bool {
+ return IntersectConvexPolygons(q, ray)
}
+type Sphere struct {
+ Origin geom.Vector
+ R float64
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{Origin: origin, R: r}
+}
+
+func (s Sphere) Inside(point geom.Vector) bool {
+ return ScalarProduct(Subtract(s.Origin, point), Subtract(s.Origin, point)) <= s.R
+}
+
func (s Sphere) DifferentHalfspaces(ray geom.Ray) bool {
return ScalarProduct(Subtract(s.Origin, ray.Origin), ray.Direction) < 0
}
func (s Sphere) MinDistance(ray geom.Ray) float64 {
if ScalarProduct(ray.Direction, ray.Direction) > 0 {
return ScalarProduct(VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin)),
VectorProduct(ray.Direction, Subtract(s.Origin, ray.Origin))) / ScalarProduct(ray.Direction, ray.Direction)
}
return ScalarProduct(Subtract(s.Origin, ray.Origin), Subtract(s.Origin, ray.Origin))
}
-func (t Triangle) GetA() geom.Vector {
- return t.A
+func (s Sphere) Intersect(ray geom.Ray) bool {
+ if s.Inside(ray.Origin) {
+ return true
+ }
+ if s.DifferentHalfspaces(ray) {
+ return false
+ }
+ return s.MinDistance(ray) <= s.R*s.R
}
-func (q Quad) GetA() geom.Vector {
- return q.A
+type ConvexPolygon interface {
+ NormalVector() geom.Vector
+ Inside(point geom.Vector) bool
+ Parallel(ray geom.Ray) bool
+ GetA() geom.Vector
}
func IntersectConvexPolygons(cp ConvexPolygon, ray geom.Ray) bool {
if cp.Parallel(ray) {
return false
}
distanceFromOrigin := ScalarProduct(cp.NormalVector(), cp.GetA()) // from Origin to the triangle's plane
distanceFromRay := (distanceFromOrigin - ScalarProduct(cp.NormalVector(), ray.Origin)) / ScalarProduct(cp.NormalVector(), ray.Direction)
if distanceFromRay < 0 {
return false
}
//here whe know that the ray intersects with triangle's plane
point := Sum(ray.Origin, geom.Vector{X: distanceFromRay * ray.Direction.X, Y: distanceFromRay * ray.Direction.Y, Z: distanceFromRay * ray.Direction.Z})
return cp.Inside(point)
}
-func (t Triangle) Intersect(ray geom.Ray) bool {
- return IntersectConvexPolygons(t, ray)
+func ScalarProduct(a, b geom.Vector) float64 {
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
}
-func (q Quad) Intersect(ray geom.Ray) bool {
- return IntersectConvexPolygons(q, ray)
+func VectorProduct(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 (s Sphere) Intersect(ray geom.Ray) bool {
- if s.Inside(ray.Origin) {
- return true
- }
- if s.DifferentHalfspaces(ray) {
- return false
- }
- return s.MinDistance(ray) <= s.R*s.R
+func MixedProduct(a, b, c geom.Vector) float64 {
+ return ScalarProduct(a, VectorProduct(b, c))
+}
+
+func Subtract(a, b geom.Vector) geom.Vector {
+ return geom.Vector{X: a.X - b.X, Y: a.Y - b.Y, Z: a.Z - b.Z}
+}
+
+func Sum(a, b geom.Vector) geom.Vector {
+ return geom.Vector{X: a.X + b.X, Y: a.Y + b.Y, Z: a.Z + b.Z}
}