geometry — wrapper classes for vectors, segments, polygons etc.¶
Vector reference¶
Constructor:
-
class
geometry.Vector(x, y)¶ Vector instance represents an Euclidean vector. It stores a pair od 2D corrdinates (x, y).
Vectors are immutable.
Vectors are used for the following purposes:
storing an actual vector pointing from (0, 0) to (x, y), for example
nodes.BodyNode.velocitystoring a 2D point, for example
nodes.Node.positionstoring a width/height of a rectangular shape, such as a screen resolution. For example
engine.Engine.virtual_resolution
Vector constructor accepts two float numbers: x and y.
Available operators:
Adding two vectors:
Vector(1,1) + Vector(2,2)Substracting two vectors:
Vector(1,1) - Vector(2,2)Multiplying vector by a scalar:
Vector(1,1) * 123Dividing vector by a scalar:
Vector(1,1) / 123
Class methods:
-
classmethod
Vector.from_angle(angle)¶ Creates a new unit Vector (i.e. length 1 vector) from angle, in radians.
import math from kaa.geometry import Vector v = Vector.from_angle(math.pi / 4) print(v) # V[0.7071067811865476, 0.7071067811865475] print(v.length()) # 1.0
-
classmethod
Vector.from_angle_degrees(degrees)¶ Creates a new unit Vector (i.e. length 1 vector) from angle, in degrees.
import math from kaa.geometry import Vector v = Vector.from_angle_degrees(90) # 90 degrees is pointing up, 180, pointing left, 270 pointing down etc. print(v) # V[0.0, 1.0] print(v.length()) # 1.0
Instance Properties (read only):
-
Vector.x¶ Gets the x value of a vector
-
Vector.y¶ Gets the y value of a vector
Instance Methods:
-
Vector.is_zero()¶ Returns
Trueif vector is a zero vectorfrom kaa.geometry import Vector Vector(0, 0).is_zero() # True Vector(0.1, 0).is_zero() # False
-
Vector.rotate_angle(angle)¶ Returns a new vector, rotated by given angle, in radians.
from kaa.geometry import Vector import math print(Vector(10, 0)) # V[10, 0] print(Vector(10, 0).rotate_angle(math.pi)) # V[-10, 0]
-
Vector.rotate_angle_degrees(degrees)¶ Returns a new vector, rotated by given angle, in degrees.
from kaa.geometry import Vector import math print(Vector(10, 0)) # V[10, 0] print(Vector(10, 0).rotate_angle_degrees(180)) # V[-10, 0]
-
Vector.to_angle()¶ Returns vector’s angle, in radians.
-
Vector.to_angle_degrees()¶ Returns vector’s angle, in degrees.
-
Vector.dot(other_vector)¶ Returns dot product of two vectors. other_vector parameter must be
geometry.Vector
-
Vector.distance(other_vector)¶ Returns a distance from (x,y) to (other_vector.x, other_vector.y), in other words: distance between two points. other_vector parameter must be
geometry.Vector
-
Vector.angle_between(other_vector)¶ Returns angle between this vector and
other_vector, in radians. The other_vector parameter must begeometry.Vector
-
Vector.angle_between_degrees(other_vector)¶ Returns angle between this vector and
other_vector, in degrees. The other_vector parameter must begeometry.Vector
-
Vector.normalize()¶ Returns a new vector, normalized (i.e. unit vector)
-
Vector.length()¶ Returns vector’s length.
Segment reference¶
Constructor:
-
class
geometry.Segment(vector_a, vector_b)¶ Segment instance represents a segment between two points, a and b.
Segments are immutable.
vector_a and vector_b params are
geometry.Vectorinstances indicating both ends of a Segment
Instance properties:
-
Segment.point_a¶ Read only. Returns point A of the segment
-
Segment.point_b¶ Read only. Returns point B of the segment
-
Segment.bounding_box¶ Read only. Returns segment’s bounding box as
geometry.BoundingBox.
Instance methods:
-
Segment.transform(transformation)¶ Applies given transformation to this Segment and returns a new Segment.
The
transformationparameter must be aTransformationinstance.
Circle reference¶
Constructor:
-
class
geometry.Circle(radius, center=Vector(0, 0))¶ Circle instance represents a circualar shape, with a center and a radius. Circles are used e.g. for creating hitboxes.
Circles are immutable.
The
centerparameter must begeometry.Vector, radius is a number.
Instance properties:
-
Circle.radius¶ Read only. Returns circle radius.
-
Circle.center¶ Read only. Returns circle center.
-
Circle.bounding_box¶ Read only. Returns circle bounding box as
geometry.BoundingBox.
Instance methods:
-
Circle.transform(transformation)¶ Applies given transformation to this Circle and returns a new Circle.
The
transformationparameter must be aTransformationinstance.
Polygon reference¶
Constructor:
-
class
geometry.Polygon(points)¶ Polygon instance represents a custom shape. Polygons are used e.g. for creating hitboxes.
Polygons are immutable.
The
pointsparameter must be a list ofgeometry.Vectorinstances.If you don’t close the polygon (the last point in the list is not identical with the first one) kaa will do that for you.
The polygon must be convex. Kaa engine will throw an exception if you try to create a non-convex polygon. You may use
classify_polygon()function to check if a list of points will form a convex polygon or not.from kaa.geometry import Polygon polygon = Polygon([Vector(-10, -10), Vector(10, 30), Vector(0, 40)]) # a triangular-shaped polygon
Class methods:
-
classmethod
Polygon.from_box(vector)¶ Creates a rectangular-shaped Polygon whose central point is at (0, 0) and width and height are passed as vector.x and vector.y respectively. A useful shorthand function for creating a rectangular shape for a
physics.HitboxNode.from kaa.geometry import Polygon, Vector poly = Polygon.from_box(Vector(10, 8)) # creates a rectangular polygon [ V(-5, -4), V(5, -4), V(5, 4), V(-5, 4) ]
Instance properties:
-
Polygon.points¶ Read only. Returns a list of points constituting the Polygon.
-
Polygon.bounding_box¶ Read only. Returns polygon’s bounding box as
geometry.BoundingBox.
Instance methods:
-
Polygon.transform(transformation)¶ Applies given transformation to this Polygon and returns a new Polygon.
The
transformationparameter must be aTransformationinstance.
Transformation reference¶
-
class
geometry.Transformation¶ Transformation is a ‘geometrical recipe’, which can be applied to a
Segment,CircleorPolygon(using thetransform()method) to change their position, rotation and scale.Transformations cannot be applied to Nodes, although if a Node has a shape, you can apply Transformations to that shape.
Transformation objects are immutable.
Transformation constructor does not accept any parameters and creates a ‘void’ transformation which, when applied, does not have any effect.
To create an actual Transformation use one of the class methods:
rotate(),rotate_degrees(),scale()ortranslate()from kaa.geometry import Transformation import math t1 = Transformation.rotate(math.pi / 2) # a 90 degrees transformation, clockwise t2 = Transformation.rotate_degrees(-45) # a 45 degrees transformation, anti-clockwise t3 = Transformation.scale(Vector(2,2)) # scale change transformation (enlarge twice) t4 = Transformation.translate(Vector(10, 0)) # position change transformation (10 units to the right)
You can chain transformations by applying the
|operator, which results in a new, combined transformations:combined_transformation = t1 | t2 | t3 | t4
Rotation and scaling is always relative to the origin of the Euclidean space, or in other words, relative to (0,0) point. Therefore, a sequence of transformations in a chain is important. Consider the following two transformations:
rotate_than_move = t2 | t4 move_than_rotate = t4 | t2
Contrary to intuition they won’t give the same result. When applied to a square with an edge length of 1 and the middle in the (0,0) the first one will rotate the square 45 degrees around (0,0) and then move 10 units to the right, while the second one will move the square 10 units to the right and then rotate, but since the center of the square is now at (10,0) the rotation is going to “wheel” it 45 degrees around the (0,0), making the Polygon end up in a different position. It’s illustrated in the example below:
from kaa.geometry import Vector, Polygon square = Polygon.from_box(Vector(2,2)) print(square.points) #[V[-1.0, -1.0], V[1.0, -1.0], V[1.0, 1.0], V[-1.0, 1.0]] # just move it square_2 = square.transform(t4) print(square_2.points) #[V[9.0, -1.0], V[11.0, -1.0], V[11.0, 1.0], V[9.0, 1.0]] # rotate then move square_3 = square.transform(t2 | t4) print(square_3.points) # [V[8.585, 0.0], V[10.0, -1.414], V[11.414, 0.0], V[10.0, 1.414]] # move then rotate square_4 = square.transform(t4 | t2) print(square_4.points) # [V[5.656, -7.071], V[7.071, -8.485], V[8.485, -7.071], V[7.0710, -5.656]]
Using the @ operator you can chain transformation in the matrix-style order:
rotate_then_move = t2 | t4 move_then_rotate = t2 @ t4
Finally, you can use the
inverse()method on the Transformation instance to get the inversed transformation:combined_transformation = t1 | t2 | t3 | t4 inversed_combined_transformation = combined_transformation.inverse()
Class methods:
-
classmethod
Transformation.rotate(rotation)¶ Creates a new rotation Transformation. The
rotationvalue must be a number (rotation in radians).
-
classmethod
Transformation.rotate_degrees(rotation_degrees)¶ Creates a new rotation Transformation. The
rotationvalue must be a number (rotation in degrees).
-
classmethod
Transformation.scale(scaling_vector)¶ Creates a new scaling Transformation. The
scaling_vectormust be aVectorwhose x and y represent scaling in x and y axis respectively.
-
classmethod
Transformation.translate(translation_vector)¶ Creates a new translation (position change) Transformation. The
translation_vectormust be aVector.
Instance methods:
-
Transformation.inverse()¶ Returns a new Transformation, being an inversed version of this Transformation.
-
Transformation.decompose()¶ Returns a
DecomposedTransformationobject which allows reading transformation’s translation, rotation and scale.combined_transformation = t1 | t2 | t3 | t4 result = combined_transformation.decompose() print(result.translation, result.rotation, result.rotation_degrees, result.scale)
DecomposedTransformation reference¶
-
class
geometry.DecomposedTransformation¶
Object returned by Transformation.decompose(). It surfaces transformation properties.
Instance properties:
-
DecomposedTransformation.translation¶ Returns translation as
geometry.Vector
-
DecomposedTransformation.rotation¶ Returns rotation as float, in radians
-
DecomposedTransformation.rotation_degrees¶ Returns rotation as float, in degrees
-
DecomposedTransformation.scale¶ Returns scale, as
geometry.Vector
BoundingBox reference¶
-
class
geometry.BoundingBox(min_x, min_y, max_x, max_y)¶ Represents a rectangular bounding box. Bounding box is always aligned with x and y axis. Bounding boxes are being used when querying for nodes on scene. Constructor accepts four parameters, which determine the bounding box x and y limits. You can also construct the BoundingBox using helper methods
BoundingBox.single_point()andBoundingBox.from_points()
Class methods:
-
classmethod
BoundingBox.single_point(point)¶ Creates a BoundingBox from a single point. The
pointparameter must be ageometry.Vectorrepresenting point coordinates. A single point BoundingBox has no width/height.
-
classmethod
BoundingBox.from_points(points)¶ Creates a BoundingBox from points. The
pointsmust be a list ofgeometry.Vectorinstances, representing point coordinates.If
pointslist is empty, it will return bounding box with NaN values.If
pointslist has 1 point, it behaves exactly likeBoundingBox.single_point()If
pointslist has 2 or more points, it will return smallest box which contains all provided points.
Instance properties:
-
BoundingBox.min_x¶ Gets min_x of the bounding box.
-
BoundingBox.min_y¶ Gets min_y of the bounding box.
-
BoundingBox.max_x¶ Gets max_x of the bounding box.
-
BoundingBox.max_y¶ Gets max_y of the bounding box.
-
BoundingBox.is_nan¶ Gets “not a number” status of the bounding box, as
bool
-
BoundingBox.center¶ Gets the central point of the bounding box, as
geometry.Vector.
-
BoundingBox.dimensions¶ Gets dimensions of the bounding box, as
geometry.Vector, x being width and y being height.
Instance methods:
-
BoundingBox.merge(other_bounding_box)¶ Merges the bounding box with other and returns a new bounding box.
-
BoundingBox.contains(other)¶ Other can be
BoundingBoxorgeometry.Vector. ReturnsTrueif bounding box contains other bounding box or point.
-
BoundingBox.intersects(other_bounding_box)¶ Returns
Trueif bounding box intersects with othergeometry.BoundingBox, otherwise returnsFalse
-
BoundingBox.intersection(other_bounding_box)¶ If bounding box intersects with other
geometry.BoundingBoxaBoundingBoxis returned which spans the intersection. If there’s no intersection, an ‘empty’geometry.BoundingBoxis returned (all properties set to NaN)
-
BoundingBox.grow(vector)¶ Grows the bounding box by given vector (adds the vector’s x and y value to the corresponding sides of the bounding box). The
vectorparam must begeometry.Vector
Alignment reference¶
-
class
geometry.Alignment¶
Enum type used to set Node’s origin alignment to one of the 9 positions. See nodes.Node.origin_alignment
Available values are:
Alignment.noneAlignment.topAlignment.bottomAlignment.leftAlignment.rightAlignment.top_leftAlignment.bottom_leftAlignment.top_rightAlignment.bottom_rightAlignment.center
PolygonType reference¶
-
class
geometry.PolygonType¶
Enum type returned by the classify_polygon() function. Available values:
PolygonType.convex_cw- the list of points forms a convex polygon, the points are ordered clockwisePolygonType.convex_ccw- the list of points forms a convex polygon, the points are ordered counter clockwisePolygonType.not_convex- the list of points forms a non-convex polygon
classify_polygon() reference¶
-
geometry.classify_polygon(polygon)¶
Accepts a list of points (list of geometry.Vector) and returns if polygon formed by those points is convex or
not. The function returns a PolygonType enum value.
from kaa.geometry import Vector, classify_polygon
print(classify_polygon([Vector(0, 0), Vector(10, 0), Vector(10, 10), Vector(0, 10)])) # PolygonType.conwex_ccw
print(classify_polygon([Vector(0, 0), Vector(0, 10), Vector(10, 10), Vector(10, 0)])) # PolygonType.conwex_cw
print(classify_polygon([Vector(0, 0), Vector(10, 0), Vector(2, 2), Vector(0, 10)])) # PolygonType.not_convex