algebra.result
Alegbraic results for the geometry of sundials and the analemma
dialface_shadowbivector_angle_cos(dialface, shadow_bivector)
cached
Form the cosine of the angle \(\Psi\) between the dial face and shadow plane
The cosine of the angle between \(S\) and \(G\) is given by
Given that \(S^2 = -\sin^2(\Xi)\) and \(G^2 = -1\), we have
$$ \cos(\Psi) = \frac{S\cdot G}{\sin(\Xi)}$$ as implemented by this function
See Normalization
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dialface
|
Mv
|
Unit bivector encoding the face of the sundial see analemma.algebra.frame.dialface) |
required |
shadow_bivector
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
Returns:
| Type | Description |
|---|---|
Expression
|
Cosine of angle \(\Psi\) between dial face and shadow plane |
Source code in src/analemma/algebra/result.py
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 | |
dialface_shadowbivector_intersection(dialface, shadow_bivector)
cached
Form a vector along the intersection of the shadow plane and dial face
Given the dialface \(G\) and shadow_bivector \(S\), this is given by
where \(I = e_1 \wedge e_2 \wedge e_3\) is the pseudo-scalar.
\(u\) has length \(\sin(\Xi)\sin(Psi)\) (see Normalization and dialface_shadowbivector_angle_cos).
See Intersecting the Shadow Plane and Dial Face.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dialface
|
Mv
|
Unit bivector encoding the face of the sundial see analemma.algebra.frame.dialface) |
required |
shadow_bivector
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
Returns:
| Type | Description |
|---|---|
Mv
|
The vector \(u\) along the intersection between the shadow plane and dial face |
Source code in src/analemma/algebra/result.py
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 | |
gnomon_dialface_angle_sin(dial_incl_symbol=i, dial_decl_symbol=d, gnomon_incl_symbol=iota)
The sine of the angle between the gnomon and the dial face
In Rohr's 1996 book SUNDIALS History, Theory and Practice, he refers to the substyle, which is the projection of the style onto the dial face. Here, we allow the gnomon to have an independent inclination \(\iota\) which matches a style when \(\iota = \theta\), the (\(90^\circ\) minus) latitude angle.
We can readily project the gnomon \(g\) onto the dial face \(G\). The vector \(\bar{b} = g\cdot G\) is parallel to \(G\) (ie lies in the dial face) and is rotated with the orientation of \(G\) (anticlockwise as seen from above the dial) by \(\pi/2\) relative to the subgnomon \(b = R \bar{b} \tilde{R}\) where \(R = \exp(\frac{\pi}{4} \, G)\) undoes that \(90^\circ\) rotation (notice the angle in \(R\) is positive in contrast to typical rotations).
Let \(A\) denote the angle between the (unit length) gnomon \(g\) and the subgnomon \(b\) (or equivalently the dial face \(G\)). Then, \(\cos(A) = \sqrt{b^2}\), and \(1-\cos^2(A)\) factorizes nicely to give \(\sin(A)\) as returned by this function.
See also Comparison with Rohr's Book and analemma.tests.test_results.test_gnomon_dialface_angle_pythagoras_identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dial_incl_symbol
|
Symbol
|
The inclination angle of the dial face relative to the surface frame |
i
|
dial_decl_symbol
|
Symbol
|
The declination angle of the dial face relative to the surface frame |
d
|
gnomon_incl_symbol
|
Symbol
|
The inclination angle of the gnomon relative to the surface frame |
iota
|
Returns:
| Type | Description |
|---|---|
Expression
|
\(\sin(A)\), the angle between gnomon and subgnomon (or, equivalently, the dial face) |
Source code in src/analemma/algebra/result.py
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | |
gnomon_shadow_angle_sincos(dial_incl_symbol=i, dial_decl_symbol=d, gnomon_incl_symbol=iota, hour_angle_symbol=mu, dialface_shadowbivector_angle_symbol=Psi)
cached
The sine and cosine of the angle \(\beta\) between the gnomon and the shadow
\(\cos(\beta)\) is readily available via \(g \cdot \hat{w}\) and \(\sin(\beta)\) is related to \(g \wedge \hat{w}\). This function provides explicit forms for these results.
See Angle between Gnomon and Shadow and shadow_triangle_solution
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dial_incl_symbol
|
Symbol
|
The inclination angle of the dial face relative to the surface frame |
i
|
dial_decl_symbol
|
Symbol
|
The declination angle of the dial face relative to the surface frame |
d
|
gnomon_incl_symbol
|
Symbol
|
The inclination angle of the gnomon relative to the surface frame |
iota
|
hour_angle_symbol
|
Symbol
|
The hour angle of the sun |
mu
|
dialface_shadowbivector_angle_symbol
|
Symbol
|
The angle between the dial face and shadow bivector (see dialface_shadowbivector_angle_cos) |
Psi
|
Returns:
| Type | Description |
|---|---|
Tuple[Expression]
|
The 2-tuple |
Source code in src/analemma/algebra/result.py
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | |
hour_angle_sincos(shadow_plane, meridian_plane, zero_decl=True)
Explicit expressions for the sine and cosine of the hour angle \(\mu\)
The hour angle is measured between the meridian plane and the shadow plane (containing sun ray and gnomon). It is given by
given that \(M^2 = -1\). \(\sin(\mu) = \sqrt{1-\cos^2(\mu)}\) can be factorized when the gnomon declination \(\delta = 0\).
See The Hour Angle
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shadow_plane
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
meridian_plane
|
Mv
|
The bivector \(M = n_1\wedge n_3\) (see analemma.algebra.frame.meridian_plane) |
required |
zero_decl
|
bool
|
Flag controlling assumption of zero gnomon declination. If False, None is returned for \(\sin(\mu)\) |
True
|
Returns:
| Type | Description |
|---|---|
Tuple[Expression]
|
A 2-tuple of explicit expressions for |
Source code in src/analemma/algebra/result.py
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 | |
hour_angle_tan(shadow_plane, meridian_plane, zero_decl=True)
cached
Explicit expression for the tangent of the hour angle \(\mu\)
The hour angle is measured between the meridian plane and the shadow plane (containing sun ray and gnomon).
\(\tan(\mu)\) is formed as the ratio of \(\sin(\Xi)\sin(\mu)\) and \(\sin(\Xi)\cos(\mu)\) as returned by hour_angle_sincos in which the shadow plane magnitude factor of \(\sin(\Xi)\) cancels.
See The Hour Angle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shadow_plane
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
meridian_plane
|
Mv
|
The bivector \(M = n_1\wedge n_3\) (see analemma.algebra.frame.meridian_plane) |
required |
zero_decl
|
bool
|
Flag controlling assumption of zero gnomon declination. Currently, supplying False reuslts in an error |
True
|
Returns:
| Type | Description |
|---|---|
Expression
|
An explicit expression for \(\tan(\mu)\) |
Source code in src/analemma/algebra/result.py
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 | |
noon_angle_sincos(dialface, shadow_bivector)
cached
The sine and cosine of the angle \(\zeta\) between the shadow at an arbitrary time and the shadow at noon
\(\cos(\zeta)\) is calculated as \(\hat{w}(\mu) \cdot \hat{w}(0)\) where \(\hat{w}(\mu)\) is the unit shadow at an arbitrary time, or equivalently hour angle, and \(\hat{w}(0)\) is the unit shadow at noon, when \(\mu = 0\).
Instead of attempting to factorize \(\sqrt{1-\cos^2(\zeta)}\), we can use the fact that the shadow lives in the plane of the dial face, so \(\hat{w}(\mu) \wedge \hat{w}(0) = \sin(\zeta) G\), and \(G^2 = -1\).
See The Shadow Angle Relative to Noon
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dialface
|
Mv
|
Unit bivector encoding the face of the sundial see analemma.algebra.frame.dialface) |
required |
shadow_bivector
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
Returns:
| Type | Description |
|---|---|
Tuple[Mv]
|
The 2-tuple |
Source code in src/analemma/algebra/result.py
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | |
noon_angle_tan(dialface, shadow_bivector)
cached
The tangent of the angle \(\zeta\) between the shadow at an arbitrary time and the shadow at noon
Formed as the ratio of \(\sin(\zeta)\) and \(\cos(\zeta)\) as returned by noon_angle_sincos
See The Shadow Angle Relative to Noon
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dialface
|
Mv
|
Unit bivector encoding the face of the sundial see analemma.algebra.frame.dialface) |
required |
shadow_bivector
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
Returns:
| Type | Description |
|---|---|
Mv
|
$\tan(\zeta), where \(\zeta\) is the noon shadow angle |
Source code in src/analemma/algebra/result.py
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | |
shadow_bivector(sunray=frame.sunray(), gnomon=frame.gnomon('e'))
Form the bivector encoding the plane containing the sun ray, the gnomon, and (therefore) the shadow
Given the sunray \(s\) and gnomon \(g\), form \(S = s\wedge g\).
See also Setup and Definitions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sunray
|
Mv
|
The vector encoding the sun ray |
sunray()
|
gnomon
|
Mv
|
The vector encoding the gnomon |
gnomon('e')
|
Returns:
| Type | Description |
|---|---|
Mv
|
The shadow bivector \(S\) |
Source code in src/analemma/algebra/result.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
shadow_bivector_explicit(hour_angle_symbol=mu, shadow_plane_magnitude_symbol=Xi, gnomon_incl_symbol=iota)
An explicit expression for the bivector encoding the plane containing the sun ray, the gnomon, and (therefore) the shadow
See The Shadow Plane.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hour_angle_symbol
|
Symbol
|
The hour angle, \(\mu\) |
mu
|
shadow_plane_magnitude_symbol
|
Symbol
|
The magnitude of the shadow bivector (see angle between sun ray and gnomon) |
Xi
|
gnomon_incl_symbol
|
Symbol
|
The gnomon inclination, \(\iota\) |
iota
|
Returns:
| Type | Description |
|---|---|
Mv
|
An explicit expression for the shadow bivector \(S\) under the assumption of zero gnomon declination (\(\delta=0\)) |
Source code in src/analemma/algebra/result.py
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 | |
shadow_bivector_magnitude_angle_cos(sunray, gnomon)
Cosine of the angle between sun ray and gnomon, \(\cos(\Xi)\)
Given the sunray \(s\) and gnomon \(g\), form \(\cos(\Xi) = s\cdot g\). Note also that the magnitude of the shadow
bivector \(S\) is \(\sin(\Xi)\) because \(S^2 = -\sin^2(\Xi)\).
See The Shadow Plane and Normalization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sunray
|
Mv
|
The vector encoding the sun ray |
required |
gnomon
|
Mv
|
The vector encoding the gnomon |
required |
Returns:
| Type | Description |
|---|---|
Expression
|
\(s\cdot g = \cos(\Xi)\) |
Source code in src/analemma/algebra/result.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
shadow_coords_xy(dial_incl_symbol=i, dial_decl_symbol=d, gnomon_incl_symbol=iota, hour_angle_symbol=mu, shadow_plane_magnitude_symbol=Xi)
The Cartesian coordinates of the analemma on the face of a sundial
Given the shadow vector \(w = L\hat{w}\) (constructed by scaling the unit shadow by its length), the coordinates of the tip of the shadow on the dial face can be found via
\(x = m_1 \cdot w\)
\(y = m_2 \cdot w\)
where \(m_1\) and \(m_2\) are the first two vectors in the dial frame.
\(z = 0\) because the shadow is parallel to the face of the dial by definition.
This function provides \(x\) and \(y\) in closed form.
See The Analemma
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dial_incl_symbol
|
Symbol
|
The inclination angle of the dial face relative to the surface frame |
i
|
dial_decl_symbol
|
Symbol
|
The declination angle of the dial face relative to the surface frame |
d
|
gnomon_incl_symbol
|
Symbol
|
The inclination angle of the gnomon relative to the surface frame |
iota
|
hour_angle_symbol
|
Symbol
|
The hour angle of the sun |
mu
|
shadow_plane_magnitude_symbol
|
Symbol
|
The angle between the sun ray and gnomon in the shadow bivector |
Xi
|
Returns:
| Type | Description |
|---|---|
Tuple[Expression]
|
2-tuple of |
Source code in src/analemma/algebra/result.py
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | |
shadow_coords_xy_explicit()
Explicit expressions for the Cartesian coordinates of the analemma in terms of fundamental angles
shadow_coords_xy expresses the analemma in terms of a mixture of the angles found in and the following derived quantities:
- \(\mu\), the hour angle
- \(\Xi\), the shadow bivector magnitude angle
- \(D\), the denominator of \(\lambda\), the solution to the shadow triangle problem
This function eliminates these quantities in the expressions for \(x\) and \(y\), the coordinates of the analemma, leaving only the fundamental angles that determine the location, orientation and geometry of the sundial as a function of date and time.
See The Analemma
Returns:
| Type | Description |
|---|---|
Tuple[Expression]
|
2-tuple of |
Source code in src/analemma/algebra/result.py
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | |
shadow_length(denom_symbol=D, shadow_plane_magnitude_symbol=Xi, dialface_shadowbivector_angle_symbol=Psi)
An expression for \(L\), the length of the shadow
\(N\), the numerator of \(\lambda\) in the solution to the shadow triangle is equal to \(\sin(\beta)\), which given the form of \(\sin(\beta)\) from gnomon_shadow_angle_sincos means that
and so, given the form of \(L\) given in Solving the Shadow Triangle, we have
See also The Shadow Vector
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
denom_symbol
|
Symbol
|
The denominator \(D\) of the shadow triangle solution \(\lambda = \frac{N}{D}\) |
D
|
shadow_plane_magnitude_symbol
|
Symbol
|
The magnitude angle of the shadow bivector (see angle between sun ray and gnomon) |
Xi
|
dialface_shadowbivector_angle_symbol
|
Symbol
|
The angle between the dial face and shadow bivector (see dialface_shadowbivector_angle_cos) |
Psi
|
Returns:
| Type | Description |
|---|---|
Expression
|
\(L = \sin(\Xi)\sin(\Psi)/D\) |
Source code in src/analemma/algebra/result.py
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | |
shadow_triangle_solution(latitude_symbol=theta, dial_incl_symbol=i, dial_decl_symbol=d, gnomon_incl_symbol=iota, hour_angle_symbol=mu_s, shadow_plane_magnitude_symbol=Xi_s)
cached
The scale factor \(\lambda\) on the unit sun ray \(s\) that solves the shadow triangle
Given the triangle \(w(\lambda) = g + \lambda s\) where \(g\) is the gnomon and \(s\) is the sun ray, enforce that \(w(\lambda)\) lies in the dial face by solving \(w(\lambda) \wedge G = 0\) for \(\lambda\). The resulting solution is given by this function.
See Solving the Shadow Triangle
.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
latitude_symbol
|
Symbol
|
\(90^\circ\) minus the latitude at which the frame is embedded |
theta
|
dial_incl_symbol
|
Symbol
|
The inclination angle of the dial face relative to the surface frame |
i
|
dial_decl_symbol
|
Symbol
|
The declination angle of the dial face relative to the surface frame |
d
|
gnomon_incl_symbol
|
Symbol
|
The inclination angle of the gnomon relative to the surface frame |
iota
|
hour_angle_symbol
|
Symbol
|
The hour angle of the sun |
mu_s
|
shadow_plane_magnitude_symbol
|
Symbol
|
The angle between the sun ray and gnomon in the shadow bivector |
Xi_s
|
Returns:
| Type | Description |
|---|---|
Expression
|
An expression for \(\lambda\) that ensures that \(w(\lambda) = g + \lambda s\) is the shadow cast by the gnomon on the dial face |
Source code in src/analemma/algebra/result.py
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | |
sunray_dialface_angle_sin()
The sine of the angle \(\gamma\) between the sun ray and the dial face
It can be important (when plotting analemmas for example) to determine an effective sunrise and sunset for a given sundial, defined as the points in the sun's journey across the sky when the angle between the sun ray \(s\) and the dial face \(G\) is zero (or \(\pi\)). This angle is given by
\(\sin(\gamma) = -(G \wedge s) \cdot I\)
where \(I = e_1 \wedge e_2 \wedge e_3\).
This function returns an explicit expression for \(\sin(\gamma)\) in terms of fundamental angles.
Source code in src/analemma/algebra/result.py
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | |
unit_noon_shadow(dialface, shadow_bivector)
cached
Evalute the unit shadow vector at noon
Noon occurs when the hour angle \(\mu\) is zero, which is when the shadow plane is parallel to the meridian plane.
See The Shadow Angle Relative to Noon
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dialface
|
Mv
|
Unit bivector encoding the face of the sundial see analemma.algebra.frame.dialface) |
required |
shadow_bivector
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
Returns:
| Type | Description |
|---|---|
Mv
|
The unit shadow vector at noon when \(\mu = 0\) |
Source code in src/analemma/algebra/result.py
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | |
unit_shadow(dialface, shadow_bivector)
cached
Form \(\hat{w}\), a unit vector parallel to the shadow
The Normalization section of the shadow angle notebook shows that the length of \(u\), the vector formed as the intersection of the shadow plane and dial face is \(\sin(\Xi)\sin(\psi)\). Here, we divide \(u\) by its length to form a unit vector parallel to the shadow:
See Normalization
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dialface
|
Mv
|
Unit bivector encoding the face of the sundial see analemma.algebra.frame.dialface) |
required |
shadow_bivector
|
Mv
|
The bivector \(S = s\wedge g\) for sun ray \(s\) and gnomon \(g\) |
required |
Returns:
| Type | Description |
|---|---|
Mv
|
Unit vector parallel to the shadow, \(\hat{w}\). |
Source code in src/analemma/algebra/result.py
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | |