如何在python中获取我的函数以返回球体和光线的交点?

问题描述 投票:0回答:1

我应该为它创建一个函数和测试用例,它返回光线和球体的交点。如果有多个交叉点(光线进出球体),那么它应该返回最接近光线起点的点。我必须使用二次方程来做到这一点。这就是我现在所拥有的。

import vector_math
import data

def sphere_intersection_point(ray, sphere):
    pnt = data.Point(2*(ray.pt.x - sphere.center.x), 2*(ray.pt.y -    sphere.center.y), 2*(ray.pt.z - sphere.center.z))
    pnt2 = data.Point(ray.pt.x - sphere.center.x, ray.pt.y - sphere.center.y, ray.pt.z - sphere.center.z)
    a = (vector_math.dot_vector(ray.dir, ray.dir))
    b = (pnt.x*ray.dir.x) + (pnt.y*ray.dir.y) + (pnt.z*ray.dir.z)
    c = (vector_math.dot_vector(pnt2, pnt2)-sphere.radius**2)

    discriminant = (b**2 - 4*a*c)

    t1 = (-b+discriminant)/(2*a)
    t2 = (-b-discriminant)/(2*a)

    t = t1 or t2

    (a*(t**2)) + (b*t) + c == 0

   if t1 > 0 and t2 > 0:
        mt = min(t1,t2)
        vec = vector_math.scale_vector(ray.dir, mt)
        return data.Point(ray.pt.x + vec.x, ray.pt.y + vec.y, ray.pt.z + vec.z)

    elif (t1>0 and t2<0) or (t1<0 and t2>0):
        maxt = max(t1, t2)
        vec2 = vector_math.scale_vector(ray.dir, maxt)
        return data.Point(ray.pt.x + vec2.x, ray.pt.y + vec2.y, ray.pt.z + vec2.z)

    elif t1<0 and t2<0:
        return None

到目前为止,我为此编写了一个测试用例,但它没有返回正确的观点。这是我的测试用例代码。这只是最后一个。

import unittest
import data
import vector_math
import math
import collisions

class TestData(unittest.TestCase):
    def test_point_1(self):
        self.assertEqual(data.Point(1,2,3).x,1)
        self.assertEqual(data.Point(1,2,3).y,2)
        self.assertEqual(data.Point(1,2,3).z,3)

    def test_point_2(self):
        self.assertEqual(data.Point(3,3,4).x,3)
        self.assertEqual(data.Point(3,3,4).y,3)
        self.assertEqual(data.Point(3,3,4).z,4)

    def test_vector_1(self):
        self.assertEqual(data.Vector(1,2,3).x,1)
        self.assertEqual(data.Vector(1,2,3).y,2)
        self.assertEqual(data.Vector(1,2,3).z,3)

    def test_vector_2(self):
        self.assertEqual(data.Vector(4,5,6).x,4)
        self.assertEqual(data.Vector(4,5,6).y,5)
        self.assertEqual(data.Vector(4,5,6).z,6)

    def test_ray_1(self):
        self.assertEqual(data.Ray(data.Point(0,0,0),data.Vector(1,2,3)).pt.x,0)
        self.assertEqual(data.Ray(data.Point(0,0,0),data.Vector(1,2,3)).pt.y,0)
        self.assertEqual(data.Ray(data.Point(0,0,0),data.Vector(1,2,3)).pt.z,0)
        self.assertEqual(data.Ray(data.Point(0,0,0),data.Vector(1,2,3)).dir.x,1)
        self.assertEqual(data.Ray(data.Point(0,0,0),data.Vector(1,2,3)).dir.y,2)
        self.assertEqual(data.Ray(data.Point(0,0,0),data.Vector(1,2,3)).dir.z,3)

    def test_ray_2(self):
        self.assertEqual(data.Ray(data.Point(1,2,3),data.Vector(2,2,2)).pt.x,1)
        self.assertEqual(data.Ray(data.Point(1,2,3),data.Vector(2,2,2)).pt.y,2)
        self.assertEqual(data.Ray(data.Point(1,2,3),data.Vector(2,2,2)).pt.z,3)
        self.assertEqual(data.Ray(data.Point(1,2,3),data.Vector(2,2,2)).dir.x,2)
        self.assertEqual(data.Ray(data.Point(1,2,3),data.Vector(2,2,2)).dir.y,2)
        self.assertEqual(data.Ray(data.Point(1,2,3),data.Vector(2,2,2)).dir.z,2)

    def test_sphere_1(self):
        self.assertEqual(data.Sphere(data.Point(1,1,1),4.0).center.x,1)
        self.assertEqual(data.Sphere(data.Point(1,1,1),4.0).center.y,1)
        self.assertEqual(data.Sphere(data.Point(1,1,1),4.0).center.z,1)
        self.assertEqual(data.Sphere(data.Point(1,1,1),4.0).radius,4.0)

    def test_sphere_2(self):
        self.assertEqual(data.Sphere(data.Point(1,1,1),3.0).center.x,1)
        self.assertEqual(data.Sphere(data.Point(1,1,1),3.0).center.y,1)
        self.assertEqual(data.Sphere(data.Point(1,1,1),3.0).center.z,1)
        self.assertEqual(data.Sphere(data.Point(1,1,1),3.0).radius,3.0)

    def test_equality(self):
        self.assertTrue(data.Point(1,2,3) == data.Point(1,2,3))
        self.assertTrue(data.Vector(1,2,3) == data.Vector(1,2,3))
        self.assertTrue(data.Ray(data.Point(0,0,0), data.Vector(1,1,1)) == data.Ray(data.Point(0,0,0), data.Vector(1,1,1)))
        self.assertTrue(data.Sphere(data.Point(0,0,0),3.0) == data.Sphere(data.Point(0,0,0),3.0))

    def test_scale_vector(self):
        self.assertEqual(vector_math.scale_vector(data.Vector(1,1,1),3.0), data.Vector(3.0,3.0,3.0))

    def test_dot_product(self):
        self.assertEqual(vector_math.dot_vector(data.Vector(1,1,1), data.Vector(2,2,2)), 6)

    def test_length_vector(self):
        self.assertEqual(vector_math.length_vector(data.Vector(1,2,3)), math.sqrt(1**2+2**2+3**2))

    def test_normalize_vector(self):
        self.assertEqual(vector_math.normalize_vector(data.Vector(2,0,0)), data.Vector(1,0,0))

    def test_difference_point(self):
        self.assertEqual(vector_math.difference_point(data.Point(2,0,0), data.Point(0,0,0)), data.Vector(2,0,0))

    def test_difference_vector(self):
        self.assertEqual(vector_math.difference_vector(data.Vector(3,3,3), data.Vector(1,1,1)), data.Vector(2,2,2))

    def test_translate_point(self):
        self.assertEqual(vector_math.translate_point(data.Point(0,0,0), data.Vector(1,1,1)), data.Point(1,1,1))

    def test_vector_from_to(self):
        self.assertEqual(vector_math.vector_from_to(data.Point(0,0,0), data.Point(2,2,2)), data.Vector(2,2,2))

    def test_sphere_intersection_pt_1(self):
        ray1 = data.Ray(data.Point(0,0,0), data.Vector(3,0,0))
        sphere1 = data.Sphere(data.Point(5,0,0), 1)
        self.assertEqual(collisions.sphere_intersection_point(ray1, sphere1), data.Point(4,0,0))

if __name__ == '__main__':
    unittest.main()

我知道有些缩进是关闭的,但它们在我的文本编辑器中是正确的,它只是复制和粘贴很奇怪。这是我得到的错误。

root@THEO_PC:/mnt/c/Users/Theo/Desktop/cpe101/hw3# python tests.py
.............F....
======================================================================
FAIL: test_sphere_intersection_pt_1 (__main__.TestData)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests.py", line 89, in test_sphere_intersection_pt_1
    self.assertEqual(collisions.sphere_intersection_point(ray1, sphere1),    data.Point(4,0,0))
AssertionError: <data.Point instance at 0x7f42757cedd0> != <data.Point   instance at 0x7f42757ced88>

----------------------------------------------------------------------
Ran 18 tests in 0.003s

FAILED (failures=1)

这里还有我的vector_math文件。

import math
import data

def scale_vector (vector, scalar):
    return data.Vector(vector.x*scalar, vector.y*scalar, vector.z*scalar)

def dot_vector (vector1, vector2):
    return vector1.x*vector2.x + vector1.y*vector2.y + vector1.z*vector2.z

def length_vector (vector):
    return math.sqrt(vector.x**2 + vector.y**2 + vector.z**2)

def normalize_vector (vector):
    return data.Vector(vector.x/length_vector(vector), vector.y/length_vector(vector), vector.z/length_vector(vector))

def difference_point (point1, point2):
     return data.Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z)

def difference_vector (vector1, vector2):
    return data.Vector(vector1.x - vector2.x, vector1.y - vector2.y, vector1.z - vector2.z)

def translate_point (point, vector):
    return data.Point(point.x + vector.x, point.y + vector.y, point.z + vector.z)

def vector_from_to (from_point, to_point):
    return data.Vector(to_point.x - from_point.x, to_point.y - from_point.y, to_point.z - from_point.z)

这是我的数据文件。

import utility

class Point:
    def __init__ (self,x,y,z):
        self.x=x
        self.y=y
        self.z=z
    def __eq__ (self, other):
        x = utility.epsilon_equal(self.x, other.x)
        y = utility.epsilon_equal(self.y, other.y)
        z = utility.epsilon_equal(self.z, other.z)
        return x and y and z

class Vector:
    def __init__ (self,x,y,z):
        self.x=x
        self.y=y
        self.z=z

    def __eq__ (self, other):
        x = utility.epsilon_equal(self.x, other.x)
        y = utility.epsilon_equal(self.y, other.y)
        z = utility.epsilon_equal(self.z, other.z)
        return x and y and z

class Ray:
    def __init__ (self,pt,dir):
        self.pt=pt
        self.dir=dir

    def __eq__ (self, other):
        a = utility.epsilon_equal(self.pt.x, other.pt.x)
        b = utility.epsilon_equal(self.pt.y, other.pt.y)
        c = utility.epsilon_equal(self.pt.z, other.pt.z)
        d = utility.epsilon_equal(self.dir.x, other.dir.x)
        e = utility.epsilon_equal(self.dir.y, other.dir.y)
        f = utility.epsilon_equal(self.dir.z, other.dir.z)
        return a and b and c and d and e and f

class Sphere:
    def __init__ (self,center,radius):
        self.center=center
        self.radius=radius

    def __eq__ (self, other):
        a = utility.epsilon_equal(self.center.x, other.center.x)
        b = utility.epsilon_equal(self.center.y, other.center.y)
        c = utility.epsilon_equal(self.center.z, other.center.z)
        d = utility.epsilon_equal(self.radius, other.radius)
        return a and b and c and d

再次对缩进感到抱歉。我知道这些类看起来不对,但它在我的代码中是正确的。此外,任何建议使我的代码更整洁,更简洁的感谢。

python intersection raytracing
1个回答
0
投票

assertEqual调用正在比较对象是否相等,而不是对象的内容。根据unittest模块的文档,您必须通过__eq__在几何类型中注册unittest.addTypeEqualityFunc()函数。

© www.soinside.com 2019 - 2024. All rights reserved.