Package: euclid
Python module for 2D and 3D graphics-related maths functions: vectors, matrices, quaternions and simple plane/line/sphere geometry.HistoryThis library was written in 2006 and [hosted on Google Code](https://code.google.com/archive/p/pyeuclid/) under an LGPL license.  Alex relicensed the code in 2019 under a more permissive BSD license.  It was updated to work with Python 3 soon after, and released as 1.0 in 2020 by the new maintainer, Richard Jones.The rest of this README is the original documentation from 2006, converted from reStructured Text to Markdown using cloudconvert.com.OverviewThis document describes theeuclidmodule, which provides vector, matrix and quaternion classes for 2D and 3D graphics applications. Everything is provided in theeuclidnamespace:>>> from euclid import *
>>>Type checking of arguments is done with assertions. The advantage of this is that in a usual Python session an exception will be raised earlier rather than later, with a message indicating the expected type. When Python is run with the-Oor-OOflags, assertions are removed and the code executes faster.Vector classesTwo mutable vector types are available:Vector2andVector3, for 2D and 3D vectors, respectively. Vectors are assumed to hold floats, but most operations will also work if you use ints or longs instead. Construct a vector in the obvious way:>>> Vector2(1.5, 2.0)
Vector2(1.50, 2.00)>>> Vector3(1.0, 2.0, 3.0)
Vector3(1.00, 2.00, 3.00)### Element accessComponents may be accessed as attributes (examples that follow useVector3, but all results are similar forVector2, using only thexandycomponents):>>> v = Vector3(1, 2, 3)
>>> v.x
1
>>> v.y
2
>>> v.z
3Vectors support the list interface via slicing:>>> v = Vector3(1, 2, 3)
>>> len(v)
3
>>> v[0]
1
>>> v[:]
(1, 2, 3)You can also “swizzle” the components (a laGLSL or Cg):>>> v = Vector3(1, 2, 3)
>>> v.xyz
(1, 2, 3)
>>> v.zx
(3, 1)
>>> v.zzzz
(3, 3, 3, 3)All of the above accessors are also mutators[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] assignment via a swizzle (e.g.,v.xyz = (1, 2, 3)) is supported only if the_enable_swizzle_setvariable is set. This is disabled by default, as it impacts on the performance of ordinary attribute setting, and is slower than setting components sequentially anyway.### OperatorsAddition and subtraction are supported via operator overloading (note that in-place operators perform faster than those that create a new object):>>> 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)Multiplication and division can be performed with a scalar only:>>> 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)The magnitude of a vector can be found withabs:>>> v = Vector3(1., 2., 3.)
>>> abs(v)
3.7416573867739413A vector can be normalized in-place (note that the in-place method also returnsself, so you can chain it with further operators):>>> v = Vector3(1., 2., 3.)
>>> v.normalize()
Vector3(0.27, 0.53, 0.80)
>>> v
Vector3(0.27, 0.53, 0.80)The following methods donotalter the original vector or their arguments:copy()Returns a copy of the vector.__copy__is also implemented.magnitude()Returns the magnitude of the vector; equivalent toabs(v). Example:>>> v = Vector3(1., 2., 3.)
>>> v.magnitude()
3.7416573867739413magnitude_squared()Returns the sum of the squares of each component. Useful for comparing the length of two vectors without the expensive square root operation. Example:>>> v = Vector3(1., 2., 3.)
>>> v.magnitude_squared()
14.0normalized()Return a unit length vector in the same direction. Note that this method differs fromnormalizein that it does not modify the vector in-place. Example:>>> v = Vector3(1., 2., 3.)
>>> v.normalized()
Vector3(0.27, 0.53, 0.80)
>>> v
Vector3(1.00, 2.00, 3.00)dot(other)Return the scalar “dot” product of two vectors. Example:>>> v1 = Vector3(1., 2., 3.)
>>> v2 = Vector3(4., 5., 6.)
>>> v1.dot(v2)
32.0cross()andcross(other)Return the cross product of a vector (forVector2), or the cross product of two vectors (forVector3). The return type is a vector. Example:>>> v1 = Vector3(1., 2., 3.)
>>> v2 = Vector3(4., 5., 6.)
>>> v1.cross(v2)
Vector3(-3.00, 6.00, -3.00)In two dimensions there can be no argument tocross:>>> v1 = Vector2(1., 2.)
>>> v1.cross()
Vector2(2.00, -1.00)reflect(normal)Return the vector reflected about the given normal. In two dimensions,normalis the normal to a line, in three dimensions it is the normal to a plane. The normal must have unit length. Example:>>> 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)For 3D vectors, return the vector rotated around axis by the angle 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)Return the angle between two vectors.project(other)Return the projection (the component) of the vector on other.Tests for equality include comparing against other sequences:>>> 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)
TrueVectors are not hashable, and hence cannot be put in sets nor used as dictionary keys:>>> {Vector2(): 0}
Traceback (most recent call last):
    ...
TypeError: unhashable type: 'Vector2'>>> {Vector3(): 0}
Traceback (most recent call last):
    ...
TypeError: unhashable type: 'Vector3'Matrix classesTwo matrix classes are supplied,Matrix3, a 3x3 matrix for working with 2D affine transformations, andMatrix4, a 4x4 matrix for working with 3D affine transformations.The default constructor intializes the matrix to the identity:>>> 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])### Element accessInternally each matrix is stored as a set of attributes namedatop. The layout for Matrix3 is:# a b c
# e f g
# i j kand for Matrix4:# a b c d
# e f g h
# i j k l
# m n o pIf you wish to set or retrieve a number of elements at once, you can do so with a slice:>>> 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])Note that slices operate in column-major order, which makes them suitable for working directly with OpenGL’sglLoadMatrixandglGetFloatvfunctions.### Class constructorsThere are class constructors for the most common types of transform.new_identityEquivalent to the default constructor. Example:>>> 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)andnew_scale(x, y, z)The former is defined onMatrix3, the latter onMatrix4. Equivalent to the OpenGL callglScalef. Example:>>> 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)andnew_translate(x, y, z)The former is defined onMatrix3, the latter onMatrix4. Equivalent to the OpenGL callglTranslatef. Example:>>> 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)Create aMatrix3for a rotation around the origin.angleis specified in radians, anti-clockwise. This is not implemented inMatrix4(see below for equivalent methods). Example:>>> 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])The following constructors are defined forMatrix4only.newConstruct a matrix with 16 values in column-major order.new_rotatex(angle),new_rotatey(angle),new_rotatez(angle)Create aMatrix4for a rotation around the X, Y or Z axis, respectively.angleis specified in radians. Example:>>> 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)Create aMatrix4for a rotation around the given axis.angleis specified in radians, andaxismust be an instance ofVector3. It is not necessary to normalize the axis. Example:>>> 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)Create aMatrix4for the given Euler rotation.headingis a rotation around the Y axis,attitudearound the X axis andbankaround the Z axis. All rotations are performed simultaneously, so this method avoids “gimbal lock” and is the usual method for implemented 3D rotations in a game. Example:>>> 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)Create aMatrix4for projection onto the 2D viewing plane. This method is equivalent to the OpenGL callgluPerspective.fov_yis the view angle in the Y direction, in radians.aspectis the aspect rationwidth/heightof the viewing plane.nearandfarare the distance to the near and far clipping planes. They must be positive and non-zero. Example:>>> 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])### OperatorsMatrices of the same dimension may be multiplied to give a new matrix. For example, to create a transform which translates and scales:>>> 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])Note that multiplication is not commutative (the order that you apply transforms matters):>>> m2 * m1
Matrix3([    1.00     0.00     5.00
             0.00     2.00    12.00
             0.00     0.00     1.00])In-place multiplication is also permitted (and optimised):>>> m1 *= m2
>>> m1
Matrix3([    1.00     0.00     5.00
             0.00     2.00     6.00
             0.00     0.00     1.00])Multiplying a matrix by a vector returns a vector, and is used to transform a vector:>>> m1 = Matrix3.new_rotate(math.pi / 2)
>>> m1 * Vector2(1.0, 1.0)
Vector2(-1.00, 1.00)Note that translations have no effect on vectors. They do affect points, however:>>> 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)Multiplication is currently incorrect between matrices and vectors – the projection component is ignored. Use theMatrix4.transformmethod instead.Matrix4 also definestranspose(in-place),transposed(functional),determinantandinverse(functional) methods.AMatrix3can be multiplied with aVector2or any of the 2D geometry objects (Point2,Line2,Circle, etc).AMatrix4can be multiplied with aVector3or any of the 3D geometry objects (Point3,Line3,Sphere, etc).For convenience, each of the matrix constructors are also available as in-place operators. For example, instead of writing:>>> m1 = Matrix3.new_translate(5.0, 6.0)
>>> m2 = Matrix3.new_scale(1.0, 2.0)
>>> m1 *= m2you can apply the scale directly tom1:>>> 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])Note that these methods operate in-place (they modify the original matrix), and they also return themselves as a result. This allows you to chain transforms together directly:>>> 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])All constructors have an equivalent in-place method. ForMatrix3, they areidentity,translate,scaleandrotate. ForMatrix4, they areidentity,translate,scale,rotatex,rotatey,rotatez,rotate_axisandrotate_euler. BothMatrix3andMatrix4also have an in-placetransposemethod.Thecopymethod is also implemented in both matrix classes and behaves in the obvious way.QuaternionsA quaternion represents a three-dimensional rotation or reflection transformation. They are the preferred way to store and manipulate rotations in 3D applications, as they do not suffer the same numerical degredation that matrices do.The quaternion constructor initializes to the identity transform:>>> q = Quaternion()
>>> q
Quaternion(real=1.00, imag=<0.00, 0.00, 0.00>)### Element accessInternally, the quaternion is stored as four attributes:x,yandzforming the imaginary vector, andwthe real component.### ConstructorsRotations can be formed using the constructors:new_identity()Equivalent to the default constructor.new_rotate_axis(angle, axis)Equivalent to the Matrix4 constructor of the same name.angleis specified in radians,axisis an instance ofVector3. It is not necessary to normalize the axis. Example:>>> 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)Equivalent to the Matrix4 constructor of the same name.headingis a rotation around the Y axis,attitudearound the X axis andbankaround the Z axis. All angles are given in radians. Example:>>> 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)Create a quaternion which gives a (SLERP) interpolated rotation betweenq1andq2.q1andq2are instances ofQuaternion, andtis a value between 0.0 and 1.0. For example:>>> 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>)### OperatorsQuaternions may be multiplied to compound rotations. For example, to rotate 90 degrees around the X axis and then 90 degrees around the Y axis:>>> 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>)Multiplying a quaternion by a vector gives a vector, transformed appropriately:>>> 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)Similarly, any 3D object can be multiplied (e.g.,Point3,Line3,Sphere, etc):>>> q * Ray3(Point3(1., 1., 1.), Vector3(1., 1., 1.))
Ray3(<1.00, 1.00, -1.00> + u<1.00, 1.00, -1.00>)As with the matrix classes, the constructors are also available as in-place operators. These are namedidentity,rotate_eulerandrotate_axis. For example:>>> 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>)Quaternions are usually unit length, but you may wish to use sized quaternions. In this case, you can find the magnitude usingabs,magnitudeandmagnitude_squared, as with the vector classes. Example:>>> q1 = Quaternion()
>>> abs(q1)
1.0
>>> q1.magnitude()
1.0Similarly, the class implementsnormalizeandnormalizedin the same way as the vectors.The following methods do not alter the quaternion:conjugated()Returns a quaternion that is the conjugate of the instance. For example:>>> 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()Returns a tuple (angle, axis), giving the angle to rotate around an axis equivalent to the quaternion. For example:>>> 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()Returns aMatrix4implementing the transformation of the quaternion. For example:>>> 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 GeometryThe following classes are available for dealing with simple 2D geometry. The interface to each shape is similar; in particular, theconnectanddistancemethods are defined identically for each.For example, to find the closest point on a line to a circle:>>> circ = Circle(Point2(3., 2.), 2.)
>>> line = Line2(Point2(0., 0.), Point2(-1., 1.))
>>> line.connect(circ).p1
Point2(0.50, -0.50)To find the corresponding closest point on the circle to the line:>>> line.connect(circ).p2
Point2(1.59, 0.59)### Point2A point on a 2D plane. Construct in the obvious way:>>> p = Point2(1.0, 2.0)
>>> p
Point2(1.00, 2.00)Point2subclassesVector2, so all ofVector2operators and methods apply. In particular, subtracting two points gives a vector:>>> Point2(2.0, 3.0) - Point2(1.0, 0.0)
Vector2(1.00, 3.00)The following methods are also defined:connect(other)Returns aLineSegment2which is the minimum length line segment that can connect the two shapes.othermay be aPoint2,Line2,Ray2,LineSegment2orCircle.distance(other)Returns the absolute minimum distance toother. Internally this simply returns the length of the result ofconnect.### Line2, Ray2, LineSegment2ALine2is a line on a 2D plane extending to infinity in both directions; aRay2has a finite end-point and extends to infinity in a single direction; aLineSegment2joins two points.All three classes support the same constructors, operators and methods, but may behave differently when calculating intersections etc.You may construct a line, ray or line segment using any of:another line, ray or line segmenttwo pointsa point and a vectora point, a vector and a lengthFor example:>>> 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>)Internally, lines, rays and line segments store a Point2pand a Vector2v. You can also access (but not set) the two endpointsp1andp2. These may or may not be meaningful for all types of lines.The following methods are supported by all three classes:intersect(other)Ifotheris aLine2,Ray2orLineSegment2, returns aPoint2of intersection, or None if the lines are parallel.Ifotheris aCircle, returns aLineSegment2orPoint2giving the part of the line that intersects the circle, or None if there is no intersection.connect(other)Returns aLineSegment2which is the minimum length line segment that can connect the two shapes. For two parallel lines, this line segment may be in an arbitrary position.othermay be aPoint2,Line2,Ray2,LineSegment2orCircle.distance(other)Returns the absolute minimum distance toother. Internally this simply returns the length of the result ofconnect.LineSegment2also has alengthproperty which is read-only.### CircleCircles are constructed with a centerPoint2and a radius:>>> c = Circle(Point2(1.0, 1.0), 0.5)
>>> c
Circle(<1.00, 1.00>, radius=0.50)Internally there are two attributes:c, giving the center point andr, giving the radius.The following methods are supported:intersect(other)Ifotheris aLine2,Ray2orLineSegment2, returns aLineSegment2giving the part of the line that intersects the circle, or None if there is no intersection.connect(other)Returns aLineSegment2which is the minimum length line segment that can connect the two shapes.othermay be aPoint2,Line2,Ray2,LineSegment2orCircle.distance(other)Returns the absolute minimum distance toother. Internally this simply returns the length of the result ofconnect.3D GeometryThe following classes are available for dealing with simple 3D geometry. The interfaces are very similar to the 2D classes (but note that you cannot mix and match 2D and 3D operations).For example, to find the closest point on a line to a sphere:>>> 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)To find the corresponding closest point on the sphere to the line:>>> line.connect(sphere).p2
Point3(1.32, 1.68, 1.05)XXX I have not checked if these are correct.### Point3A point on a 3D plane. Construct in the obvious way:>>> p = Point3(1.0, 2.0, 3.0)
>>> p
Point3(1.00, 2.00, 3.00)Point3subclassesVector3, so all ofVector3operators and methods apply. In particular, subtracting two points gives a vector:>>> Point3(1.0, 2.0, 3.0) - Point3(1.0, 0.0, -2.0)
Vector3(0.00, 2.00, 5.00)The following methods are also defined:intersect(other)Ifotheris aSphere, returnsTrueiff the point lies within the sphere.connect(other)Returns aLineSegment3which is the minimum length line segment that can connect the two shapes.othermay be aPoint3,Line3,Ray3,LineSegment3,SphereorPlane.distance(other)Returns the absolute minimum distance toother. Internally this simply returns the length of the result ofconnect.### Line3, Ray3, LineSegment3ALine3is a line on a 3D plane extending to infinity in both directions; aRay3has a finite end-point and extends to infinity in a single direction; aLineSegment3joins two points.All three classes support the same constructors, operators and methods, but may behave differently when calculating intersections etc.You may construct a line, ray or line segment using any of:another line, ray or line segmenttwo pointsa point and a vectora point, a vector and a lengthFor example:>>> 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>)Internally, lines, rays and line segments store a Point3pand a Vector3v. You can also access (but not set) the two endpointsp1andp2. These may or may not be meaningful for all types of lines.The following methods are supported by all three classes:intersect(other)Ifotheris aSphere, returns aLineSegment3which is the intersection of the sphere and line, orNoneif there is no intersection.Ifotheris aPlane, returns aPoint3of intersection, orNone.connect(other)Returns aLineSegment3which is the minimum length line segment that can connect the two shapes. For two parallel lines, this line segment may be in an arbitrary position.othermay be aPoint3,Line3,Ray3,LineSegment3,SphereorPlane.distance(other)Returns the absolute minimum distance toother. Internally this simply returns the length of the result ofconnect.LineSegment3also has alengthproperty which is read-only.### SphereSpheres are constructed with a centerPoint3and a radius:>>> s = Sphere(Point3(1.0, 1.0, 1.0), 0.5)
>>> s
Sphere(<1.00, 1.00, 1.00>, radius=0.50)Internally there are two attributes:c, giving the center point andr, giving the radius.The following methods are supported:intersect(other):
Ifotheris aPoint3, returnsTrueiff the point lies within the sphere.Ifotheris aLine3,Ray3orLineSegment3, returns aLineSegment3giving the intersection, orNoneif the line does not intersect the sphere.connect(other)Returns aLineSegment3which is the minimum length line segment that can connect the two shapes.othermay be aPoint3,Line3,Ray3,LineSegment3,SphereorPlane.distance(other)Returns the absolute minimum distance toother. Internally this simply returns the length of the result ofconnect.### PlanePlanes can be constructed with any of:threePoint3’s lying on the planeaPoint3on the plane and theVector3normalaVector3normal andk, described below.Internally, planes are stored with the normalnand constantksuch thatn.p=kfor any point on the planep.The following methods are supported:intersect(other)Ifotheris aLine3,Ray3orLineSegment3, returns aPoint3of intersection, orNoneif there is no intersection.Ifotheris aPlane, returns theLine3of intersection.connect(other)Returns aLineSegment3which is the minimum length line segment that can connect the two shapes.othermay be aPoint3,Line3,Ray3,LineSegment3,SphereorPlane.distance(other)Returns the absolute minimum distance toother. Internally this simply returns the length of the result ofconnect.