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 draw(self, model):
48 cy = self.height / 2.0
51 if model.base_polygon_radius is None:
52 model.base_polygon_radius = min(self.width, self.height) / 4.0
54 if model.element_radius is None:
55 model.element_radius = model.base_polygon_radius
58 self.draw_elements(cx, cy, model)
60 def draw_elements(self, cx, cy, model):
61 central_angle = 2 * pi / model.base_polygon_sides
63 base_polygon_orientation = central_angle + model.base_polygon_angle
65 verts = self.get_regular_polygon(cx, cy, model.base_polygon_sides, model.base_polygon_radius,
66 base_polygon_orientation)
68 if model.show_base_polygon:
69 self.draw_polygon(verts, [0, 0, 0])
71 for i, v in enumerate(verts[:]):
72 radial_orientation_angle = (i + 1) * central_angle
73 rotated_radial_orientation_angle = radial_orientation_angle + model.base_polygon_angle
75 # the element orientation may depend the base polygon rotation
76 if model.radial_orientate:
77 element_angle = rotated_radial_orientation_angle
79 element_angle = 2 * pi / model.element_sides
81 element_angle += model.element_angle_offset
83 # the element color depends oly on the element index
84 a = self.normalized_angle_01(radial_orientation_angle)
85 color = colorsys.hsv_to_rgb(a, 1.0, 1.0)
87 self.draw_element(v[0], v[1], model, element_angle, color)
90 ta = self.normalized_angle_01(rotated_radial_orientation_angle)
91 text = ("%.2f" % (ta * 360)).rstrip('0').rstrip('.')
92 color = colorsys.hsv_to_rgb(a, 1.0, 1.0)
93 self.draw_centered_text(v[0], v[1], text,
94 rotated_radial_orientation_angle, color)
96 def draw_element(self, x, y, model, theta, color=[0, 0, 0]):
97 if model.show_elements:
98 tverts = self.get_regular_polygon(x, y, model.element_sides, model.element_radius, theta)
99 self.draw_polygon(tverts, color)
102 apothem = model.element_radius * cos(pi / model.element_sides)
103 apothem_angle = theta + pi / model.element_sides
105 sverts = self.get_regular_polygon(x, y, model.element_sides, apothem,
107 self.draw_star(x, y, sverts, color)
110 if __name__ == '__main__':
111 h = RadialSymmetryDiagram(800, 600)
112 h.draw(RadialSymmetryModel(base_polygon_sides=10, element_sides=4, show_stars=True, show_labels=False))
113 h.draw(RadialSymmetryModel(base_polygon_sides=31, element_sides=4, show_stars=False, show_labels=False))
115 h.save_svg("radial_symmetry_test")
116 h.save_png("radial_symmetry_test")