Spatial (3D) Math¶
Math utility library for common three-dimensional constructs:
The pint library can be used to specify dimensions:
>>> from petrify import u
>>> p = Point3(50, 25, 50) * u.mm
>>> p.to('m')
<Quantity(Point3(0.05, 0.025, 0.05), 'meter')>
Many methods are nominally supported when wrapped with pint. We recommend you only use units when exporting and importing data, and pick a canonical unit for all petrify operations.
Big thanks to pyeuclid, the source of most of the code here.
Note
These examples and this library make heavy use of the tau constant for rotational math instead of Pi. Read why at the Tau Manifesto.
-
class
petrify.space.Basis(origin, bx, by)[source]¶ Embeds a two-dimensional space into a three-dimensional space:
>>> basis = Basis(Point3(1, 0, 0), Vector3.basis.y, Vector3.basis.z) >>> basis.project(Point2(2, 3)) Point3(1, 2, 3) >>> basis.project(Vector2(-2, -3)) Vector3(1, -2, -3)
Can be translated:
>>> translated = basis.xy + Vector3(0, 0, 2) >>> translated Basis(Point3(0, 0, 2), Vector3(1, 0, 0), Vector3(0, 1, 0)) >>> translated.project(Point2(2, 3)) Point3(2, 3, 2)
There are special Basis objects for commonly used bases:
>>> Basis.unit Basis(Point3(0, 0, 0), Vector3(1, 0, 0), Vector3(0, 1, 0)) >>> Basis.xy Basis(Point3(0, 0, 0), Vector3(1, 0, 0), Vector3(0, 1, 0)) >>> Basis.yz Basis(Point3(0, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)) >>> Basis.xz Basis(Point3(0, 0, 0), Vector3(1, 0, 0), Vector3(0, 0, 1))
-
class
petrify.space.Face(basis, direction, polygon)[source]¶ A
PlanarPolygonwith an associated polarity. Face.Positive polarity follows the right hand rule, Face.Negative is inverted.>>> tri= Polygon2([ Point2(0, 0), Point2(0, 2), Point2(1, 1) ]) >>> triangle = Face(Basis.xy, Face.Positive, tri)
-
petrify.space.Line¶ alias of
petrify.space.Line3
-
class
petrify.space.Line3(*args)[source]¶ An infinite line:
>>> Line3(Point3(0, 0, 0), Vector3(1, 1, 1)) Line3(Point3(0, 0, 0), Vector3(1, 1, 1)) >>> Line3(Point3(0, 0, 0), Point3(1, 1, 1)) Line3(Point3(0, 0, 0), Vector3(1, 1, 1))
-
petrify.space.LineSegment¶ alias of
petrify.space.LineSegment3
-
petrify.space.Matrix¶ alias of
petrify.space.Matrix3
-
class
petrify.space.Matrix3[source]¶ A matrix that can be used to perform common transformations on three-dimensional points and vectors:
>>> Matrix3.scale(*Vector3(1, 2, 1).xyz) * Point3(1, 1, 1) Point3(1, 2, 1)
-
classmethod
identity()[source]¶ The identity transform:
>>> Matrix3.identity() * Point3(1, 1, 1) Point3(1.0, 1.0, 1.0)
-
classmethod
rotate_at(origin, axis, angle)[source]¶ A rotational transform:
>>> rotation = Matrix3.rotate_at(Point3(1, 1, 1), Vector3.basis.z, tau / 4) >>> (rotation * Point3(2, 1, 1)).rounded() Point3(1, 2, 1)
-
classmethod
rotate_axis(axis, angle)[source]¶ A rotational transform:
>>> (Matrix3.rotate_axis(Vector3.basis.z, tau / 4) * Point3(1, 0, 0)).rounded() Point3(0, 1, 0)
-
classmethod
-
class
petrify.space.PlanarPolygon(basis, polygon)[source]¶ A two-dimensional
petrify.plane.Polygon2orpetrify.plane.ComplexPolygon2embedded in three-dimensional space via aBasis:>>> tri = plane.Polygon2([ plane.Point2(0, 0), plane.Point2(0, 2), plane.Point2(1, 1) ]) >>> triangle = PlanarPolygon(Basis.xy, tri) >>> triangle.project() [Polygon3([Point3(0, 0, 0), Point3(0, 2, 0), Point3(1, 1, 0)])]
-
class
petrify.space.Plane(*args)[source]¶ A three-dimensional plane.
Can be constructed with three coplanar points:
>>> Plane(Point3(0, 0, 0), Point3(1, 0, 0), Point3(0, 1, 0)) Plane(Vector3(0.0, 0.0, 1.0), 0.0)
Or an origin point and two basis vectors: >>> Plane(Point3(0, 0, 0), Vector3.basis.x, Vector3.basis.y) Plane(Vector3(0.0, 0.0, 1.0), 0.0)
Or a normal and solution scalar / point:
>>> Plane(Vector3.basis.z, 0) Plane(Vector3(0.0, 0.0, 1.0), 0) >>> Plane(Vector3.basis.z, Point3.origin) Plane(Vector3(0.0, 0.0, 1.0), 0.0)
Plane also defines convenience methods for commonly used origin planes:
>>> Plane.xy Plane(Vector3(0.0, 0.0, 1.0), 0.0) >>> Plane.xz Plane(Vector3(0.0, 1.0, 0.0), 0.0) >>> Plane.yz Plane(Vector3(1.0, 0.0, 0.0), 0.0)
-
intersect(other)[source]¶ Find the point where this plane intersects the other line or plane:
>>> Plane(Vector3(0, 1, 0), 1).intersect(Plane(Vector3(1, 0, 0), 2)) Line3(Point3(2.0, 1.0, 0.0), Vector3(0.0, 0.0, 1.0)) >>> Plane(Vector3(0, 0, 1), 2).intersect(Line3(Point3(0, 0, 0), Vector3(1, 1, 1))) Point3(2.0, 2.0, 2.0)
-
-
petrify.space.Point¶ alias of
petrify.space.Point3
-
class
petrify.space.Point3(x=0, y=0, z=0)[source]¶ A close cousin of
petrify.space.Vector3, used to represent a point instead of a transform.Defines a convenience .origin attribute for this commonly-used point:
>>> Point3.origin Point3(0, 0, 0)
-
petrify.space.Polygon¶ alias of
petrify.space.Polygon3
-
class
petrify.space.Polygon3(points)[source]¶ A linear cycle of coplanar convex points:
>>> triangle = Polygon3([Point3(0, 0, 0), Point3(0, 2, 0), Point3(1, 1, 0)]) >>> triangle.plane Plane(Vector3(0.0, 0.0, -1.0), 0.0)
-
simplify(tolerance=0.0001)[source]¶ Remove any duplicate points, within a certain tolerance:
>>> Polygon3([Point3(1, 1, 0), Point3(2, 0, 0), Point3(0, 0, 0), Point3(1, 1, 0)]).simplify() Polygon3([Point3(2, 0, 0), Point3(0, 0, 0), Point3(1, 1, 0)])
Returns None if the resulting simplification would create a point:
>>> Polygon3([Point3(1, 1, 0), Point3(2, 0, 0), Point3(0, 0, 0)]).simplify(100) is None True
-
-
class
petrify.space.Quaternion(w=1, x=0, y=0, z=0)[source]¶ Quaternions are composable representations of three-dimensional rotation operations.
Multiplication can be performed on Vector3 instances to get the transformed vector or point:
>>> r = Quaternion.rotate_axis(Vector3.basis.x, tau / 4); >>> (r * Vector3(0, 1, 0)).rounded() Vector3(0, 0, 1)
-
petrify.space.Ray¶ alias of
petrify.space.Ray3
-
class
petrify.space.Ray3(*args)[source]¶ A
Line3with a fixed origin that continues indefinitely in the given direction.
-
class
petrify.space.Sphere(center, radius)[source]¶ A perfect sphere with the provided center and radius:
>>> Sphere(Point3(0, 0, 0), 1.0) Sphere(Point3(0, 0, 0), 1.0)
-
petrify.space.Vector¶ alias of
petrify.space.Vector3
-
class
petrify.space.Vector3(x=0, y=0, z=0)[source]¶ A three-dimensional vector supporting all corresponding built-in math operators:
>>> Vector3(1, 2, 3) + Vector3(2, 2, 2) Vector3(3, 4, 5) >>> Vector3(1, 2, 3) - Vector3(2, 2, 2) Vector3(-1, 0, 1) >>> Vector3(1, 0, 1) * 5 Vector3(5, 0, 5) >>> Vector3(1, 0, 1) / 5 Vector3(0.2, 0.0, 0.2) >>> Vector3(1, 1, 1) == Vector3(1, 1, 1) True
In addition to many other specialized vector operations.
Defines convenience .basis members for commonly used basis vectors:
>>> Vector3.basis.x; Vector3.bx Vector3(1, 0, 0) Vector3(1, 0, 0) >>> Vector3.basis.y; Vector3.by Vector3(0, 1, 0) Vector3(0, 1, 0) >>> Vector3.basis.z; Vector3.bz Vector3(0, 0, 1) Vector3(0, 0, 1)
-
reflect(normal)[source]¶ Reflect this vector across a plane with the given normal
Note
Assumes the given normal has unit (1) length.
-