Added Sundial Declining from https://inkscape.org/de/~TomasUrban/%E2%98%85sundial-declining
This commit is contained in:
parent
df2a34940d
commit
e065f92907
46
extensions/fablabchemnitz_sundial_declining.inx
Normal file
46
extensions/fablabchemnitz_sundial_declining.inx
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<_name>Sundial Declining</_name>
|
||||
<id>fablabchemnitz.de.sundialdeclining</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="input" appearance="minimal" _gui-text="Options">
|
||||
<param name="desc1" type="description" appearance="header">Location coordinates</param>
|
||||
<param name="latitude" type="float" min="10" max="70" precision="3" _gui-text="Latitude: ">50</param>
|
||||
<param name="longitude" type="float" min="-180" max="180" precision="3" _gui-text="Longitude: ">16</param>
|
||||
<param name="timezone" type="int" min="-12" max="12" precision="0" _gui-text="Time zone: ">0</param>
|
||||
<param name="summer_time" type="boolean" gui-text="Summer time:">false</param>
|
||||
</page>
|
||||
<page name="input_2" appearance="minimal" _gui-text="Add">
|
||||
<param name="note1" type="description" appearance="header">Add 1</param>
|
||||
<param name="gnom" type="float" min="10" max="50" precision="1" _gui-text="Length of the gnomon: ">40</param>
|
||||
<param name="decl" type="float" min="-90" max="90" precision="1" _gui-text="Azimuth wall: ">40</param>
|
||||
<_param name="instructions" type="description" xml:space="preserve"> ( + West; - East)</_param>
|
||||
<param name="incl" type="float" min="-45" max="45" precision="1" _gui-text="Slope of the wall: ">0</param>
|
||||
<_param name="instructions" type="description" xml:space="preserve"> ( + x; - x)</_param>
|
||||
</page>
|
||||
<page name="input_3" appearance="minimal" _gui-text="Draw">
|
||||
<param name="note2" type="description" appearance="header">Add 2</param>
|
||||
<param name="DL" type="enum" _gui-text="Number of data lines:">
|
||||
<item value="0">0</item>
|
||||
<item value="3">3</item>
|
||||
<item value="7">7</item>
|
||||
</param>
|
||||
</page>
|
||||
</param>
|
||||
<param name="instructions" type="description" xml:space="preserve">
|
||||
* Latitude from +10 to +70
|
||||
* Longitude (+ to E) from -180 to 180
|
||||
* Time Zone (+ to E) from -12 to 12
|
||||
</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu _name="FabLab Chemnitz">
|
||||
<submenu _name="Shape/Pattern from Generator" />
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command reldir="extensions" interpreter="python">fablabchemnitz_sundial_declining.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
328
extensions/fablabchemnitz_sundial_declining.py
Normal file
328
extensions/fablabchemnitz_sundial_declining.py
Normal file
@ -0,0 +1,328 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
#http://astrodinamica.altervista.org/ESU/sundial/Condensed-vector-theory.pdf
|
||||
#https://www.helios-sonnenuhren.de/sites/default/files/upload/the_calculation_of_declining_and_inclining_sundials_an_unusual_approach.pdf
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
from __future__ import division
|
||||
import inkex
|
||||
from datetime import datetime, time, timedelta
|
||||
from math import *
|
||||
from lxml import etree
|
||||
|
||||
class SunDial(inkex.Effect):
|
||||
def __init__(self):
|
||||
inkex.Effect.__init__(self)
|
||||
self.arg_parser.add_argument("--latitude", type=float, dest="latitude", default="50.3515")
|
||||
self.arg_parser.add_argument("--longitude", type=float, dest="longitude", default="15.7512")
|
||||
self.arg_parser.add_argument("--timezone", type=int, dest="timezone", default="0")
|
||||
self.arg_parser.add_argument("--summer_time", type=inkex.Boolean, dest="summer_time", default='False')
|
||||
self.arg_parser.add_argument("--gnom", type=float, dest="gnom", default="30")
|
||||
self.arg_parser.add_argument("--decl", type=float, dest="decl", default="0")
|
||||
self.arg_parser.add_argument("--incl", type=float, dest="incl", default="0")
|
||||
self.arg_parser.add_argument("--DL", type=float, dest="DL", default="0")
|
||||
self.arg_parser.add_argument("--tab")
|
||||
|
||||
def effect(self):
|
||||
def draw_SVG_line(x1, y1, x2, y2, width, stroke, name, parent):
|
||||
style = { 'stroke': stroke, 'stroke-width':str(width), 'fill': 'none' }
|
||||
line_attribs = {'style':str(inkex.Style(style)),
|
||||
inkex.addNS('label','inkscape'):name,
|
||||
'd':'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)}
|
||||
etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs )
|
||||
|
||||
def draw_SVG_circle(cx, cy, r, width, stroke, fill, name, parent):
|
||||
style = { 'stroke': stroke, 'stroke-width':str(width), 'fill':fill}
|
||||
circle_attribs = {'style':str(inkex.Style(style)),
|
||||
inkex.addNS('label','inkscape'):name,
|
||||
'cx':str(cx), 'cy':str(cy), 'r':str(r)}
|
||||
etree.SubElement(parent, inkex.addNS('circle','svg'), circle_attribs )
|
||||
|
||||
def draw_SVG_tri(x1, y1, x2, y2, x3, y3, width, stroke, name, parent):
|
||||
style = { 'stroke': stroke, 'stroke-width':str(width), 'fill': 'none' }
|
||||
tri_attribs = {'style':str(inkex.Style(style)),
|
||||
inkex.addNS('label','inkscape'):name,
|
||||
'd':'M '+str(x1)+','+str(y1)+
|
||||
' L '+str(x2)+','+str(y2)+
|
||||
' L '+str(x3)+','+str(y3)+
|
||||
' L '+str(x1)+','+str(y1)+' z'}
|
||||
etree.SubElement(parent, inkex.addNS('path','svg'), tri_attribs )
|
||||
|
||||
def draw_SVG_rect(x, y, w, h, width, fill, name, parent):
|
||||
style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill':fill}
|
||||
rect_attribs = {'style':str(inkex.Style(style)),
|
||||
inkex.addNS('label','inkscape'):name,
|
||||
'x':str(x), 'y':str(y), 'width':str(w), 'height':str(h)}
|
||||
etree.SubElement(parent, inkex.addNS('rect','svg'), rect_attribs )
|
||||
|
||||
def draw_SVG_polyline(DP, width, colour, fill, name, parent):
|
||||
style = { 'stroke': colour, 'stroke-width': str(width), 'fill':fill}
|
||||
polyline_attribs = {'style':str(inkex.Style(style)),
|
||||
inkex.addNS('label','inkscape'):name,
|
||||
'd':'M' +str(DP)}
|
||||
etree.SubElement(parent, inkex.addNS('path','svg'), polyline_attribs )
|
||||
|
||||
def draw_SVG_text(x, y, textvalue, font, text_size, parent):
|
||||
text = etree.Element(inkex.addNS('text','svg'))
|
||||
text.set('x', str(x))
|
||||
text.set('y', str(y))
|
||||
style = {'text-align' : 'center', 'font-family': str(font) ,'text-anchor': 'middle', 'alignment-baseline' : 'center', 'font-size' : str(text_size), 'vertical-align' : 'middle'}
|
||||
text.set('style', str(inkex.Style(style)))
|
||||
text.text = textvalue
|
||||
parent.append(text)
|
||||
|
||||
so = self.options
|
||||
parent = self.svg.get_current_layer()
|
||||
|
||||
border=5
|
||||
widthgrid = 200
|
||||
heightgrid = 150
|
||||
|
||||
# Grid
|
||||
Gx=15
|
||||
Gy=9
|
||||
|
||||
# Get SVG document dimensions
|
||||
svg = self.document.getroot()
|
||||
width = self.svg.unittouu(svg.get('width'))
|
||||
height = self.svg.unittouu(svg.attrib['height'])
|
||||
|
||||
# Embed grid in group
|
||||
#Put in in the centre of the current view
|
||||
#t = 'translate(' + str( self.view_center[0]- width/2.0) + ',' + str( self.view_center[1]- height/2.0) + ')'
|
||||
#t = 'translate(0,' + str(height) + ') rotate(-180,0,0)'
|
||||
t = 'translate(' + str(width/2) + ',' + str(border) + ')'
|
||||
#t = 'translate(0 ,0)'
|
||||
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'SunDial_Lat:' + str( so.latitude )+';Long:'+str( so.longitude ),'transform':t}
|
||||
grid = etree.SubElement(self.svg.get_current_layer(), 'g', g_attribs)
|
||||
|
||||
#Group for x gridlines
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'XGridlines'}
|
||||
glx = etree.SubElement(grid, 'g', g_attribs)
|
||||
|
||||
#Group for y gridlines
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'YGridlines'}
|
||||
gly = etree.SubElement(grid, 'g', g_attribs)
|
||||
|
||||
#Group for Hour lines vertical SunDial
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'VerticalHourLines'}
|
||||
vhl = etree.SubElement(grid, 'g', g_attribs)
|
||||
|
||||
#Group for Nodus vertical SunDial
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'Nodus'}
|
||||
nod = etree.SubElement(grid, 'g', g_attribs)
|
||||
|
||||
#Group for zodiac line
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'Line of zodiac'}
|
||||
loz = etree.SubElement(grid, 'g', g_attribs)
|
||||
|
||||
# ----------Grid and border------------------------------------------------------------------
|
||||
# Border
|
||||
draw_SVG_rect(-width/2+border, -0, width-2*border, heightgrid, 0.8, 'none', 'Border', grid) #border rectangle
|
||||
|
||||
# XGridLine
|
||||
for i in range(Gx): #x divisons
|
||||
distX=widthgrid/(Gx-1)
|
||||
draw_SVG_line(distX*i-width/2+border, heightgrid, distX*i-width/2+border, 0, 0.1, '#0000FF', 'X'+str(i), glx)
|
||||
|
||||
# YGridLine
|
||||
for i in range(Gy): #y divisons
|
||||
distY=heightgrid/(Gy-1)
|
||||
draw_SVG_line(-width/2+border, distY*i, width/2-border, distY*i, 0.1, '#0000FF', 'Y'+str(i), gly)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
Time = [4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
|
||||
T = {} #
|
||||
T_rad = {} #
|
||||
|
||||
# Line of zodiac
|
||||
if so.DL == 0:
|
||||
D = []
|
||||
if so.DL == 3:
|
||||
D = [-23.44, 0.0001, 23.44]
|
||||
if so.DL == 7:
|
||||
D = [-23.44, -20.15, -11.47, 0.0001, 11.47, 20.15, 23.44] #https://www.mysundial.ca/tsp/the_zodiac.html
|
||||
|
||||
D_rad = {}
|
||||
|
||||
W = so.decl*pi/180 # Declination of wall in radian https://www.mysundial.ca/tsp/vertical_declining_sundial.html
|
||||
R = so.incl*pi/180 # Inclination of wall in radian
|
||||
L = so.latitude*pi/180 # Latitude in radian
|
||||
|
||||
#Text
|
||||
textvalue='Sundials for Latitude: %s; Wall azimuth: %s; Wall inclination: %s --- (c)2019 Tomas Urban ' % (so.latitude, round(W*180/pi,2), round(R*180/pi,2))
|
||||
draw_SVG_text(0, heightgrid+4, textvalue, 'san-serif', 4, gly)
|
||||
|
||||
# ----------Gnomon ----------------------------------------------------------------------------
|
||||
Xf =-so.gnom*(sin(W)*cos(L))/(cos(R)*cos(W)*cos(L)-sin(R)*sin(L))
|
||||
Zf = so.gnom*((sin(R)*cos(W)*cos(L))+(cos(R)*sin(L)))/(cos(R)*cos(W)*cos(L)-sin(R)*sin(L))
|
||||
g = asin(cos(R)*cos(W)*cos(L)-sin(R)*sin(L))
|
||||
f = atan(-sin(W)*cos(L)/(sin(R)*cos(W)*cos(L)+cos(R)*sin(L)))
|
||||
P = -so.gnom/(cos(R)*cos(W)*cos(L)-sin(R)*sin(L))
|
||||
|
||||
#Text
|
||||
#textvalue='Xf: %s; Zf: %s; g: %s; P: %s; f: %s' % (round(Xf,2), round(Zf,2), round(g*180/pi,2), round(P,2), round(f*180/pi,2))
|
||||
#draw_SVG_text(0, 120, textvalue, 'san-serif', 4, gly)
|
||||
#textvalue='G*cos(f): %s; G*sin(f): %s; g: %s; P: %s; f: %s' % (round(so.gnom*cos(f),2), round(so.gnom*sin(f),2), round(so.gnom*180/pi,2), round(P,2), round(f*180/pi,2))
|
||||
#draw_SVG_text(0, 125, textvalue, 'san-serif', 4, gly)
|
||||
|
||||
# Horizont line
|
||||
draw_SVG_line(-width/2+border, Zf, width/2-border, Zf, 0.5, '#000000', 'Horizont line', nod)
|
||||
|
||||
# Nodus
|
||||
a = (0,0)
|
||||
b = (-Xf, Zf)
|
||||
c = (-Xf+so.gnom*cos(f),Zf+so.gnom*sin(f))
|
||||
draw_SVG_tri(a[0], a[1], b[0], b[1], c[0], c[1], 0.35, '#FF00FF', 'Nodus', nod)
|
||||
draw_SVG_circle(-Xf,Zf, 2, 0.3, '#000000', '#0000FF', 'Nodus', nod)
|
||||
|
||||
# --------- Line of zodiac ----------------------------------------------------------------------
|
||||
A = -cos(R)*sin(W)
|
||||
B = -cos(R)*cos(W)
|
||||
C = sin(R)
|
||||
#textvalue='A: %s; B: %s; C: %s' % (A, B, C)
|
||||
#draw_SVG_text(0, 125, textvalue, 'san-serif', 4, gly)
|
||||
|
||||
for i in range(len(D)):
|
||||
D_rad[i]= D[i]*pi/180
|
||||
DP=''
|
||||
for ii in range(len(Time)):
|
||||
T[ii]=(Time[ii]-12)*15
|
||||
T_rad[ii]=T[ii]*pi/180
|
||||
AzSun = atan(sin(T_rad[ii])/(sin(L)*cos(T_rad[ii]) - tan(D_rad[i])*cos(L)))
|
||||
AltSun = asin(sin(D_rad[i])*sin(L) + cos(D_rad[i])*cos(L)*cos(T_rad[ii]))
|
||||
|
||||
if T[ii] < 0:
|
||||
if AzSun > 0:
|
||||
AzSun=AzSun+pi
|
||||
else:
|
||||
AzSun = AzSun+2*pi
|
||||
else:
|
||||
if AzSun >= 0:
|
||||
AzSun=AzSun
|
||||
else:
|
||||
AzSun = AzSun+pi
|
||||
|
||||
#Text
|
||||
#textvalue='AzSun: %s; AltSun: %s; T: %s' % (round(AzSun*180/pi,2), round(AltSun*180/pi,2), Time[ii])
|
||||
#draw_SVG_text(200, 220+5*ii+100*i, textvalue, 'san-serif', 4, gly)
|
||||
|
||||
X0= -cos(AltSun)*sin(AzSun)
|
||||
Y0= -cos(AltSun)*cos(AzSun)
|
||||
Z0= sin(AltSun)
|
||||
|
||||
X1=X0*cos(W)-Y0*sin(W)
|
||||
Y1=X0*sin(W)+Y0*cos(W)
|
||||
Z1=Z0
|
||||
|
||||
X2=X1
|
||||
Y2=Y1*cos(R)-Z1*sin(R)
|
||||
Z2=Y1*sin(R)+Z1*cos(R)
|
||||
|
||||
X3=so.gnom*X2/Y2
|
||||
Z3=-so.gnom*Z2/Y2
|
||||
p1= X0*A+Y0*B+Z0*C
|
||||
|
||||
Xe = X3 - Xf
|
||||
Ze = Z3 + Zf
|
||||
|
||||
if p1 >0:
|
||||
DP = DP +' '+str(Xe)+', '+str(Ze)
|
||||
|
||||
# draw polyline
|
||||
draw_SVG_polyline(DP, 0.5,'#FF0000', 'none', 'Zodiac line '+str(i+1), loz)
|
||||
|
||||
# --------- Time Line ----------------------------------------------------------------------
|
||||
ALFA= atan(widthgrid/(2*heightgrid)) # Line for help
|
||||
|
||||
for i in range(len(Time)):
|
||||
T[i]=(Time[i]-12)*15
|
||||
T_rad[i]=T[i]*pi/180
|
||||
TL=''
|
||||
|
||||
D = [-23.44, -20.15, -11.47, 0.0001, 11.47, 20.15, 23.44]
|
||||
for ii in range(len(D)):
|
||||
D_rad[ii]= D[ii]*pi/180
|
||||
TL= '0, 0'
|
||||
|
||||
AzSun = atan(sin(T_rad[i])/(sin(L)*cos(T_rad[i]) - tan(D_rad[ii])*cos(L)))
|
||||
AltSun = asin(sin(D_rad[ii])*sin(L) + cos(D_rad[ii])*cos(L)*cos(T_rad[i]))
|
||||
|
||||
if T[i] < 0:
|
||||
if AzSun > 0:
|
||||
AzSun=AzSun+pi
|
||||
else:
|
||||
AzSun = AzSun+2*pi
|
||||
else:
|
||||
if AzSun >= 0:
|
||||
AzSun=AzSun
|
||||
else:
|
||||
AzSun = AzSun+pi
|
||||
|
||||
X0= -cos(AltSun)*sin(AzSun)
|
||||
Y0= -cos(AltSun)*cos(AzSun)
|
||||
Z0= sin(AltSun)
|
||||
|
||||
X1=X0*cos(W)-Y0*sin(W)
|
||||
Y1=X0*sin(W)+Y0*cos(W)
|
||||
Z1=Z0
|
||||
|
||||
X2=X1
|
||||
Y2=Y1*cos(R)-Z1*sin(R)
|
||||
Z2=Y1*sin(R)+Z1*cos(R)
|
||||
|
||||
X3=so.gnom*X2/Y2
|
||||
Z3=so.gnom*Z2/Y2
|
||||
|
||||
Xe = X3 - Xf
|
||||
Ze = -Z3 + Zf
|
||||
|
||||
if Ze == 0:
|
||||
Ze = 0.0001
|
||||
|
||||
SG = atan(Xe/Ze)
|
||||
#Xe = so.gnom /((cos(R)/tan(AzSun-W))+(sin(R)*tan(AltSun)/sin(AzSun-W))) - Xf
|
||||
#Ze = -so.gnom *((tan(R)-(tan(AltSun)/cos(AzSun-W)))/(1+(tan(R)*tan(AltSun))/cos(AzSun-W))) + Zf
|
||||
p1= X0*A+Y0*B+Z0*C
|
||||
|
||||
if p1 >=0:
|
||||
#if SG <= pi and SG >=-pi:
|
||||
TL = TL +' '+str(Xe)+', '+str(Ze)
|
||||
else:
|
||||
Xe=-Xe
|
||||
Ze=-Ze
|
||||
TL = TL +' '+str(Xe)+', '+str(Ze)
|
||||
|
||||
if T[i] < 0:
|
||||
if SG >= 0:
|
||||
SG = SG-pi
|
||||
else:
|
||||
SG = SG
|
||||
else:
|
||||
if SG >= 0:
|
||||
SG = SG
|
||||
else:
|
||||
SG = SG+pi
|
||||
|
||||
if SG >= (-pi) and SG < -ALFA:
|
||||
draw_SVG_text(-widthgrid/2+5, -widthgrid/(2*tan(SG)), str(Time[i]), 'Algerian', 8, vhl)
|
||||
|
||||
if SG > (-ALFA) and SG < ALFA:
|
||||
draw_SVG_text(heightgrid*tan(SG), heightgrid-5, str(Time[i]), 'Algerian',8, vhl)
|
||||
|
||||
if SG > ALFA and SG <= (pi):
|
||||
if Time[i] == 12: #workaround because y coordinate gets extreme values like "-816561967659768448.0000"
|
||||
draw_SVG_text(0, heightgrid-5, str(Time[i]), 'Algerian',8, vhl)
|
||||
else:
|
||||
draw_SVG_text(widthgrid/2-8, widthgrid/(2*tan(SG)), str(Time[i]), 'Algerian',8, vhl)
|
||||
#Text
|
||||
#textvalue='Xe: %s; Ze: %s; T: %s; SG: %s' % (round(Xe,2), round(Ze,2), Time[i], SG*180/pi)
|
||||
#draw_SVG_text(0, 220+5*i, textvalue, 'san-serif', 4, gly)
|
||||
|
||||
# draw polyline
|
||||
draw_SVG_polyline(TL, 0.5,'#008000', 'none', 'Time line '+str(Time[i]), loz)
|
||||
|
||||
if __name__ == '__main__':
|
||||
SunDial().run()
|
Reference in New Issue
Block a user