planarSundial.frink

View or download planarSundial.frink in plain text format


// 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[]


View or download planarSundial.frink in plain text format


This is a program written in the programming language Frink.
For more information, view the Frink Documentation or see More Sample Frink Programs.

Alan Eliasen was born 17596 days, 22 hours, 1 minutes ago.