#!/usr/bin/env python # # A study on radial symmetry based # # Copyright (C) 2015 Antonio Ospite # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from math import * import colorsys import Diagram class RadialSymmetryModel(): def __init__(self, base_polygon_sides=6, base_polygon_radius=None, base_polygon_angle=0, show_base_polygon=False, element_sides=3, element_radius=None, element_angle_offset=0, radial_orientation=True, show_elements=True, show_stars=False, show_labels=False): self.base_polygon_sides = base_polygon_sides self.base_polygon_radius = base_polygon_radius self.base_polygon_angle = base_polygon_angle self.show_base_polygon = show_base_polygon self.element_sides = element_sides self.element_radius = element_radius self.element_angle_offset = element_angle_offset self.radial_orientate = radial_orientation self.show_elements = show_elements self.show_stars = show_stars self.show_labels = show_labels class RadialSymmetryDiagram(Diagram.Diagram): def draw(self, model): cx = self.width / 2.0 cy = self.height / 2.0 # internal radius if model.base_polygon_radius is None: model.base_polygon_radius = min(self.width, self.height) / 4.0 if model.element_radius is None: model.element_radius = model.base_polygon_radius self.clear() self.draw_elements(cx, cy, model) def draw_elements(self, cx, cy, model): central_angle = 2 * pi / model.base_polygon_sides base_polygon_orientation = central_angle + model.base_polygon_angle verts = self.get_regular_polygon(cx, cy, model.base_polygon_sides, model.base_polygon_radius, base_polygon_orientation) if model.show_base_polygon: self.draw_polygon(verts, [0, 0, 0]) for i, v in enumerate(verts[:]): radial_orientation_angle = (i + 1) * central_angle rotated_radial_orientation_angle = radial_orientation_angle + model.base_polygon_angle # the element orientation may depend the base polygon rotation if model.radial_orientate: element_angle = rotated_radial_orientation_angle else: element_angle = 2 * pi / model.element_sides element_angle += model.element_angle_offset # the element color depends oly on the element index a = self.normalized_angle_01(radial_orientation_angle) color = colorsys.hsv_to_rgb(a, 1.0, 1.0) self.draw_element(v[0], v[1], model, element_angle, color) if model.show_labels: ta = self.normalized_angle_01(rotated_radial_orientation_angle) text = ("%.2f" % (ta * 360)).rstrip('0').rstrip('.') color = colorsys.hsv_to_rgb(a, 1.0, 1.0) self.draw_centered_text(v[0], v[1], text, rotated_radial_orientation_angle, color, align_baseline=True) def draw_element(self, x, y, model, theta, color=[0, 0, 0]): if model.show_elements: tverts = self.get_regular_polygon(x, y, model.element_sides, model.element_radius, theta) self.draw_polygon(tverts, color) if model.show_stars: apothem = model.element_radius * cos(pi / model.element_sides) apothem_angle = theta + pi / model.element_sides sverts = self.get_regular_polygon(x, y, model.element_sides, apothem, apothem_angle) self.draw_star(x, y, sverts, color) if __name__ == '__main__': h = RadialSymmetryDiagram(800, 600) h.draw(RadialSymmetryModel(base_polygon_sides=10, element_sides=4, show_stars=True, show_labels=False)) h.draw(RadialSymmetryModel(base_polygon_sides=31, element_sides=4, show_stars=False, show_labels=False)) h.show() h.save_svg("radial_symmetry_test") h.save_png("radial_symmetry_test")