# -*- coding: utf-8 -*-
'''
経緯線描画 (日時指定)
Ver 1.11 2013-05-29 update
'''
from tkinter import *
from math import *
from numpy import *
from urllib.request import *
from urllib.parse import *
from html.parser import HTMLParser
import datetime
'''
経緯線描画
'''
class LatLong:
def __init__(self, P,B0,L0,r,width,height,astep,dstep,bg,fc,line,fpath):
self.root = Tk()
self.P = P
self.B0 = B0
self.L0 = L0
self.r = r
self.width = width
self.height = height
self.astep = astep
self.dstep = dstep
self.backcolor = bg
self.forecolor = fc
self.lineweight = line
self.fpath = fpath
self.c0=Canvas(self.root, width=width, height=height, bg=bg)
self.c0.pack()
# Z軸回転
def rotZ(self, a, d):
L = cos(radians(d)) * cos(radians(a - self.L0))
M = cos(radians(d)) * sin(radians(a - self.L0))
N = sin(radians(d))
return array([[L], [M], [N]])
# Y軸回転
def rotY(self, LMN):
mB0 = radians(self.B0) * -1
res = array([[]])
res = append(res, [[cos(mB0), 0, -1 * sin(mB0)]], axis=1)
res = append(res, [[0, 1, 0]], axis=0)
res = append(res, [[sin(mB0), 0, cos(mB0)]], axis=0)
return dot(res, LMN)
# X軸回転
def rotX(self, LMNd):
mP = radians(self.P) * -1
res = array([[]])
res = append(res, [[1, 0, 0]], axis=1)
res = append(res, [[0, cos(mP), sin(mP)]], axis=0)
res = append(res, [[0, -1 * sin(mP), cos(mP)]], axis=0)
return dot(res, LMNd)
# XYZ計算
def calXYZ(self, a, d):
LMN = self.rotZ(a,d)
LMNd = self.rotY(LMN)
xyz = self.rotX(LMNd)
return sum(xyz[0]),sum(xyz[1]),sum(xyz[2])
# 位置補正(XYZ)
def corrPos(self, x, y, z):
x = x
y = y * self.r + self.width / 2
z = self.height / 2 - z * self.r
return x,y,z
# 緯線
def Latitude(self):
lpos=[]
for delta in range(-90,90,self.dstep):
for alpha in range(0, 361, 5):
xyz = self.calXYZ(alpha, delta)
x,y,z = self.corrPos(xyz[0], xyz[1], xyz[2])
if x>=0:
lpos.append(y)
lpos.append(z)
else:
if len(lpos)>2:
self.c0.create_line(lpos,fill=self.forecolor,width=self.lineweight,smooth=True)
lpos[:]=[]
if len(lpos)>2:
self.c0.create_line(lpos,fill=self.forecolor,width=self.lineweight,smooth=True)
lpos[:]=[]
# 経線
def Longitude(self):
lpos=[]
for alpha in range(0,360,self.astep):
for delta in range(-90, 91, 5):
xyz = self.calXYZ(alpha, delta)
x,y,z = self.corrPos(xyz[0], xyz[1], xyz[2])
if x>=0:
lpos.append(y)
lpos.append(z)
if len(lpos)>2:
self.c0.create_line(lpos,fill=self.forecolor,width=self.lineweight,smooth=True)
lpos[:]=[]
# 外周描画
def dispOuter(self):
lpos = []
for pos in range(360):
y = cos(radians(pos))
z = sin(radians(pos))
x,y,z = self.corrPos(0, y, z)
lpos.append(y)
lpos.append(z)
self.c0.create_line(lpos,fill=self.forecolor,width=self.lineweight,smooth=True)
lpos[:] = []
# Save PostScript
def SaveImage(self):
self.c0.postscript(file=self.fpath, width=self.width, height=self.height)
# MainLoop
def mainloop(self):
self.root.mainloop()
'''
国立天文台よりPB0L0取得
'''
class KHTMLParser(HTMLParser):
hms = "00:00:00"
getfl = False
P = None
B0 = None
L0 = None
def handle_data(self, data):
data = data.strip(" \t\r\n")
if data and self.getfl:
if self.P and self.B0 and self.L0 is None: self.L0 = float(data)
if self.P and self.B0 is None: self.B0 = float(data)
if self.P is None: self.P = float(data)
if data.strip() == self.hms: self.getfl = True
def handle_starttag(self, tag, attrs):
pass
def handle_endtag(self, tag):
pass
'''
Main
'''
if __name__=='__main__':
'''
使用方法
クラス初期化
LatLong(P,B0,L0,r,width,height,astep,dstep,backcolor,forecolor,lineweight,fpath)
'''
# PB0L0取得
params = {'year':2013,'month':5,'day':20,'hour':10,'min':30,'sec':00,'tsys':2}
r=urlopen("http://e...content-available-to-author-only...c.jp/cgi-bin/koyomi/cande/sun_spin.cgi",urlencode(params).encode("utf-8"))
mp = KHTMLParser()
mp.hms = "%02d:%02d:%02d" % (params['hour'], params['min'], params['sec'])
mp.feed(r.read().decode("euc_jp"))
# LatLong起動
latlong = LatLong(mp.P,mp.B0,mp.L0,300, 800, 800, 15, 15, "black", "green", 2.0, r"~/Desktop/ball.ps")
latlong.Latitude()
latlong.Longitude()
latlong.dispOuter()
latlong.SaveImage()
latlong.mainloop()
IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KJycnCue1jOe3r+e3muaPj+eUuyAo5pel5pmC5oyH5a6aKQpWZXIgMS4xMSAyMDEzLTA1LTI5IHVwZGF0ZQonJycKZnJvbSB0a2ludGVyIGltcG9ydCAqCmZyb20gbWF0aCBpbXBvcnQgKgpmcm9tIG51bXB5IGltcG9ydCAqCmZyb20gdXJsbGliLnJlcXVlc3QgaW1wb3J0ICoKZnJvbSB1cmxsaWIucGFyc2UgaW1wb3J0ICoKZnJvbSBodG1sLnBhcnNlciBpbXBvcnQgSFRNTFBhcnNlcgppbXBvcnQgZGF0ZXRpbWUKCicnJwrntYznt6/nt5rmj4/nlLsKJycnCmNsYXNzIExhdExvbmc6CiAgICBkZWYgX19pbml0X18oc2VsZiwgUCxCMCxMMCxyLHdpZHRoLGhlaWdodCxhc3RlcCxkc3RlcCxiZyxmYyxsaW5lLGZwYXRoKToKICAgICAgICBzZWxmLnJvb3QgPSBUaygpCiAgICAgICAgc2VsZi5QID0gUAogICAgICAgIHNlbGYuQjAgPSBCMAogICAgICAgIHNlbGYuTDAgPSBMMAogICAgICAgIHNlbGYuciA9IHIKICAgICAgICBzZWxmLndpZHRoID0gd2lkdGgKICAgICAgICBzZWxmLmhlaWdodCA9IGhlaWdodAogICAgICAgIHNlbGYuYXN0ZXAgPSBhc3RlcAogICAgICAgIHNlbGYuZHN0ZXAgPSBkc3RlcAogICAgICAgIHNlbGYuYmFja2NvbG9yID0gYmcKICAgICAgICBzZWxmLmZvcmVjb2xvciA9IGZjCiAgICAgICAgc2VsZi5saW5ld2VpZ2h0ID0gbGluZQogICAgICAgIHNlbGYuZnBhdGggPSBmcGF0aAogICAgICAgIHNlbGYuYzA9Q2FudmFzKHNlbGYucm9vdCwgd2lkdGg9d2lkdGgsIGhlaWdodD1oZWlnaHQsIGJnPWJnKQogICAgICAgIHNlbGYuYzAucGFjaygpCgogICAgIyBa6Lu45Zue6LuiCiAgICBkZWYgcm90WihzZWxmLCBhLCBkKToKICAgICAgICBMID0gY29zKHJhZGlhbnMoZCkpICogY29zKHJhZGlhbnMoYSAtIHNlbGYuTDApKQogICAgICAgIE0gPSBjb3MocmFkaWFucyhkKSkgKiBzaW4ocmFkaWFucyhhIC0gc2VsZi5MMCkpCiAgICAgICAgTiA9IHNpbihyYWRpYW5zKGQpKQogICAgICAgIHJldHVybiBhcnJheShbW0xdLCBbTV0sIFtOXV0pCgogICAgIyBZ6Lu45Zue6LuiCiAgICBkZWYgcm90WShzZWxmLCBMTU4pOgogICAgICAgIG1CMCA9IHJhZGlhbnMoc2VsZi5CMCkgKiAtMQogICAgICAgIHJlcyA9IGFycmF5KFtbXV0pCiAgICAgICAgcmVzID0gYXBwZW5kKHJlcywgW1tjb3MobUIwKSwgMCwgLTEgKiBzaW4obUIwKV1dLCBheGlzPTEpCiAgICAgICAgcmVzID0gYXBwZW5kKHJlcywgW1swLCAxLCAwXV0sIGF4aXM9MCkKICAgICAgICByZXMgPSBhcHBlbmQocmVzLCBbW3NpbihtQjApLCAwLCBjb3MobUIwKV1dLCBheGlzPTApCiAgICAgICAgcmV0dXJuIGRvdChyZXMsIExNTikKICAgIAogICAgIyBY6Lu45Zue6LuiCiAgICBkZWYgcm90WChzZWxmLCBMTU5kKToKICAgICAgICBtUCA9IHJhZGlhbnMoc2VsZi5QKSAqIC0xCiAgICAgICAgcmVzID0gYXJyYXkoW1tdXSkKICAgICAgICByZXMgPSBhcHBlbmQocmVzLCBbWzEsIDAsIDBdXSwgYXhpcz0xKQogICAgICAgIHJlcyA9IGFwcGVuZChyZXMsIFtbMCwgY29zKG1QKSwgc2luKG1QKV1dLCBheGlzPTApCiAgICAgICAgcmVzID0gYXBwZW5kKHJlcywgW1swLCAtMSAqIHNpbihtUCksIGNvcyhtUCldXSwgYXhpcz0wKQogICAgICAgIHJldHVybiBkb3QocmVzLCBMTU5kKQoKICAgICMgWFla6KiI566XCiAgICBkZWYgY2FsWFlaKHNlbGYsIGEsIGQpOgogICAgICAgIExNTiA9IHNlbGYucm90WihhLGQpCiAgICAgICAgTE1OZCA9IHNlbGYucm90WShMTU4pCiAgICAgICAgeHl6ID0gc2VsZi5yb3RYKExNTmQpCgogICAgICAgIHJldHVybiBzdW0oeHl6WzBdKSxzdW0oeHl6WzFdKSxzdW0oeHl6WzJdKQoKICAgICMg5L2N572u6KOc5q2jKFhZWikKICAgIGRlZiBjb3JyUG9zKHNlbGYsIHgsIHksIHopOgogICAgICAgIHggPSB4CiAgICAgICAgeSA9IHkgKiBzZWxmLnIgKyBzZWxmLndpZHRoIC8gMgogICAgICAgIHogPSBzZWxmLmhlaWdodCAvIDIgLSB6ICogc2VsZi5yCiAgICAgICAgcmV0dXJuIHgseSx6CiAgICAgICAgCiAgICAj44CA57ev57eaCiAgICBkZWYgTGF0aXR1ZGUoc2VsZik6CiAgICAgICAgbHBvcz1bXQogICAgICAgIGZvciBkZWx0YSBpbiByYW5nZSgtOTAsOTAsc2VsZi5kc3RlcCk6CiAgICAgICAgICAgIGZvciBhbHBoYSBpbiByYW5nZSgwLCAzNjEsIDUpOgogICAgICAgICAgICAgICAgeHl6ID0gc2VsZi5jYWxYWVooYWxwaGEsIGRlbHRhKQogICAgICAgICAgICAgICAgeCx5LHogPSBzZWxmLmNvcnJQb3MoeHl6WzBdLCB4eXpbMV0sIHh5elsyXSkKICAgICAgICAgICAgICAgIGlmIHg+PTA6CiAgICAgICAgICAgICAgICAgICAgbHBvcy5hcHBlbmQoeSkKICAgICAgICAgICAgICAgICAgICBscG9zLmFwcGVuZCh6KQogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICBpZiBsZW4obHBvcyk+MjoKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jMC5jcmVhdGVfbGluZShscG9zLGZpbGw9c2VsZi5mb3JlY29sb3Isd2lkdGg9c2VsZi5saW5ld2VpZ2h0LHNtb290aD1UcnVlKQogICAgICAgICAgICAgICAgICAgIGxwb3NbOl09W10KCiAgICAgICAgICAgIGlmIGxlbihscG9zKT4yOiAKICAgICAgICAgICAgICAgIHNlbGYuYzAuY3JlYXRlX2xpbmUobHBvcyxmaWxsPXNlbGYuZm9yZWNvbG9yLHdpZHRoPXNlbGYubGluZXdlaWdodCxzbW9vdGg9VHJ1ZSkKICAgICAgICAgICAgbHBvc1s6XT1bXQogICAgICAgIAogICAgIyDntYznt5oKICAgIGRlZiBMb25naXR1ZGUoc2VsZik6CiAgICAgICAgbHBvcz1bXQogICAgICAgIGZvciBhbHBoYSBpbiByYW5nZSgwLDM2MCxzZWxmLmFzdGVwKToKICAgICAgICAgICAgZm9yIGRlbHRhIGluIHJhbmdlKC05MCwgOTEsIDUpOgogICAgICAgICAgICAgICAgeHl6ID0gc2VsZi5jYWxYWVooYWxwaGEsIGRlbHRhKQogICAgICAgICAgICAgICAgeCx5LHogPSBzZWxmLmNvcnJQb3MoeHl6WzBdLCB4eXpbMV0sIHh5elsyXSkKICAgICAgICAgICAgICAgIGlmIHg+PTA6CiAgICAgICAgICAgICAgICAgICAgbHBvcy5hcHBlbmQoeSkKICAgICAgICAgICAgICAgICAgICBscG9zLmFwcGVuZCh6KQogICAgICAgICAgICBpZiBsZW4obHBvcyk+MjoKICAgICAgICAgICAgICAgIHNlbGYuYzAuY3JlYXRlX2xpbmUobHBvcyxmaWxsPXNlbGYuZm9yZWNvbG9yLHdpZHRoPXNlbGYubGluZXdlaWdodCxzbW9vdGg9VHJ1ZSkKICAgICAgICAgICAgbHBvc1s6XT1bXQoKICAgICMg5aSW5ZGo5o+P55S7CiAgICBkZWYgZGlzcE91dGVyKHNlbGYpOgogICAgICAgIGxwb3MgPSBbXQogICAgICAgIGZvciBwb3MgaW4gcmFuZ2UoMzYwKToKICAgICAgICAgICAgeSA9IGNvcyhyYWRpYW5zKHBvcykpCiAgICAgICAgICAgIHogPSBzaW4ocmFkaWFucyhwb3MpKQogICAgICAgICAgICB4LHkseiA9IHNlbGYuY29yclBvcygwLCB5LCB6KQoKICAgICAgICAgICAgbHBvcy5hcHBlbmQoeSkKICAgICAgICAgICAgbHBvcy5hcHBlbmQoeikKICAgICAgICBzZWxmLmMwLmNyZWF0ZV9saW5lKGxwb3MsZmlsbD1zZWxmLmZvcmVjb2xvcix3aWR0aD1zZWxmLmxpbmV3ZWlnaHQsc21vb3RoPVRydWUpCiAgICAgICAgbHBvc1s6XSA9IFtdCgogICAgIyBTYXZlIFBvc3RTY3JpcHQKICAgIGRlZiBTYXZlSW1hZ2Uoc2VsZik6CiAgICAgICAgc2VsZi5jMC5wb3N0c2NyaXB0KGZpbGU9c2VsZi5mcGF0aCwgd2lkdGg9c2VsZi53aWR0aCwgaGVpZ2h0PXNlbGYuaGVpZ2h0KQoKICAgICMgTWFpbkxvb3AKICAgIGRlZiBtYWlubG9vcChzZWxmKToKICAgICAgICBzZWxmLnJvb3QubWFpbmxvb3AoKQoKCicnJwrlm73nq4vlpKnmloflj7DjgojjgopQQjBMMOWPluW+lwonJycKY2xhc3MgS0hUTUxQYXJzZXIoSFRNTFBhcnNlcik6CiAgICBobXMgPSAiMDA6MDA6MDAiCiAgICBnZXRmbCA9IEZhbHNlCiAgICBQID0gTm9uZQogICAgQjAgPSBOb25lCiAgICBMMCA9IE5vbmUKICAgIAogICAgZGVmIGhhbmRsZV9kYXRhKHNlbGYsIGRhdGEpOgogICAgICAgIGRhdGEgPSBkYXRhLnN0cmlwKCIgIFx0XHJcbiIpCgogICAgICAgIGlmIGRhdGEgYW5kIHNlbGYuZ2V0Zmw6CiAgICAgICAgICAgIGlmIHNlbGYuUCBhbmQgc2VsZi5CMCBhbmQgc2VsZi5MMCBpcyBOb25lOiBzZWxmLkwwID0gZmxvYXQoZGF0YSkKICAgICAgICAgICAgaWYgc2VsZi5QIGFuZCBzZWxmLkIwIGlzIE5vbmU6IHNlbGYuQjAgPSBmbG9hdChkYXRhKQogICAgICAgICAgICBpZiBzZWxmLlAgaXMgTm9uZTogc2VsZi5QID0gZmxvYXQoZGF0YSkKICAgICAgICAgICAgCiAgICAgICAgaWYgZGF0YS5zdHJpcCgpID09IHNlbGYuaG1zOiBzZWxmLmdldGZsID0gVHJ1ZQoKICAgIGRlZiBoYW5kbGVfc3RhcnR0YWcoc2VsZiwgdGFnLCBhdHRycyk6CiAgICAgICAgcGFzcwoKICAgIGRlZiBoYW5kbGVfZW5kdGFnKHNlbGYsIHRhZyk6CiAgICAgICAgcGFzcwoKCicnJwpNYWluCicnJwppZiBfX25hbWVfXz09J19fbWFpbl9fJzoKICAgICcnJwogICAg5L2/55So5pa55rOVCgogICAg44Kv44Op44K55Yid5pyf5YyWCiAgICBMYXRMb25nKFAsQjAsTDAscix3aWR0aCxoZWlnaHQsYXN0ZXAsZHN0ZXAsYmFja2NvbG9yLGZvcmVjb2xvcixsaW5ld2VpZ2h0LGZwYXRoKQogICAgJycnCiAgICAjIFBCMEww5Y+W5b6XCiAgICBwYXJhbXMgPSB7J3llYXInOjIwMTMsJ21vbnRoJzo1LCdkYXknOjIwLCdob3VyJzoxMCwnbWluJzozMCwnc2VjJzowMCwndHN5cyc6Mn0KCiAgICByPXVybG9wZW4oImh0dHA6Ly9lLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5jLmpwL2NnaS1iaW4va295b21pL2NhbmRlL3N1bl9zcGluLmNnaSIsdXJsZW5jb2RlKHBhcmFtcykuZW5jb2RlKCJ1dGYtOCIpKQogICAgbXAgPSBLSFRNTFBhcnNlcigpCiAgICBtcC5obXMgPSAiJTAyZDolMDJkOiUwMmQiICUgKHBhcmFtc1snaG91ciddLCBwYXJhbXNbJ21pbiddLCBwYXJhbXNbJ3NlYyddKQogICAgbXAuZmVlZChyLnJlYWQoKS5kZWNvZGUoImV1Y19qcCIpKQoKICAgICMgTGF0TG9uZ+i1t+WLlQogICAgbGF0bG9uZyA9IExhdExvbmcobXAuUCxtcC5CMCxtcC5MMCwzMDAsIDgwMCwgODAwLCAxNSwgMTUsICJibGFjayIsICJncmVlbiIsIDIuMCwgciJ+L0Rlc2t0b3AvYmFsbC5wcyIpCiAgICAKICAgIGxhdGxvbmcuTGF0aXR1ZGUoKQogICAgbGF0bG9uZy5Mb25naXR1ZGUoKQogICAgbGF0bG9uZy5kaXNwT3V0ZXIoKQogICAgbGF0bG9uZy5TYXZlSW1hZ2UoKQogICAgbGF0bG9uZy5tYWlubG9vcCgpCg==