1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
|
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 [stormname:core.geometry.Point] stores a 2-dimensional point expressed by 2
[stormname: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:
```stormdoc
@core.geometry.Point
- .tangent()
- .lengthSq()
- .length()
- .taxiLength()
- .normalized()
```
The following free functions are also available:
```stormdoc
@core.geometry
- .abs(Point)
- .project(Point, Point, Point)
```
Size
----
The value [stormname:core.geometry.Size] stores a 2-dimensional size expressed by 2
[stormname: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:
```stormdoc
@core.geometry.Size
- .__init()
- .__init(Float)
- .__init(Float, Float)
- .__init(Point)
- .valid()
- .min(Size)
- .max(Size)
```
Apart from the members, the following free functions are available:
```stormdoc
@core.geometry
- .max(Size)
- .min(Size)
- .abs(Size)
- .center(Size)
```
Rect
----
The value [stormname: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:
```stormdoc
@core.geometry.Rect
- .__init()
- .__init(Size)
- .__init(Point, Size)
- .__init(Point, Point)
- .__init(Float, Float, Float, Float)
- .normalized()
- .contains(*)
- .intersects(*)
- .sized(*)
- .center()
- .at(*)
- .include(*)
- .scaled(*)
- .shrink(*)
- .grow(*)
```
The following free functions are also available:
```stormdoc
@core.geometry
- .inside(Point, Rect)
```
Angle
-----
The value [stormname: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:
```bsstmt
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:
- [stormname:core.geometry.deg(Float)]
- [stormname:core.geometry.rad(Float)]
The `Angle` class contains the following members:
```stormdoc
@core.geometry.Angle
- .normalized()
- .opposite()
- .rad()
- .deg()
```
There are also a number of free functions that utilize angles together with other parts of the
geometry package:
```stormdoc
@core.geometry
- .sin(Angle)
- .cos(Angle)
- .tan(Angle)
- .asin(Float)
- .acos(Float)
- .atan(Float)
- .angle(Point)
- .angle(Angle)
```
Vector
------
The library also provides a type for 3-dimensional coordinates. This type is name
[stormname: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:
```stormdoc
@core.geometry.Vector
- .lengthSq()
- .length()
- .taxiLength()
- .normalized()
```
Similarly, there are also a few free functions:
```stormdoc
@core.geometry
- .abs(Vector)
- .project(Vector, Vector, Vector)
```
Transform
---------
The library also contains the [stormname: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:
```stormdoc
@core.geometry.Transform
- .__init()
- .*(*)
- .inverted()
- .at(Nat, Nat)
```
There are, however, a number of free functions that allow transforming points and vectors:
```stormdoc
@core.geometry
- .*(Vector, Transform)
- .*(Point, Transform)
```
There are also a number of functions that create various transforms:
- [stormname:core.geometry.translate(core.geometry.Vector)]
Creates a transform that translates points by the coordinate `v`. Also accepts `v` as a `Point` or
a `Size`.
- [stormname:core.geometry.rotateX(core.geometry.Angle)]
Creates a transform that rotates points around the X axis. Also available for the Y axis and the
Z axis.
- [stormname:core.geometry.rotateX(core.geometry.Angle, core.geometry.Vector)]
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.
- [stormname:core.geometry.rotate(core.geometry.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.
- [stormname:core.geometry.rotate(core.geometry.Angle, core.geometry.Point)]
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.
- [stormname:core.geometry.scale(core.geometry.Vector)]
Creates a transform that scales points according to the dimensions in `scale`. Also available in
versions that accepts `scale` as a `Float` (affects all axes), and a `Size` (affects the X and Y
axes).
- [stormname:core.geometry.skewX(core.geometry.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.
|