3
Copyright (C) 2007 John Beard john.j.beard@gmail.com
5
##This extension allows you to draw a polar grid in Inkscape.
6
##There is a wide range of options including subdivision and labels.
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
import simplestyle, sys
27
def draw_SVG_circle(r, cx, cy, width, fill, name, parent):
28
style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill': fill }
29
circ_attribs = {'style':simplestyle.formatStyle(style),
30
'cx':str(cx), 'cy':str(cy),
32
inkex.addNS('label','inkscape'):name}
33
circle = inkex.etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs )
35
def draw_SVG_line(x1, y1, x2, y2, width, name, parent):
36
style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill': 'none' }
37
line_attribs = {'style':simplestyle.formatStyle(style),
38
inkex.addNS('label','inkscape'):name,
39
'd':'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)}
40
inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs )
42
def draw_SVG_label_centred(x, y, string, font_size, name, parent):
43
style = {'text-align': 'center', 'vertical-align': 'top',
44
'text-anchor': 'middle', 'font-size': str(font_size)+'px',
45
'fill-opacity': '1.0', 'stroke': 'none',
46
'font-weight': 'normal', 'font-style': 'normal', 'fill': '#000000'}
47
label_attribs = {'style':simplestyle.formatStyle(style),
48
inkex.addNS('label','inkscape'):name,
49
'x':str(x), 'y':str(y)}
50
label = inkex.etree.SubElement(parent, inkex.addNS('text','svg'), label_attribs)
53
class Grid_Polar(inkex.Effect):
55
inkex.Effect.__init__(self)
56
self.OptionParser.add_option("--r_divs",
57
action="store", type="int",
58
dest="r_divs", default=5,
59
help="Circular Divisions")
60
self.OptionParser.add_option("--dr",
61
action="store", type="float",
62
dest="dr", default=50,
63
help="Circular Division Spacing")
64
self.OptionParser.add_option("--r_subdivs",
65
action="store", type="int",
66
dest="r_subdivs", default=3,
67
help="Circular Subdivisions per Major division")
68
self.OptionParser.add_option("--r_log",
69
action="store", type="inkbool",
70
dest="r_log", default=False,
71
help="Logarithmic subdivisions if true")
72
self.OptionParser.add_option("--r_divs_th",
73
action="store", type="float",
74
dest="r_divs_th", default=2,
75
help="Major Circular Division Line thickness")
76
self.OptionParser.add_option("--r_subdivs_th",
77
action="store", type="float",
78
dest="r_subdivs_th", default=1,
79
help="Minor Circular Division Line thickness")
80
self.OptionParser.add_option("--a_divs",
81
action="store", type="int",
82
dest="a_divs", default=24,
83
help="Angle Divisions")
84
self.OptionParser.add_option("--a_divs_cent",
85
action="store", type="int",
86
dest="a_divs_cent", default=4,
87
help="Angle Divisions at Centre")
88
self.OptionParser.add_option("--a_subdivs",
89
action="store", type="int",
90
dest="a_subdivs", default=1,
91
help="Angcular Subdivisions per Major division")
92
self.OptionParser.add_option("--a_subdivs_cent",
93
action="store", type="int",
94
dest="a_subdivs_cent", default=1,
95
help="Angular Subdivisions end 'n' major circular divisions before the centre")
96
self.OptionParser.add_option("--a_divs_th",
97
action="store", type="float",
98
dest="a_divs_th", default=2,
99
help="Major Angular Division Line thickness")
100
self.OptionParser.add_option("--a_subdivs_th",
101
action="store", type="float",
102
dest="a_subdivs_th", default=1,
103
help="Minor Angular Division Line thickness")
104
self.OptionParser.add_option("--c_dot_dia",
105
action="store", type="float",
106
dest="c_dot_dia", default=5.0,
107
help="Diameter of Centre Dot")
108
self.OptionParser.add_option("--a_labels",
109
action="store", type="string",
110
dest="a_labels", default='deg',
111
help="The kind of labels to apply")
112
self.OptionParser.add_option("--a_label_size",
113
action="store", type="int",
114
dest="a_label_size", default=18,
115
help="The nominal pixel size of the circumferential labels")
116
self.OptionParser.add_option("--a_label_outset",
117
action="store", type="float",
118
dest="a_label_outset", default=24,
119
help="The radial outset of the circumferential labels")
123
# Embed grid in group
124
#Put in in the centre of the current view
125
t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
126
g_attribs = {inkex.addNS('label','inkscape'):'Grid_Polar:R' +
127
str( self.options.r_divs )+':A'+str( self.options.a_divs ),
129
grid = inkex.etree.SubElement(self.current_layer, 'g', g_attribs)
131
dr = self.options.dr #Distance between neighbouring circles
132
dtheta = 2 * pi / self.options.a_divs_cent #Angular change between adjacent radial lines at centre
133
rmax = self.options.r_divs * dr
136
for i in range(1, self.options.r_divs+1):
137
draw_SVG_circle(i*dr, 0, 0, #major div circles
138
self.options.r_divs_th, 'none',
139
'MajorDivCircle'+str(i)+':R'+str(i*dr), grid)
141
if self.options.r_log: #logarithmic subdivisions
142
for j in range (2, self.options.r_subdivs):
143
draw_SVG_circle(i*dr-(1-log(j, self.options.r_subdivs))*dr, #minor div circles
144
0, 0, self.options.r_subdivs_th, 'none',
145
'MinorDivCircle'+str(i)+':Log'+str(j), grid)
146
else: #linear subdivs
147
for j in range (1, self.options.r_subdivs):
148
draw_SVG_circle(i*dr-j*dr/self.options.r_subdivs, #minor div circles
149
0, 0, self.options.r_subdivs_th, 'none',
150
'MinorDivCircle'+str(i)+':R'+str(i*dr), grid)
152
if self.options.a_divs == self.options.a_divs_cent: #the lines can go from the centre to the edge
153
for i in range(0, self.options.a_divs):
154
draw_SVG_line(0, 0, rmax*sin(i*dtheta), rmax*cos(i*dtheta),
155
self.options.a_divs_th, 'RadialGridline'+str(i), grid)
157
else: #we need separate lines
158
for i in range(0, self.options.a_divs_cent): #lines that go to the first circle
159
draw_SVG_line(0, 0, dr*sin(i*dtheta), dr*cos(i*dtheta),
160
self.options.a_divs_th, 'RadialGridline'+str(i), grid)
162
dtheta = 2 * pi / self.options.a_divs #work out the angle change for outer lines
164
for i in range(0, self.options.a_divs): #lines that go from there to the edge
165
draw_SVG_line( dr*sin(i*dtheta+pi/2.0), dr*cos(i*dtheta+pi/2.0),
166
rmax*sin(i*dtheta+pi/2.0), rmax*cos(i*dtheta+pi/2.0),
167
self.options.a_divs_th, 'RadialGridline'+str(i), grid)
169
if self.options.a_subdivs > 1: #draw angular subdivs
170
for i in range(0, self.options.a_divs): #for each major divison
171
for j in range(1, self.options.a_subdivs): #draw the subdivisions
172
angle = i*dtheta-j*dtheta/self.options.a_subdivs+pi/2.0 # the angle of the subdivion line
173
draw_SVG_line(dr*self.options.a_subdivs_cent*sin(angle),
174
dr*self.options.a_subdivs_cent*cos(angle),
175
rmax*sin(angle), rmax*cos(angle),
176
self.options.a_subdivs_th, 'RadialMinorGridline'+str(i), grid)
178
if self.options.c_dot_dia <> 0: #if a non-zero diameter, draw the centre dot
179
draw_SVG_circle(self.options.c_dot_dia /2.0,
180
0, 0, 0, '#000000', 'CentreDot', grid)
182
if self.options.a_labels == 'deg':
183
label_radius = rmax+self.options.a_label_outset #radius of label centres
184
label_size = self.options.a_label_size
185
numeral_size = 0.73*label_size #numerals appear to be 0.73 the height of the nominal pixel size of the font in "Sans"
187
for i in range(0, self.options.a_divs):#self.options.a_divs): #radial line labels
188
draw_SVG_label_centred(sin(i*dtheta+pi/2.0)*label_radius, #0 at the RHS, mathematical style
189
cos(i*dtheta+pi/2.0)*label_radius+ numeral_size/2.0, #centre the text vertically
190
str(i*360/self.options.a_divs),
191
label_size, 'Label'+str(i), grid)
193
if __name__ == '__main__':
198
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99