// 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]] // println["sunset is " + format[sunset, "deg", 3]] 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] // println["H is " + format[H, "deg", 2] + " time is $time "] g.font["SansSerif", a/15] g.text["$time:00", x, -y, "right", "top"] } } } /* 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] // Latitude on the Earth where the sundial will be placed. lat = 40 deg // Alignment of the face of the sundial with respect to the compass align = (180-22) deg // 180 deg = due south, 90 deg = due east stylusLength = 3 // Alignment of the plane of the sundial z = 0.1 deg // 0 deg = horizontal sundial (on floor) // 90 deg = vertical sundial (on wall) // Convert compass alignment to Meeus coordinates. To convert to/from // compass coordinates, use (align + 180 deg) mod circle alignMeeus = (align + 180 deg) mod circle g = new graphics drawHourAngles[g, lat, alignMeeus, 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[]