Created
September 4, 2011 18:01
-
-
Save basicxman/1193231 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import glob | |
| import string | |
| import colorsys | |
| import sys | |
| from Tkinter import * | |
| class Constellations(object): | |
| def __init__(self): | |
| self.named_stars = [] | |
| self.constellations = {} | |
| def parse_constellations(self): | |
| for file_name in glob.glob("constellations/*.txt"): | |
| self.add_constellation_file(file_name) | |
| def add_constellation_file(self, file_name): | |
| star_pairs = open(file_name, "r").read().split("\n") | |
| ss, se = 15, file_name.index(".txt") | |
| name = file_name[ss:se] | |
| self.constellations[name] = [] | |
| for pair in star_pairs: | |
| t = map(self.find_star_by_name, pair.split(",")) | |
| self.constellations[name].append(t) | |
| def add_star(self, x, y, cx, cy, magnitude, names): | |
| if names[0] == "": return | |
| for name in names: | |
| self.named_stars.append((x, y, cx, cy, magnitude, name)) | |
| def sort_stars(self): | |
| self.named_stars = sorted(self.named_stars, key=lambda star: star[5]) | |
| def binary_search(self, l, value, left = 0, right = None): | |
| if right == None: right = len(l) - 1 | |
| if right < left: | |
| return -1 | |
| mid = (left + right) / 2 | |
| if l[mid][5] > value: | |
| return self.binary_search(l, value, left, mid - 1) | |
| elif l[mid][5] < value: | |
| return self.binary_search(l, value, mid + 1, right) | |
| else: | |
| return mid | |
| def find_star_by_name(self, name): | |
| return self.binary_search(self.named_stars, name) | |
| def draw(self, cv): | |
| for constellation in self.constellations: | |
| self.draw_constellation(cv, self.constellations[constellation]) | |
| def draw_constellation(self, cv, constellation): | |
| for pair in constellation: | |
| if pair[0] == -1: continue | |
| x1, y1 = self.named_stars[pair[0]][2:4] | |
| x2, y2 = self.named_stars[pair[1]][2:4] | |
| cv.create_line(x1, y1, x2, y2, fill = "green") | |
| cv.pack() | |
| class Stars(object): | |
| def __init__(self, width, height): | |
| self.canvas_width = width | |
| self.canvas_height = height | |
| self.canvas_margin = 10 | |
| self.constellations = Constellations() | |
| self.initialize_graphics() | |
| self.parse_file("stars.txt") | |
| self.constellations.sort_stars() | |
| self.constellations.parse_constellations() | |
| self.constellations.draw(self.cv) | |
| def initialize_graphics(self): | |
| self.root = Tk() | |
| self.root.title("Stars") | |
| self.cv = Canvas(self.root, width = self.canvas_width + 50, height = self.canvas_height + 20, bg = "black") | |
| self.cv.pack() | |
| self.display_magnitude_legend() | |
| def display_magnitude_legend(self): | |
| for i in range(1, 25): | |
| self.draw_star(i / 2.0, self.canvas_width + 15, i * (i / 3.0)) | |
| # Python can die with many fires here, such a poorly documented stdlib module (colorsys). | |
| def convert_to_rgb(self, h, s, l): | |
| r, g, b = map(lambda x: x * 255, colorsys.hls_to_rgb(h, s, l)) | |
| return "#%02x%02x%02x" % (r, g, b) | |
| def magnitude_to_hsl(self, magnitude): | |
| value = magnitude / 10.0 | |
| value = 0 if value < 0 else 1 if value > 1 else value | |
| h, s, l = 0.55 + value / 2, value, 0.75 | |
| return (h, s, l) | |
| def draw_star(self, magnitude, x, y): | |
| m = magnitude * 0.45 | |
| colour = self.convert_to_rgb(*self.magnitude_to_hsl(magnitude)) | |
| self.cv.create_oval(x - m / 2, y - m / 2, x + m, y + m, fill = colour) | |
| self.cv.pack() | |
| def coordinate_to_pixel(self, x, y): | |
| return self.scale(x, self.canvas_width) + self.canvas_margin, self.scale(y * -1, self.canvas_height) + self.canvas_margin | |
| def scale(self, value, bound): | |
| x = (value + 1) * bound # Ensure number is positive and multiply by maximum. | |
| return x / 2.0 # Divide by range of -1 to 1. | |
| def fill_args(self, args): | |
| if len(args) == 6: args.append("") | |
| elif len(args) > 7: | |
| args[6] = " ".join(args[6:]) | |
| args = args[0:7] | |
| return args | |
| def parse_line(self, line): | |
| if not line: return | |
| x, y, z, henry, magnitude, harvard, names = self.fill_args(line.split(" ")) | |
| x, y, magnitude, names = float(x), float(y), float(magnitude), map(string.strip, names.split(";")) | |
| cx, cy = self.coordinate_to_pixel(x, y) | |
| self.constellations.add_star(x, y, cx, cy, magnitude, names) | |
| self.draw_star(magnitude, cx, cy) | |
| def parse_file(self, file_name): | |
| lines = open(file_name, "r").read().split("\n") | |
| return map(self.parse_line, lines) | |
| if len(sys.argv) != 3: | |
| star_field = Stars(800, 800) | |
| else: | |
| star_field = Stars(int(sys.argv[1]), int(sys.argv[2])) | |
| star_field.root.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment