File: 13-Geometry.md

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (269 lines) | stat: -rw-r--r-- 8,595 bytes parent folder | download | duplicates (2)
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.