跳转到主要内容

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,结果类似,只需使用xy分量)

>>> 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的glLoadMatrixglGetFloatv函数一起使用。

### 类构造函数

对于最常见的变换类型,提供了类构造函数。

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) 创建一个围绕原点旋转的 Matrix3angle 以弧度指定,逆时针。在 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 轴旋转的 Matrix4angle 以弧度指定。示例

>>> 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) 创建一个围绕给定轴旋转的 Matrix4angle 以弧度指定,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) 创建一个给定欧拉旋转的 Matrix4heading 是围绕 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 调用 gluPerspectivefov_y 是 Y 方向的视角角度,以弧度为单位。 aspect 是观察平面的宽高比 width / heightnearfar 是近剪切面和远剪切面的距离。它们必须是正数且非零。示例

>>> 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(功能)、determinantinverse(功能)方法。

Matrix3 可以与 Vector2 或任何二维几何对象(Point2Line2Circle 等)相乘。

Matrix4 可以与 Vector3 或任何三维几何对象(Point3Line3Sphere 等)相乘。

为了方便,每个矩阵构造函数也都可以作为就地操作符使用。例如,而不是写

>>> 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,它们是 identitytranslatescalerotate。对于 Matrix4,它们是 identitytranslatescalerotatexrotateyrotatezrotate_axisrotate_eulerMatrix3Matrix4 还有一个就地 transpose 方法。

复制方法也在这两个矩阵类中实现,并且表现得非常明显。

四元数

四元数表示三维旋转或反射变换。在3D应用程序中,它们是存储和操作旋转的首选方式,因为它们不会像矩阵那样受到数值退化的影响。

四元数构造函数初始化为恒等变换

>>> q = Quaternion()
>>> q
Quaternion(real=1.00, imag=<0.00, 0.00, 0.00>)

### 元素访问

在内部,四元数存储为四个属性:xyz形成一个虚向量,而w是实部。

### 构造函数

可以使用构造函数形成旋转

new_identity() 等同于默认构造函数。

new_rotate_axis(angle, axis) 等同于同名Matrix4构造函数。 angle 以弧度指定,axisVector3 的一个实例。不需要对轴进行归一化。示例

>>> 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) 创建一个四元数,它给出在 q1q2 之间(SLERP)插值旋转。 q1q2Quaternion 的实例,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对象都可以相乘(例如,Point3Line3Sphere等)

>>> q * Ray3(Point3(1., 1., 1.), Vector3(1., 1., 1.))
Ray3(<1.00, 1.00, -1.00> + u<1.00, 1.00, -1.00>)

与矩阵类一样,构造函数也作为就地运算符提供。这些名称为 identityrotate_eulerrotate_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>)

四元数通常是单位长度,但您可能希望使用有大小四元数。在这种情况下,您可以使用与向量类相同的方式使用 absmagnitudemagnitude_squared 来找到大小。示例

>>> q1 = Quaternion()
>>> abs(q1)
1.0
>>> q1.magnitude()
1.0

同样,该类以与向量相同的方式实现了 normalizenormalized

以下方法不会改变四元数

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几何。每个形状的接口相似;特别是,connectdistance 方法对每个形状都定义相同。

例如,要找到一条线到圆上最近点

>>> 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)

Point2Vector2 的子类,因此所有 Vector2 操作符和方法都适用。特别是,两个点相减得到一个向量

>>> Point2(2.0, 3.0) - Point2(1.0, 0.0)
Vector2(1.00, 3.00)

还定义了以下方法

connect(other) 返回一个 LineSegment2,这是可以连接两个形状的最短线段。other 可以是一个 Point2Line2Ray2LineSegment2Circle

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。您也可以访问(但不能设置)两个端点 p1p2。这些可能对所有类型的线都很有意义。

以下方法由所有三个类支持

intersect(other) 如果 other 是一个 Line2Ray2LineSegment2,则返回一个交点 Point2,如果两条线平行则返回 None。

如果 other 是一个 Circle,则返回一个相交的 LineSegment2Point2,或者在没有交点的情况下返回 None。

connect(other) 返回一个 LineSegment2,它是连接两个形状的最短线段。对于两条平行线,此线段可能处于任意位置。other 可以是一个 Point2Line2Ray2LineSegment2Circle

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 是一个 Line2Ray2LineSegment2,则返回一个相交的 LineSegment2,如果没有交点则返回 None。

connect(other) 返回一个 LineSegment2,这是可以连接两个形状的最短线段。other 可以是一个 Point2Line2Ray2LineSegment2Circle

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)

Point3Vector3 的子类,因此所有 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 可以是一个 Point3Line3Ray3LineSegment3SpherePlane

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。您也可以访问(但不能设置)两个端点 p1p2。这些可能对所有类型的线都很有意义。

以下方法由所有三个类支持

intersect(other) 如果 other 是一个 Sphere,则返回一个与线相交的 LineSegment3,如果没有交点则返回 None

如果 other 是一个 Plane,则返回一个交点 Point3,或者返回 None

connect(other) 返回一个 LineSegment3,它是连接两个形状的最短线段。对于两条平行线,此线段可能处于任意位置。other 可以是一个 Point3Line3Ray3LineSegment3SpherePlane

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 是一个 Line3Ray3LineSegment3,则返回一个表示交点的 LineSegment3,如果没有交点则返回 None

connect(other) 返回一个 LineSegment3,它是连接两个形状的最短线段。other 可以是一个 Point3Line3Ray3LineSegment3SpherePlane

distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。

### 平面

平面可以通过以下方式之一构建:

  • 位于平面上的三个 Point3

  • 位于平面上的一个 Point3 和法向量 Vector3

  • 法向量 Vector3k,具体说明如下。

内部存储时,平面存储为法向量 n 和常数 k,使得对于平面上任意点 p,有 n.p = k

以下方法被支持

intersect(other):如果 other 是一个 Line3Ray3LineSegment3,则返回交点的 Point3,如果没有交点则返回 None

如果 other 是一个 Plane,则返回交点的 Line3

connect(other) 返回一个 LineSegment3,它是连接两个形状的最短线段。other 可以是一个 Point3Line3Ray3LineSegment3SpherePlane

distance(other) 返回到 other 的绝对最小距离。内部,这仅返回 connect 结果的长度。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分发

euclid-1.2.tar.gz (26.1 kB 查看哈希值)

上传时间 源代码

支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面