Dear Gnomonists
Recently, there has been a small correspondence about Spider Dials. This
message mainly concerns those who like to do all their gnomonic calculations
programatically.
I attach a short text file that contains the routines needed to prepare spider
curves for a horizontal dial with a gnomon of given thickness. Computer
routines are usually language and implementation specific (as these are), but
the logic and gnomonics provided are correct (or so I hope and pray). The
language is Python, which is easily read and quite easily adaptable to any
other language (e.g. Java).
For me, the advantage of using a programical approach is that I use the same
program to prepare graphics files that can be sent to...
i) a laser engraver to make a cheap plywood maquette of my design to check
things out
ii) a water jet cutting company to cut out the dial plate and gnomon
iii) a photo-etching company to create the dial.
I am current working on the routines to generate G-Code that can go direct to a
CNC routing engraver. I would love to hear from anyone working on a similar
approach.
Best wishes
Kevin
p.s anyone who wants the astronomical routines mentioned in the text file have
only to ask!
# Here are two routines that I use to draw Spider Hour lines on horizontal
dials.
# They are written in Python, which is easy to read and can be adapted to
# any other language quite simply
# Items such as Latitude, Time Zone etc are prefixed by My_ . These are global
variables
# The coordinate sysyem is x-axis East/West, y-axis North/South downwards
def Get_Point(Year,Month,Day,Hour,Minute,Second,The_radius):
# This routine is for a horizontal dial with a gnomon of given
thickness
# It returns an x-y coordinate of the intersection of...
# a gnomon's shadow line
# a circle centred in the middle of the dial
# Inputs are the Date and CIVIL Time and the radius of the circle
# The routine calls Sunpos - a general purpose astronomical support
routine
# based on the rigorous algorithms of Meeus' "Astronomical Algorithms",
# which provides (amongst other things) the Sun's True Hour Angle.
# (the routines use temperature, pressure and height - far beyond the
accuracy
# requirements of this application, but computers calculate quickly
these days....)
Result = Sunpos(My_Latitude_deg, My_Longitude_deg,
My_Time_Zone,My_DST,
Year, Month, Day, Hour, Minute, Second,
My_Temp,My_Press,My_Height)
#=========================================================================
# Sunpos returns...
# 0 RA_hrs
# 1 Decl_deg
# 2 Radius_Vector_AU
# 3 EoT_Gnomon_Min
# 4 GMST_hrs
# 5 Alt_deg
# 6 Azim_deg
# 7 LHA_deg
# 8 Sunrise_hrs
# 9 Sunset_hrs
# unpack the variable of the Result that I need
HA_deg = Result[7]
HA_rad = radians(abs(HA_deg))
# Calculate the Hour Line Angle
HLA_rad = atan(tan(HA_rad) * sin(radians(abs(My_Latitude_deg))))
if (HA_deg > 90 or HA_deg < -90) : HLA_rad = HLA_rad + pi
HLA_deg = degrees(HLA_rad)
# My_Noon_Gap is the thickness of the gnomon, HNG = Half Noon Gap
HNG = My_Noon_Gap/2. if (HLA_deg < -90 or HLA_deg > 90) else
-My_Noon_Gap/2.
# Signer picks the correct of the two intersection points between line
and circle
Signer = 1 if HLA_deg < 90 else -1
# this part just does the coordinate geometry to find the intersection
of line with circle
tanGamma = tan(HLA_rad)
dd = My_Style_Foot_Posn * tanGamma - HNG
aaa = 1 + tanGamma**2
bbb = 2 * dd * tanGamma
ccc = dd * dd - The_radius ** 2
y1 = (-bbb + Signer * sqrt(bbb**2 - 4 * aaa * ccc)) / (2 * aaa)
x1 = sqrt(The_radius**2 - y1**2)
# Switch sets the x-coordinate depend whether morning or afternoon
Switch = 1 if HA_deg > 0 else (-1 if HA_deg < 0 else 0)
if HA_deg <> 0. :
xxx = Switch * x1
yyy = - y1 # graphics system has +ve y down the screen
else: # deals with Noon
xxx = HNG
yyy = -sqrt(The_radius**2 - HNG**2)
return (xxx,yyy)
def Do_Spiders():
# The routine calls two general purpose routines....
# Julian_Day - which gives to the Julian Day Number for a given
Year/MonthDay
# Get_Date_Time_from_JD - which Year/Month/Day from a given Julian Date
# The Loop to draw ALL of the Spider Lines
# The_Civil_Mins is the time on your watch
The_Civil_Mins = int(60 * My_Start_Hour) # an integer
The_End_Minutes= int(60 * My_End_Hour) # an integer
The_Start_Day = Julian_Day(My_Year,1,1)
The_End_Day = Julian_Day(My_Year,12,31)
while The_Civil_Mins <= The_End_Minutes :
# The Loop through each day of the year to generate ONE Spider
Line
The_Day = The_Start_Day
Start_line = True # a new graphic line will have to be initiated
while The_Day <= The_End_Day :
# this cumbersome bit of code is because nu
astronomical routine
# uses the date in years/month/days and civil
hours/mins/seconds as input
xyz = Get_Date_Time_from_JD(The_Day)
YYYY = xyz[0]
MMMM = xyz[1]
DDDD = xyz[2]
HHHH = The_Civil_Mins/60 # n.b. integer
arithmetic
mmmm = The_Civil_Mins - HHHH * 60 # n.b. integer
arithmetic
SSSS = 0
# get the radus appropriate for the date
Radius = My_Inner_Radius + float(The_Day)/366.*
(My_Outer_Radius - My_Inner_Radius)
# Call the routine to get the next point along the
Spider Line
pqr = Get_Point(YYYY,MMMM,DDDD,HHHH,mmmm,SSSS,Radius)
# Unpack the retuned variables
x = pqr[0]
y = pqr[1]
# the actual creation of the Spider Line is probably
specific to your
# graphics or plotting package,
# but will probably contain something like this...
if Start_line: # initiate a new graphic path
beginpath(x,y)
Start_line = False
else:
lineto(x,y) # continue existing graphic path
# increment the day
The_Day += 1
# The year is done, close the graphic path, but do not draw it
yet
abc = endpath(draw=False)
# what follows is specific to the equipment you might be using
Line_Type = 0 # 10 minute line
if The_Civil_Mins % 30 == 0 : Line_Type = 1 # half-hour line
if The_Civil_Mins % 60 == 0 : Line_Type = 2 # hour line
if To_Laser_Engraver :
# constant line thickness, variable colour to engrave
different depths
Line_Thickness = .001
if Line_Type == 0 : Line_Colour = Cyan
if Line_Type == 1 : Line_Colour = Blue
if Line_Type == 2 : Line_Colour = Magenta
else : # to photo etching
# constant colour, variable line thickness to etch more
depth
Line_Colour = Black
if Line_Type == 0 : Line_Thickness = 1
if Line_Type == 1 : Line_Thickness = 2
if Line_Type == 2 : Line_Thickness = 2.5
# NOW DRAW THE GRAPHIC PATH
drawpath(abc, fill=None, stroke=
Line_Colour,strokewidth=Line_Thickness)
# Increment the minutes to draw the next spider line
The_Mins += 10
---------------------------------------------------
https://lists.uni-koeln.de/mailman/listinfo/sundial