2D和3D矢量、矩阵、四元数和几何模块
项目描述
Python模块,用于2D和3D图形相关数学函数:矢量、矩阵、四元数和简单的平面/线/球面几何。
历史
此库于2006年编写,在Google Code上托管(https://code.google.com/archive/p/pyeuclid/),采用LGPL许可。Alex于2019年将代码重新许可,采用更宽松的BSD许可。随后很快更新以支持Python 3,并于2020年由新维护者Richard Jones以1.0版本发布。
本README的其余部分是2006年的原始文档,使用cloudconvert.com从reStructured Text转换为Markdown。
概述
本文件描述了euclid模块,该模块为2D和3D图形应用提供矢量、矩阵和四元数类。所有内容都位于euclid命名空间中
>>> from euclid import * >>>
使用断言执行参数类型检查。这样做的好处是在通常的Python会话中,异常会在较晚之前被引发,并显示预期的类型消息。当Python以-O或-OO标志运行时,断言将被删除,代码执行速度更快。
矢量类
提供了两种可变向量类型:分别是用于2D向量的Vector2和用于3D向量的Vector3。向量默认存储浮点数,但大多数操作也可以使用整型或长整型。按照直观的方式构造向量。
>>> Vector2(1.5, 2.0) Vector2(1.50, 2.00)>>> Vector3(1.0, 2.0, 3.0) Vector3(1.00, 2.00, 3.00)
### 元素访问
可以通过属性访问分量(以下示例使用Vector3,但对于Vector2,结果类似,只需使用x和y分量)
>>> v = Vector3(1, 2, 3) >>> v.x 1 >>> v.y 2 >>> v.z 3
向量支持通过切片实现列表接口
>>> v = Vector3(1, 2, 3) >>> len(v) 3 >>> v[0] 1 >>> v[:] (1, 2, 3)
也可以对分量进行“分解”(类似于GLSL或Cg)
>>> v = Vector3(1, 2, 3) >>> v.xyz (1, 2, 3) >>> v.zx (3, 1) >>> v.zzzz (3, 3, 3, 3)
所有上述访问器也都是修改器[1]
>>> v = Vector3(1, 2, 3) >>> v.x = 5 >>> v Vector3(5.00, 2.00, 3.00) >>> v[1:] = (10, 20) >>> v Vector3(5.00, 10.00, 20.00)
[1] 通过分解赋值(例如,v.xyz = (1, 2, 3))是受支持的,但前提是已设置_enable_swizzle_set变量。默认情况下这是禁用的,因为它会影响普通属性设置的性能,并且比按顺序设置分量要慢。
### 运算符
通过运算符重载支持加法和减法(请注意,就地运算符比创建新对象的速度快)
>>> v1 = Vector3(1, 2, 3) >>> v2 = Vector3(4, 5, 6) >>> v1 + v2 Vector3(5.00, 7.00, 9.00) >>> v1 -= v2 >>> v1 Vector3(-3.00, -3.00, -3.00)
只能与标量进行乘法和除法运算
>>> Vector3(1, 2, 3) * 2 Vector3(2.00, 4.00, 6.00) >>> v1 = Vector3(1., 2., 3.) >>> v1 /= 2 >>> v1 Vector3(0.50, 1.00, 1.50)
可以使用abs找到向量的长度
>>> v = Vector3(1., 2., 3.) >>> abs(v) 3.7416573867739413
向量可以就地归一化(请注意,就地方法也会返回self,因此您可以将其与后续运算符链接使用)
>>> v = Vector3(1., 2., 3.) >>> v.normalize() Vector3(0.27, 0.53, 0.80) >>> v Vector3(0.27, 0.53, 0.80)
以下方法都不会修改原始向量或它们的参数
copy() 返回向量的副本。__copy__也实现了。
magnitude() 返回向量的长度;等同于abs(v)。示例
>>> v = Vector3(1., 2., 3.) >>> v.magnitude() 3.7416573867739413
magnitude_squared() 返回每个分量的平方和。对于比较两个向量的长度而无需进行昂贵的平方根运算非常有用。示例
>>> v = Vector3(1., 2., 3.) >>> v.magnitude_squared() 14.0
normalized() 返回具有相同方向的单位长度向量。请注意,此方法与normalize不同,因为它不会就地修改向量。示例
>>> v = Vector3(1., 2., 3.) >>> v.normalized() Vector3(0.27, 0.53, 0.80) >>> v Vector3(1.00, 2.00, 3.00)
dot(other) 返回两个向量的标量“点”积。示例
>>> v1 = Vector3(1., 2., 3.) >>> v2 = Vector3(4., 5., 6.) >>> v1.dot(v2) 32.0
cross() 和 cross(other) 返回向量的叉积(对于Vector2)或两个向量的叉积(对于Vector3)。返回类型是向量。示例
>>> v1 = Vector3(1., 2., 3.) >>> v2 = Vector3(4., 5., 6.) >>> v1.cross(v2) Vector3(-3.00, 6.00, -3.00)
在二维中,cross没有参数
>>> v1 = Vector2(1., 2.) >>> v1.cross() Vector2(2.00, -1.00)
reflect(normal) 返回关于给定法线的反射向量。在二维中,normal是线的法线,在三维中它是平面的法线。法线必须具有单位长度。示例
>>> v = Vector3(1., 2., 3.) >>> v.reflect(Vector3(0, 1, 0)) Vector3(1.00, -2.00, 3.00) >>> v = Vector2(1., 2.) >>> v.reflect(Vector2(1, 0)) Vector2(-1.00, 2.00)
rotate_around(axes, theta) 对于3D向量,返回围绕轴旋转角度theta的向量。
>>> v = Vector3(1., 2., 3.) >>> axes = Vector3(1.,1.,0) >>> v.rotate_around(axes,math.pi/4) Vector3(2.65, 0.35, 2.62)
angle(other) 返回两个向量之间的角度。
project(other) 返回向量在另一个向量上的投影(分量)。
相等性测试包括与其他序列的比较
>>> v2 = Vector2(1, 2) >>> v2 == Vector2(3, 4) False >>> v2 != Vector2(1, 2) False >>> v2 == (1, 2) True>>> v3 = Vector3(1, 2, 3) >>> v3 == Vector3(3, 4, 5) False >>> v3 != Vector3(1, 2, 3) False >>> v3 == (1, 2, 3) True
向量不可哈希,因此不能放入集合中或用作字典键
>>> {Vector2(): 0} Traceback (most recent call last): ... TypeError: unhashable type: 'Vector2'>>> {Vector3(): 0} Traceback (most recent call last): ... TypeError: unhashable type: 'Vector3'
矩阵类
提供了两个矩阵类,分别是用于2D仿射变换的3x3矩阵Matrix3和用于3D仿射变换的4x4矩阵Matrix4。
默认构造函数将矩阵初始化为单位矩阵
>>> Matrix3() Matrix3([ 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00]) >>> Matrix4() Matrix4([ 1.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 1.00])
### 元素访问
内部,每个矩阵存储为一系列属性,命名为cite>a到cite>p。Matrix3的布局为
# a b c # e f g # i j k
而Matrix4为
# a b c d # e f g h # i j k l # m n o p
如果您希望一次设置或检索多个元素,可以使用切片来完成
>>> m = Matrix4() >>> m[:] [1.0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 1.0] >>> m[12:15] = (5, 5, 5) >>> m Matrix4([ 1.00 0.00 0.00 5.00 0.00 1.00 0.00 5.00 0.00 0.00 1.00 5.00 0.00 0.00 0.00 1.00])
请注意,切片以列主序顺序操作,这使得它们适合直接与OpenGL的glLoadMatrix和glGetFloatv函数一起使用。
### 类构造函数
对于最常见的变换类型,提供了类构造函数。
new_identity 等同于默认构造函数。示例
>>> m = Matrix4.new_identity() >>> m Matrix4([ 1.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 1.00])
new_scale(x, y) 和 new_scale(x, y, z) 前者定义在 Matrix3 上,后者定义在 Matrix4 上。等同于 OpenGL 调用 glScalef。示例
>>> m = Matrix4.new_scale(2.0, 3.0, 4.0) >>> m Matrix4([ 2.00 0.00 0.00 0.00 0.00 3.00 0.00 0.00 0.00 0.00 4.00 0.00 0.00 0.00 0.00 1.00])
new_translate(x, y) 和 new_translate(x, y, z) 前者定义在 Matrix3 上,后者定义在 Matrix4 上。等同于 OpenGL 调用 glTranslatef。示例
>>> m = Matrix4.new_translate(3.0, 4.0, 5.0) >>> m Matrix4([ 1.00 0.00 0.00 3.00 0.00 1.00 0.00 4.00 0.00 0.00 1.00 5.00 0.00 0.00 0.00 1.00])
new_rotate(angle) 创建一个围绕原点旋转的 Matrix3。 angle 以弧度指定,逆时针。在 Matrix4 中没有实现(以下为等效方法)。示例
>>> import math >>> m = Matrix3.new_rotate(math.pi / 2) >>> m Matrix3([ 0.00 -1.00 0.00 1.00 0.00 0.00 0.00 0.00 1.00])
以下构造函数仅定义在 Matrix4 上。
new 使用列主顺序创建一个包含 16 个值的矩阵。
new_rotatex(angle)、new_rotatey(angle)、new_rotatez(angle) 分别创建围绕 X、Y 或 Z 轴旋转的 Matrix4。 angle 以弧度指定。示例
>>> m = Matrix4.new_rotatex(math.pi / 2) >>> m Matrix4([ 1.00 0.00 0.00 0.00 0.00 0.00 -1.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 1.00])
new_rotate_axis(angle, axis) 创建一个围绕给定轴旋转的 Matrix4。 angle 以弧度指定,axis 必须是 Vector3 的实例。不需要归一化轴。示例
>>> m = Matrix4.new_rotate_axis(math.pi / 2, Vector3(1.0, 0.0, 0.0)) >>> m Matrix4([ 1.00 0.00 0.00 0.00 0.00 0.00 -1.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 1.00])
new_rotate_euler(heading, attitude, bank) 创建一个给定欧拉旋转的 Matrix4。 heading 是围绕 Y 轴的旋转,attitude 是围绕 X 轴的旋转,bank 是围绕 Z 轴的旋转。所有旋转同时进行,因此此方法避免了“万向节锁”,通常是实现游戏中 3D 旋转的常用方法。示例
>>> m = Matrix4.new_rotate_euler(math.pi / 2, math.pi / 2, 0.0) >>> m Matrix4([ 0.00 -0.00 1.00 0.00 1.00 0.00 -0.00 0.00 -0.00 1.00 0.00 0.00 0.00 0.00 0.00 1.00])
new_perspective(fov_y, aspect, near, far) 创建一个投影到 2D 观察平面的 Matrix4。此方法等同于 OpenGL 调用 gluPerspective。 fov_y 是 Y 方向的视角角度,以弧度为单位。 aspect 是观察平面的宽高比 width / height。 near 和 far 是近剪切面和远剪切面的距离。它们必须是正数且非零。示例
>>> m = Matrix4.new_perspective(math.pi / 2, 1024.0 / 768, 1.0, 100.0) >>> m Matrix4([ 0.75 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 -1.02 -2.02 0.00 0.00 -1.00 0.00])
### 运算符
相同维度的矩阵可以相乘,以得到一个新的矩阵。例如,要创建一个平移和缩放的变换
>>> m1 = Matrix3.new_translate(5.0, 6.0) >>> m2 = Matrix3.new_scale(1.0, 2.0) >>> m1 * m2 Matrix3([ 1.00 0.00 5.00 0.00 2.00 6.00 0.00 0.00 1.00])
请注意,乘法不是交换律的(应用变换的顺序很重要)
>>> m2 * m1 Matrix3([ 1.00 0.00 5.00 0.00 2.00 12.00 0.00 0.00 1.00])
还允许就地乘法(并进行了优化)
>>> m1 *= m2 >>> m1 Matrix3([ 1.00 0.00 5.00 0.00 2.00 6.00 0.00 0.00 1.00])
将矩阵乘以一个向量返回一个向量,并用于变换一个向量
>>> m1 = Matrix3.new_rotate(math.pi / 2) >>> m1 * Vector2(1.0, 1.0) Vector2(-1.00, 1.00)
请注意,平移对向量没有影响。然而,它们会影响点
>>> m1 = Matrix3.new_translate(5.0, 6.0) >>> m1 * Vector2(1.0, 2.0) Vector2(1.00, 2.00) >>> m1 * Point2(1.0, 2.0) Point2(6.00, 8.00)
当前矩阵和向量之间的乘法是错误的 – 忽略了投影组件。请使用 Matrix4.transform 方法。
Matrix4 还定义了 transpose(就地)、transposed(功能)、determinant 和 inverse(功能)方法。
Matrix3 可以与 Vector2 或任何二维几何对象(Point2、Line2、Circle 等)相乘。
Matrix4 可以与 Vector3 或任何三维几何对象(Point3、Line3、Sphere 等)相乘。
为了方便,每个矩阵构造函数也都可以作为就地操作符使用。例如,而不是写
>>> m1 = Matrix3.new_translate(5.0, 6.0) >>> m2 = Matrix3.new_scale(1.0, 2.0) >>> m1 *= m2
可以直接将缩放应用到 m1
>>> m1 = Matrix3.new_translate(5.0, 6.0) >>> m1.scale(1.0, 2.0) Matrix3([ 1.00 0.00 5.00 0.00 2.00 6.00 0.00 0.00 1.00]) >>> m1 Matrix3([ 1.00 0.00 5.00 0.00 2.00 6.00 0.00 0.00 1.00])
请注意,这些方法是在就地操作(它们修改了原始矩阵),并且它们也返回自身作为结果。这允许您直接链接变换
>>> Matrix3().translate(1.0, 2.0).rotate(math.pi / 2).scale(4.0, 4.0) Matrix3([ 0.00 -4.00 1.00 4.00 0.00 2.00 0.00 0.00 1.00])
所有构造函数都有一个等效的就地方法。对于 Matrix3,它们是 identity、translate、scale 和 rotate。对于 Matrix4,它们是 identity、translate、scale、rotatex、rotatey、rotatez、rotate_axis 和 rotate_euler。Matrix3 和 Matrix4 还有一个就地 transpose 方法。
复制方法也在这两个矩阵类中实现,并且表现得非常明显。
四元数
四元数表示三维旋转或反射变换。在3D应用程序中,它们是存储和操作旋转的首选方式,因为它们不会像矩阵那样受到数值退化的影响。
四元数构造函数初始化为恒等变换
>>> q = Quaternion() >>> q Quaternion(real=1.00, imag=<0.00, 0.00, 0.00>)
### 元素访问
在内部,四元数存储为四个属性:x、y和z形成一个虚向量,而w是实部。
### 构造函数
可以使用构造函数形成旋转
new_identity() 等同于默认构造函数。
new_rotate_axis(angle, axis) 等同于同名Matrix4构造函数。 angle 以弧度指定,axis 是 Vector3 的一个实例。不需要对轴进行归一化。示例
>>> q = Quaternion.new_rotate_axis(math.pi / 2, Vector3(1, 0, 0)) >>> q Quaternion(real=0.71, imag=<0.71, 0.00, 0.00>)
new_rotate_euler(heading, attitude, bank) 等同于同名Matrix4构造函数。 heading 是绕Y轴的旋转,attitude 是绕X轴的旋转,bank 是绕Z轴的旋转。所有角度均以弧度给出。示例
>>> q = Quaternion.new_rotate_euler(math.pi / 2, math.pi / 2, 0) >>> q Quaternion(real=0.50, imag=<0.50, 0.50, 0.50>)
new_interpolate(q1, q2, t) 创建一个四元数,它给出在 q1 和 q2 之间(SLERP)插值旋转。 q1 和 q2 是 Quaternion 的实例,t 是介于 0.0 和 1.0 之间的值。例如
>>> q1 = Quaternion.new_rotate_axis(math.pi / 2, Vector3(1, 0, 0)) >>> q2 = Quaternion.new_rotate_axis(math.pi / 2, Vector3(0, 1, 0)) >>> for i in range(11): ... print Quaternion.new_interpolate(q1, q2, i / 10.0) ... Quaternion(real=0.71, imag=<0.71, 0.00, 0.00>) Quaternion(real=0.75, imag=<0.66, 0.09, 0.00>) Quaternion(real=0.78, imag=<0.61, 0.17, 0.00>) Quaternion(real=0.80, imag=<0.55, 0.25, 0.00>) Quaternion(real=0.81, imag=<0.48, 0.33, 0.00>) Quaternion(real=0.82, imag=<0.41, 0.41, 0.00>) Quaternion(real=0.81, imag=<0.33, 0.48, 0.00>) Quaternion(real=0.80, imag=<0.25, 0.55, 0.00>) Quaternion(real=0.78, imag=<0.17, 0.61, 0.00>) Quaternion(real=0.75, imag=<0.09, 0.66, 0.00>) Quaternion(real=0.71, imag=<0.00, 0.71, 0.00>)
### 运算符
四元数可以相乘以组合旋转。例如,要绕X轴旋转90度,然后绕Y轴旋转90度
>>> q1 = Quaternion.new_rotate_axis(math.pi / 2, Vector3(1, 0, 0)) >>> q2 = Quaternion.new_rotate_axis(math.pi / 2, Vector3(0, 1, 0)) >>> q1 * q2 Quaternion(real=0.50, imag=<0.50, 0.50, 0.50>)
将四元数乘以一个向量给出一个向量,并适当地进行变换
>>> q = Quaternion.new_rotate_axis(math.pi / 2, Vector3(0, 1, 0)) >>> q * Vector3(1.0, 0, 0) Vector3(0.00, 0.00, -1.00)
同样,任何3D对象都可以相乘(例如,Point3、Line3、Sphere等)
>>> q * Ray3(Point3(1., 1., 1.), Vector3(1., 1., 1.)) Ray3(<1.00, 1.00, -1.00> + u<1.00, 1.00, -1.00>)
与矩阵类一样,构造函数也作为就地运算符提供。这些名称为 identity、rotate_euler 和 rotate_axis。例如
>>> q1 = Quaternion() >>> q1.rotate_euler(math.pi / 2, math.pi / 2, 0) Quaternion(real=0.50, imag=<0.50, 0.50, 0.50>) >>> q1 Quaternion(real=0.50, imag=<0.50, 0.50, 0.50>)
四元数通常是单位长度,但您可能希望使用有大小四元数。在这种情况下,您可以使用与向量类相同的方式使用 abs、magnitude 和 magnitude_squared 来找到大小。示例
>>> q1 = Quaternion() >>> abs(q1) 1.0 >>> q1.magnitude() 1.0
同样,该类以与向量相同的方式实现了 normalize 和 normalized。
以下方法不会改变四元数
conjugated() 返回一个与实例共轭的四元数。例如
>>> q1 = Quaternion.new_rotate_axis(math.pi / 2, Vector3(1, 0, 0)) >>> q1.conjugated() Quaternion(real=0.71, imag=<-0.71, -0.00, -0.00>) >>> q1 Quaternion(real=0.71, imag=<0.71, 0.00, 0.00>)
get_angle_axis() 返回一个元组(角度,轴),给出与四元数等效的轴的旋转角度。例如
>>> q1 = Quaternion.new_rotate_axis(math.pi / 2, Vector3(1, 0, 0)) >>> q1.get_angle_axis() (1.5707963267948966, Vector3(1.00, 0.00, 0.00))
get_matrix() 返回一个实现四元数变换的 Matrix4。例如
>>> q1 = Quaternion.new_rotate_axis(math.pi / 2, Vector3(1, 0, 0)) >>> q1.get_matrix() Matrix4([ 1.00 0.00 0.00 0.00 0.00 0.00 -1.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 1.00])
2D 几何
以下类可用于处理简单的2D几何。每个形状的接口相似;特别是,connect 和 distance 方法对每个形状都定义相同。
例如,要找到一条线到圆上最近点
>>> circ = Circle(Point2(3., 2.), 2.) >>> line = Line2(Point2(0., 0.), Point2(-1., 1.)) >>> line.connect(circ).p1 Point2(0.50, -0.50)
要找到对应于线到圆上最近点的圆上的点
>>> line.connect(circ).p2 Point2(1.59, 0.59)
### Point2
2D平面上的一个点。按明显的方式构造
>>> p = Point2(1.0, 2.0) >>> p Point2(1.00, 2.00)
Point2 是 Vector2 的子类,因此所有 Vector2 操作符和方法都适用。特别是,两个点相减得到一个向量
>>> Point2(2.0, 3.0) - Point2(1.0, 0.0) Vector2(1.00, 3.00)
还定义了以下方法
connect(other) 返回一个 LineSegment2,这是可以连接两个形状的最短线段。other 可以是一个 Point2、Line2、Ray2、LineSegment2 或 Circle。
distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。
### Line2, Ray2, LineSegment2
Line2 是一个在2D平面上延伸到无穷远的线;Ray2 有一个有限的端点,在一个方向上延伸到无穷远;LineSegment2 连接两个点。
这三个类都支持相同的构造函数、运算符和方法,但在计算交点等时可能表现不同。
您可以使用以下任一方式构建线、射线或线段
另一条线、射线或线段
两个点
一个点和向量
一个点、一个向量和一个长度
例如
>>> Line2(Point2(1.0, 1.0), Point2(2.0, 3.0)) Line2(<1.00, 1.00> + u<1.00, 2.00>) >>> Line2(Point2(1.0, 1.0), Vector2(1.0, 2.0)) Line2(<1.00, 1.00> + u<1.00, 2.00>) >>> Ray2(Point2(1.0, 1.0), Vector2(1.0, 2.0), 1.0) Ray2(<1.00, 1.00> + u<0.45, 0.89>)
内部,线、射线和线段存储一个 Point2 p 和一个 Vector2 v。您也可以访问(但不能设置)两个端点 p1 和 p2。这些可能对所有类型的线都很有意义。
以下方法由所有三个类支持
intersect(other) 如果 other 是一个 Line2、Ray2 或 LineSegment2,则返回一个交点 Point2,如果两条线平行则返回 None。
如果 other 是一个 Circle,则返回一个相交的 LineSegment2 或 Point2,或者在没有交点的情况下返回 None。
connect(other) 返回一个 LineSegment2,它是连接两个形状的最短线段。对于两条平行线,此线段可能处于任意位置。other 可以是一个 Point2、Line2、Ray2、LineSegment2 或 Circle。
distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。
LineSegment2 还有一个只读的 length 属性。
### 圆
圆是通过一个中心 Point2 和一个半径来构建的
>>> c = Circle(Point2(1.0, 1.0), 0.5) >>> c Circle(<1.00, 1.00>, radius=0.50)
内部有两个属性:c 给出中心点,r 给出半径。
以下方法被支持
intersect(other) 如果 other 是一个 Line2、Ray2 或 LineSegment2,则返回一个相交的 LineSegment2,如果没有交点则返回 None。
connect(other) 返回一个 LineSegment2,这是可以连接两个形状的最短线段。other 可以是一个 Point2、Line2、Ray2、LineSegment2 或 Circle。
distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。
3D 几何
以下类可用于处理简单的 3D 几何。接口与 2D 类非常相似(但请注意,不能混合使用 2D 和 3D 操作)。
例如,找到线上的一个点到球体的最短距离
>>> sphere = Sphere(Point3(1., 2., 3.,), 2.) >>> line = Line3(Point3(0., 0., 0.), Point3(-1., -1., 0.)) >>> line.connect(sphere).p1 Point3(1.50, 1.50, 0.00)
找到球体上与线对应的最短距离点
>>> line.connect(sphere).p2 Point3(1.32, 1.68, 1.05)
XXX 我还没有检查这些是否正确。
### Point3
一个 3D 平面上的点。以明显的方式构建
>>> p = Point3(1.0, 2.0, 3.0) >>> p Point3(1.00, 2.00, 3.00)
Point3 是 Vector3 的子类,因此所有 Vector3 操作符和方法都适用。特别是,减去两个点会得到一个向量
>>> Point3(1.0, 2.0, 3.0) - Point3(1.0, 0.0, -2.0) Vector3(0.00, 2.00, 5.00)
还定义了以下方法
intersect(other) 如果 other 是一个 Sphere,则返回 True 如果且仅如果该点位于球体内。
connect(other) 返回一个 LineSegment3,它是连接两个形状的最短线段。other 可以是一个 Point3、Line3、Ray3、LineSegment3、Sphere 或 Plane。
distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。
### Line3、Ray3、LineSegment3
Line3 是一个在 3D 平面上延伸到无穷远的线;Ray3 有一个有限的端点,沿一个方向延伸到无穷远;LineSegment3 连接两个点。
这三个类都支持相同的构造函数、运算符和方法,但在计算交点等时可能表现不同。
您可以使用以下任一方式构建线、射线或线段
另一条线、射线或线段
两个点
一个点和向量
一个点、一个向量和一个长度
例如
>>> Line3(Point3(1.0, 1.0, 1.0), Point3(1.0, 2.0, 3.0)) Line3(<1.00, 1.00, 1.00> + u<0.00, 1.00, 2.00>) >>> Line3(Point3(0.0, 1.0, 1.0), Vector3(1.0, 1.0, 2.0)) Line3(<0.00, 1.00, 1.00> + u<1.00, 1.00, 2.00>) >>> Ray3(Point3(1.0, 1.0, 1.0), Vector3(1.0, 1.0, 2.0), 1.0) Ray3(<1.00, 1.00, 1.00> + u<0.41, 0.41, 0.82>)
内部,线、射线和线段存储一个 Point3 p 和一个 Vector3 v。您也可以访问(但不能设置)两个端点 p1 和 p2。这些可能对所有类型的线都很有意义。
以下方法由所有三个类支持
intersect(other) 如果 other 是一个 Sphere,则返回一个与线相交的 LineSegment3,如果没有交点则返回 None。
如果 other 是一个 Plane,则返回一个交点 Point3,或者返回 None。
connect(other) 返回一个 LineSegment3,它是连接两个形状的最短线段。对于两条平行线,此线段可能处于任意位置。other 可以是一个 Point3、Line3、Ray3、LineSegment3、Sphere 或 Plane。
distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。
LineSegment3 还有一个只读的 length 属性。
### 球体
球体由中心点 Point3 和半径构成
>>> s = Sphere(Point3(1.0, 1.0, 1.0), 0.5) >>> s Sphere(<1.00, 1.00, 1.00>, radius=0.50)
内部有两个属性:c 给出中心点,r 给出半径。
以下方法被支持
intersect(other):如果 other 是一个 Point3,则返回 True,如果该点位于球体内。
如果 other 是一个 Line3、Ray3 或 LineSegment3,则返回一个表示交点的 LineSegment3,如果没有交点则返回 None。
connect(other) 返回一个 LineSegment3,它是连接两个形状的最短线段。other 可以是一个 Point3、Line3、Ray3、LineSegment3、Sphere 或 Plane。
distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。
### 平面
平面可以通过以下方式之一构建:
位于平面上的三个 Point3
位于平面上的一个 Point3 和法向量 Vector3
法向量 Vector3 和 k,具体说明如下。
内部存储时,平面存储为法向量 n 和常数 k,使得对于平面上任意点 p,有 n.p = k。
以下方法被支持
intersect(other):如果 other 是一个 Line3、Ray3 或 LineSegment3,则返回交点的 Point3,如果没有交点则返回 None。
如果 other 是一个 Plane,则返回交点的 Line3。
connect(other) 返回一个 LineSegment3,它是连接两个形状的最短线段。other 可以是一个 Point3、Line3、Ray3、LineSegment3、Sphere 或 Plane。
distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。
项目详情
euclid-1.2.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f179506dc6bb3c870e2002ad4658c53a02e518399188c2b47d955b311c97d66b |
|
MD5 | ac0723b9755e7c432189618cf87dd8c7 |
|
BLAKE2b-256 | e0dca14aa837b71be7e0107710ff91cccaeebaba43c0acb732480d1180b98e22 |