Geometry Library
The Storm standard library provides a number of types for 2D and 3D geometry in its standard library. These are provided to make it easier for different graphics libraries to interact with each other, even if parts of them are implemented in C++.
All of these types and functions are in the core.geometry
package. All their members treat the
values as if they were immutable. That is, it is possible to modify the contents of all values
except for Angle
by assigning to their members. All member functions do, however, not modify the
data structure, but instead return an updated copy. This typically makes it easier to chain
operations conveniently without unintended side-effects.
Point
The value core.geometry.Point
stores a 2-dimensional point expressed by 2
core.Float
s named x
and y
. The implementation assumes that points appear in a
coordinate system where positive x
is towards the right, and positive y
is downwards (as is
typical for 2D computer graphics).
The Point
type has the expected arithmetic operations as overloaded operators. Namely, addition,
subtraction, multiplication with a scalar, and division by a scalar. The *
operator for two points
is overloaded as the dot product. It also has the following members:
-
core.geometry.Point tangent()
Tangent. Always 90 deg clockwise from the vector in screen-space.
-
core.Float lengthSq()
Compute the length squared of the point. Cheaper than the length.
-
core.Float length()
Compute the lenght of the point.
-
core.Float taxiLength()
Compute the taxicab/manhattan length (i.e. x + y).
-
core.geometry.Point normalized()
Return a normalized point (i.e. length 1). If the point has length zero, then the original point is returned.
The following free functions are also available:
-
core.geometry.Point abs(core.geometry.Point a)
Compute the absolute value of both compontents in the point.
-
core.geometry.Point project(core.geometry.Point pt, core.geometry.Point origin, core.geometry.Point dir)
Project the point
pt
onto a line that starts inorigin
and expands in the direction ofdir
.dir
does not have to be normalized.
Size
The value core.geometry.Size
stores a 2-dimensional size expressed by 2
core.Float
s named w
and h
(for width and height). Since the Size
class is expected
to represent a size, both of w
and h
are expected to be non-negative.
Overall, the size is convertible to a Point
, and follows the same basic interface. However, due to
the expectation that it contains a size, the interface is smaller. Apart from arithmetic operators,
it has the following members:
-
init()
Create a size of zero.
-
init(core.Float wh)
Create a size with width and height set to the same value.
-
init(core.Float w, core.Float h)
Create a size with separate width and height.
-
init(core.geometry.Point pt)
Create a size from a point.
-
core.Bool valid()
Check if the components are non-negative.
-
core.geometry.Size min(core.geometry.Size o)
Component-wise minimum of two sizes.
-
core.geometry.Size max(core.geometry.Size o)
Component-wise maximum of two sizes.
Apart from the members, the following free functions are available:
-
core.Float max(core.geometry.Size x)
Get the maximum of the two components.
-
core.Float min(core.geometry.Size x)
Get the minimum of the two components.
-
core.geometry.Size abs(core.geometry.Size a)
Normalize a size by taking its absolute value.
-
core.geometry.Point center(core.geometry.Size s)
Center point of a size.
Rect
The value core.geometry.Rect
stores a 2-dimensional rectangle, expressed as two points,
p0
and p1
. The first point p0
is the top-left corner of the rectangle, and p1
is the
bottom-right corner of the rectangle. The member functions of Rect
considers the rectangle to
contain all points from p0
up to, but not including p1
. The class also contains the function
size
that computes the size of the rectangle. The size
function also has an assignment variant,
so it is possible to treat the point as if it cointained a point p0
for the top-left corner, and a
size
instead of two points.
The Rect
type has overloads the +
and -
operators where the right hand side is a Point
to
translate a rectangle based on the coordinates in the point.
The Rect
type has the following parameters:
-
init()
Create an empty rectangle.
-
init(core.geometry.Size s)
Initialize to (0, 0)-(size)
-
init(core.geometry.Point p, core.geometry.Size s)
Initialize to point and size.
-
init(core.geometry.Point topLeft, core.geometry.Point bottomRight)
Initialize to two points.
-
init(core.Float left, core.Float top, core.Float right, core.Float bottom)
Initialize to raw coordinates.
-
core.geometry.Rect normalized()
Return a normalized rectangle, where
p0
is to the top-left ofp1
. -
core.Bool contains(core.geometry.Point pt)
Does this rectangle contain the point
pt
. -
core.Bool contains(core.geometry.Rect rect)
Does this rectangle contain another rectangle? For this to be true, all parts of
rect
needs to be inside this rectangle. -
core.Bool intersects(core.geometry.Rect other)
Does this rectangle intersect with another rectangle?
-
core.geometry.Rect sized(core.geometry.Size to)
Return a rectangle with the same origin, but the specified size.
-
core.geometry.Point center()
Compute the center of the rectangle.
-
core.geometry.Rect at(core.geometry.Point to)
Move the origin of the rectangle to
to
. -
core.geometry.Rect include(core.geometry.Point to)
Increase the rectangle to include the point
to
. Can be seen as a single step in computing a bounding box of a number of points. -
core.geometry.Rect include(core.geometry.Rect other)
Increase the dimensions of the rectangle to include
other
. Can be seen as the union of two bounding boxes. -
core.geometry.Rect scaled(core.Float scale)
Scale the entire rect around its center.
-
core.geometry.Rect shrink(core.geometry.Size rate)
Shrink the rectangle in all dimensions based on the height and width in
rate
. -
core.geometry.Rect grow(core.geometry.Size rate)
Grow the rectangle in all dimensions based on the height and width in
rate
.
The following free functions are also available:
-
core.Bool inside(core.geometry.Point pt, core.geometry.Rect r)
Check if the point
pt
is inside the rectangler
. Same asr.contains(pt)
.
Angle
The value core.geometry.Angle
represents an angle in some unit (internally, radians is
used, but this may change). The value overloads the operators +
and -
for adding and subtracting
angles, and the operators *
and /
for multiplication and division by a scalar. While the Angle
type does not contain any constructors, the functions deg
and rad
are provided instead.
Furthermore, Basic Storm allows creating angles using units, like so:
Angle a = 90 deg; Angle b = 2.3 rad; Float pi = (180 deg).rad();
An Angle
is not limited to contain a value between 0 and 360 degrees. However, storing large angle
values will yield a loss in precision. The member normalized
normalizes the angle to between 0 and
360 degrees.
As mentioned above, the following functions are used to create angles from numbers in degrees or radians:
-
core.geometry.Angle deg(core.Float v)
-
core.geometry.Angle rad(core.Float v)
The Angle
class contains the following members:
-
core.geometry.Angle normalized()
Return a normalized angle that lies between 0 and 360 degrees.
-
core.geometry.Angle opposite()
Return an angle in the opposite direction. Normalizes the result after the computation.
-
core.Float rad()
Convert to radians.
-
core.Float deg()
Convert to degrees.
There are also a number of free functions that utilize angles together with other parts of the geometry package:
-
core.Float sin(core.geometry.Angle v)
Compute the sin of an angle.
-
core.Float cos(core.geometry.Angle v)
Compute the cos of an angle.
-
core.Float tan(core.geometry.Angle v)
Compute the tan of an angle.
-
core.geometry.Angle asin(core.Float v)
Compute asin of a float.
-
core.geometry.Angle acos(core.Float v)
Compute acos of a float.
-
core.geometry.Angle atan(core.Float v)
Compute atan of a float.
-
core.geometry.Angle angle(core.geometry.Point pt)
Compute the angle of the point. Zero degrees is the point (0, -1), i.e. downwards in screen space.
-
core.geometry.Point angle(core.geometry.Angle angle)
Create an angle based on the point. 0 deg is (0, -1)
Vector
The library also provides a type for 3-dimensional coordinates. This type is name
core.geometry.Vector
. As with points, the type provides arithmetic operations for vector
addition, subtraction, and multiplication with scalars. It is also possible to implicitly cast a
Point
into a Vector
in order to make it easier to use transforms for both 2D and 3D coordinates.
The 3-dimensional Vector
uses *
for dot product, and /
for cross product.
Apart from that, the interface is similar to that of Point
, but some operations are missing due to
them having a different meaning in 3 dimensions:
-
core.Float lengthSq()
Compute the length squared of the vector. Cheaper to compute than the length.
-
core.Float length()
Compute the length of the vector.
-
core.Float taxiLength()
Compute the taxicab/manhattan length (i.e. x + y + z).
-
core.geometry.Vector normalized()
Return a normalized vector (i.e. length 1).
Similarly, there are also a few free functions:
-
core.geometry.Vector abs(core.geometry.Vector a)
Compute the absolute value of both compontents in the point.
-
core.geometry.Vector project(core.geometry.Vector pt, core.geometry.Vector origin, core.geometry.Vector dir)
Project the point
pt
onto a line that starts inorigin
and expands in the direction ofdir
.dir
does not have to be normalized.
Transform
The library also contains the core.geometry.Transform
class, which represents a
3-dimensional affine transform using a 4 by 4 matrix. This means that the transform can represent
arbitrary combinations of for example translation, rotation, scaling, skewing, and projections.
A transform interprets points or vectors as four-dimensional row-vectors. The fourth element, w
,
is set to 1 for the purposes of the transform. The row vector is multiplied with the transform
matrix from the left, and the resulting four-dimensional vector is reduced to three dimensions by
dividing the x
, y
, and z
coordinates by w
. As such, when transforms are multiplied together
as a * b * c
, then they will be applied from left to right with respect to the geometry.
The transform
class itself has few members:
-
init()
Unit transform.
-
core.geometry.Transform *(core.geometry.Transform o)
Multiply two transforms, creates a transform that performs both original transforms in sequence.
-
core.geometry.Transform inverted()
Invert the transform.
-
core.Float at(core.Nat row, core.Nat col)
Get a single element.
There are, however, a number of free functions that allow transforming points and vectors:
-
core.geometry.Vector *(core.geometry.Vector o, core.geometry.Transform tfm)
Transform a vector using a transform.
-
core.geometry.Point *(core.geometry.Point o, core.geometry.Transform tfm)
Transform a point using a transform.
There are also a number of functions that create various transforms:
-
core.geometry.Transform translate(core.geometry.Vector v)
Creates a transform that translates points by the coordinate
v
. Also acceptsv
as aPoint
or aSize
. -
core.geometry.Transform rotateX(core.geometry.Angle angle)
Creates a transform that rotates points around the X axis. Also available for the Y axis and the Z axis.
-
core.geometry.Transform rotateX(core.geometry.Angle angle, core.geometry.Vector origin)
Creates a transform that rotates point around a line that extends from the point
origin
and is parallel to the X axis. As with the other rotate function, there are variants for the Y axis and the Z axis as well. -
core.geometry.Transform rotate(core.geometry.Angle angle)
Creates a transform that rotates points around the Z axis. This is the one rotation that is relevant in 2 dimensions, which is why it has a special name.
-
core.geometry.Transform rotate(core.geometry.Angle angle, core.geometry.Point origin)
Creates a transform that rotates points around a line that extends from
origin
that is parallel to the the Z axis. This is the one rotation that is relevant in 2 dimensions, which is why it has a special name. -
core.geometry.Transform scale(core.geometry.Vector scale)
Creates a transform that scales points according to the dimensions in
scale
. Also available in versions that acceptsscale
as aFloat
(affects all axes), and aSize
(affects the X and Y axes). -
core.geometry.Transform skewX(core.geometry.Angle angle)
Creates a transform that skews points along the X axis by
angle
. Also available in versions that skew along the Y axis and the Z axis.