// This allows the construction of a planar sundial of any given orientation // and inclination. // // It also draws a scaled horizontal line indicating the size of the gnomon. // // See Jean Meeus, Astronomical Algorithms, Chapter 58 for description. calculatePoint[lat, D, a, z, H, delta] := { P = calcP[lat, D, a, z] Q = sin[D] sin[z] sin[H] + (cos[lat] cos[z] + sin[lat] sin[z] cos[D]) cos[H] + P tan[delta] Nx = cos[D] sin[H] - sin[D] (sin[lat] cos[H] - cos[lat] tan[delta]) Ny = cos[z] sin[D] sin[H] - (cos[lat] sin[z] - sin[lat] cos[z] cos[D]) cos[H] - (sin[lat] sin[z] + cos[lat] cos[z] cos[D]) tan[delta] x = a Nx / Q y = a Ny / Q return [x,y,Q] } drawHourAngles[g is graphics, lat, D, a, z] := { deltas = [-23.44 deg, -20.15 deg, -11.47 deg, 0 deg, 11.47 deg, 20.15 deg , 23.44 deg] Hs = new range[-45 deg, 46 deg, 15 deg] for H = Hs { p = new polyline pointFound = false for delta = deltas { sunset = arccos[-tan[lat] tan[delta]] if (H < sunset) and (H > -sunset) { [x,y,Q] = calculatePoint[lat, D, a, z, H, delta] if Q > 0 // Plane illuminated? { pointFound = true p.addPoint[x,-y] } } } if pointFound { g.add[p] [x,y] = calculatePoint[lat, D, a, z, H, 23.55 deg] time = round[(H/(15 degrees) * hour + 12 hours)/hour, 1] g.font["SansSerif", a/15] g.text["\$time:00", x, -y] } } } /* Calculate the "center" point of the sundial. This is not where the gnomon is placed, but where the lines for each hour angle converge. */ findCenter[lat, D, a, z] := { P = calcP[lat, D, a, z] x0 = a / P cos[lat] sin[D] y0 = -a / P (sin[lat] sin[z] + cos[lat] cos[z] cos[D]) return [x0, y0] } calcP[lat, D, a, z] := sin[lat] cos[z] - cos[lat] sin[z] cos[D] g = new graphics lat = 40 deg // Alignment of wall it's mounted on. align = 0 deg // 0 deg = due south, 270 deg = due east stylusLength = 3 z = 90 deg // 0 deg = horizontal sundial 90 deg = vertical sundial drawHourAngles[g, lat, align, stylusLength, z] g.drawEllipseCenter[0,0,stylusLength/100, stylusLength/100] // Draw the gnomon g.line[-stylusLength/2, -stylusLength/10, stylusLength/2, -stylusLength/10] g.show[]