3 # A study on radial symmetry based
5 # Copyright (C) 2015 Antonio Ospite <ao2@ao2.it>
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 class RadialSymmetryModel():
26 def __init__(self, base_polygon_sides=6, base_polygon_radius=None,
27 base_polygon_angle=0, show_base_polygon=False,
28 element_sides=3, element_radius=None, element_angle_offset=0,
29 radial_orientation=True, show_elements=True, show_stars=False,
31 self.base_polygon_sides = base_polygon_sides
32 self.base_polygon_radius = base_polygon_radius
33 self.base_polygon_angle = base_polygon_angle
34 self.show_base_polygon = show_base_polygon
35 self.element_sides = element_sides
36 self.element_radius = element_radius
37 self.element_angle_offset = element_angle_offset
38 self.radial_orientate = radial_orientation
39 self.show_elements = show_elements
40 self.show_stars = show_stars
41 self.show_labels = show_labels
44 class RadialSymmetryDiagram(Diagram.Diagram):
46 def __init__(self, width, height, background=[1, 1, 1]):
47 Diagram.Diagram.__init__(self, width, height, background)
49 def draw(self, model):
51 cy = self.height / 2.0
54 if model.base_polygon_radius is None:
55 model.base_polygon_radius = min(self.width, self.height) / 4.0
57 if model.element_radius is None:
58 model.element_radius = model.base_polygon_radius
61 self.draw_elements(cx, cy, model)
63 def draw_elements(self, cx, cy, model):
64 central_angle = 2 * pi / model.base_polygon_sides
66 base_polygon_orientation = central_angle + model.base_polygon_angle
68 verts = self.get_regular_polygon(cx, cy, model.base_polygon_sides, model.base_polygon_radius,
69 base_polygon_orientation)
71 if model.show_base_polygon:
72 self.draw_polygon(verts, [0, 0, 0])
74 for i, v in enumerate(verts[:]):
75 radial_orientation_angle = (i + 1) * central_angle
76 rotated_radial_orientation_angle = radial_orientation_angle + model.base_polygon_angle
78 # the element orientation may depend the base polygon rotation
79 if model.radial_orientate:
80 element_angle = rotated_radial_orientation_angle
82 element_angle = 2 * pi / model.element_sides
84 element_angle += model.element_angle_offset
86 # the element color depends oly on the element index
87 a = self.normalized_angle_01(radial_orientation_angle)
88 color = colorsys.hsv_to_rgb(a, 1.0, 1.0)
90 self.draw_element(v[0], v[1], model, element_angle, color)
93 ta = self.normalized_angle_01(rotated_radial_orientation_angle)
94 text = ("%.2f" % (ta * 360)).rstrip('0').rstrip('.')
95 color = colorsys.hsv_to_rgb(a, 1.0, 1.0)
96 self.draw_centered_text(v[0], v[1], text,
97 rotated_radial_orientation_angle, color)
99 def draw_element(self, x, y, model, theta, color=[0, 0, 0]):
100 if model.show_elements:
101 tverts = self.get_regular_polygon(x, y, model.element_sides, model.element_radius, theta)
102 self.draw_polygon(tverts, color)
105 apothem = model.element_radius * cos(pi / model.element_sides)
106 apothem_angle = theta + pi / model.element_sides
108 sverts = self.get_regular_polygon(x, y, model.element_sides, apothem,
110 self.draw_star(x, y, sverts, color)
113 if __name__ == '__main__':
114 h = RadialSymmetryDiagram(800, 600)
115 h.draw(RadialSymmetryModel(base_polygon_sides=10, element_sides=4, show_stars=True, show_labels=False))
116 h.draw(RadialSymmetryModel(base_polygon_sides=31, element_sides=4, show_stars=False, show_labels=False))
118 h.save_svg("radial_symmetry_test")
119 h.save_png("radial_symmetry_test")