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 18015 days, 21 hours, 38 minutes ago.