Code

noop: Add vim modeline for all share/extensions/*.py files that use four-space indent...
[inkscape.git] / share / extensions / grid_cartesian.py
1 #!/usr/bin/env python 
2 '''
3 Copyright (C) 2007 John Beard john.j.beard@gmail.com
5 ##This extension allows you to draw a Cartesian grid in Inkscape.
6 ##There is a wide range of options including subdivision, subsubdivions
7 ## and logarithmic scales. Custom line widths are also possible.
8 ##All elements are grouped with similar elements (eg all x-subdivs)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 '''
25 import inkex
26 import simplestyle, sys
27 from math import *
29 def draw_SVG_line(x1, y1, x2, y2, width, name, parent):
30     style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill': 'none' }
31     line_attribs = {'style':simplestyle.formatStyle(style),
32                     inkex.addNS('label','inkscape'):name,
33                     'd':'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)}
34     inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs )
35     
36 def draw_SVG_rect(x,y,w,h, width, fill, name, parent):
37     style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill':fill}
38     rect_attribs = {'style':simplestyle.formatStyle(style),
39                     inkex.addNS('label','inkscape'):name,
40                     'x':str(x), 'y':str(y), 'width':str(w), 'height':str(h)}
41     inkex.etree.SubElement(parent, inkex.addNS('rect','svg'), rect_attribs )
43 class Grid_Polar(inkex.Effect):
44     def __init__(self):
45         inkex.Effect.__init__(self)
46         self.OptionParser.add_option("--x_divs",
47                         action="store", type="int", 
48                         dest="x_divs", default=5,
49                         help="Major X Divisions")
50         self.OptionParser.add_option("--dx",
51                         action="store", type="float", 
52                         dest="dx", default=100.0,
53                         help="Major X divison Spacing")
54         self.OptionParser.add_option("--x_subdivs",
55                         action="store", type="int", 
56                         dest="x_subdivs", default=2,
57                         help="Subdivisions per Major X division")
58         self.OptionParser.add_option("--x_log",
59                         action="store", type="inkbool", 
60                         dest="x_log", default=False,
61                         help="Logarithmic x subdivisions if true")
62         self.OptionParser.add_option("--x_subsubdivs",
63                         action="store", type="int", 
64                         dest="x_subsubdivs", default=5,
65                         help="Subsubdivisions per Minor X division")
66         self.OptionParser.add_option("--x_half_freq",
67                         action="store", type="int", 
68                         dest="x_half_freq", default=4,
69                         help="Halve Subsubdiv. Frequency after 'n' Subdivs. (log only)")
70         self.OptionParser.add_option("--x_divs_th",
71                         action="store", type="float", 
72                         dest="x_divs_th", default=2,
73                         help="Major X Division Line thickness")
74         self.OptionParser.add_option("--x_subdivs_th",
75                         action="store", type="float", 
76                         dest="x_subdivs_th", default=1,
77                         help="Minor X Division Line thickness")
78         self.OptionParser.add_option("--x_subsubdivs_th",
79                         action="store", type="float", 
80                         dest="x_subsubdivs_th", default=1,
81                         help="Subminor X Division Line thickness")
82         self.OptionParser.add_option("--y_divs",
83                         action="store", type="int", 
84                         dest="y_divs", default=6,
85                         help="Major Y Divisions")
86         self.OptionParser.add_option("--dy",
87                         action="store", type="float", 
88                         dest="dy", default=100.0,
89                         help="Major Gridline Increment")
90         self.OptionParser.add_option("--y_subdivs",
91                         action="store", type="int", 
92                         dest="y_subdivs", default=2,
93                         help="Minor Divisions per Major Y division")
94         self.OptionParser.add_option("--y_log",
95                         action="store", type="inkbool", 
96                         dest="y_log", default=False,
97                         help="Logarithmic y subdivisions if true")
98         self.OptionParser.add_option("--y_subsubdivs",
99                         action="store", type="int", 
100                         dest="y_subsubdivs", default=5,
101                         help="Subsubdivisions per Minor Y division")
102         self.OptionParser.add_option("--y_half_freq",
103                         action="store", type="int", 
104                         dest="y_half_freq", default=4,
105                         help="Halve Y Subsubdiv. Frequency after 'n' Subdivs. (log only)")
106         self.OptionParser.add_option("--y_divs_th",
107                         action="store", type="float", 
108                         dest="y_divs_th", default=2,
109                         help="Major Y Division Line thickness")
110         self.OptionParser.add_option("--y_subdivs_th",
111                         action="store", type="float", 
112                         dest="y_subdivs_th", default=1,
113                         help="Minor Y Division Line thickness")
114         self.OptionParser.add_option("--y_subsubdivs_th",
115                         action="store", type="float", 
116                         dest="y_subsubdivs_th", default=1,
117                         help="Subminor Y Division Line thickness")
118         self.OptionParser.add_option("--border_th",
119                         action="store", type="float", 
120                         dest="border_th", default=3,
121                         help="Border Line thickness")
124     def effect(self):
125         
126         #find the pixel dimensions of the overall grid
127         ymax = self.options.dy * self.options.y_divs
128         xmax = self.options.dx * self.options.x_divs
129         
130         # Embed grid in group
131         #Put in in the centre of the current view
132         t = 'translate(' + str( self.view_center[0]- xmax/2.0) + ',' + \
133                            str( self.view_center[1]- ymax/2.0) + ')'
134         g_attribs = {inkex.addNS('label','inkscape'):'Grid_Polar:X' + \
135                      str( self.options.x_divs )+':Y'+str( self.options.y_divs ),
136                      'transform':t }
137         grid = inkex.etree.SubElement(self.current_layer, 'g', g_attribs)
138         
139         #Group for major x gridlines
140         g_attribs = {inkex.addNS('label','inkscape'):'MajorXGridlines'}
141         majglx = inkex.etree.SubElement(grid, 'g', g_attribs)
143         #Group for major y gridlines
144         g_attribs = {inkex.addNS('label','inkscape'):'MajorYGridlines'}
145         majgly = inkex.etree.SubElement(grid, 'g', g_attribs)
146         
147         #Group for minor x gridlines
148         if self.options.x_subdivs > 1:#if there are any minor x gridlines
149             g_attribs = {inkex.addNS('label','inkscape'):'MinorXGridlines'}
150             minglx = inkex.etree.SubElement(grid, 'g', g_attribs)
151         
152         #Group for subminor x gridlines
153         if self.options.x_subsubdivs > 1:#if there are any minor minor x gridlines
154             g_attribs = {inkex.addNS('label','inkscape'):'SubMinorXGridlines'}
155             mminglx = inkex.etree.SubElement(grid, 'g', g_attribs)
156         
157         #Group for minor y gridlines
158         if self.options.y_subdivs > 1:#if there are any minor y gridlines
159             g_attribs = {inkex.addNS('label','inkscape'):'MinorYGridlines'}
160             mingly = inkex.etree.SubElement(grid, 'g', g_attribs)
161         
162         #Group for subminor y gridlines
163         if self.options.y_subsubdivs > 1:#if there are any minor minor x gridlines
164             g_attribs = {inkex.addNS('label','inkscape'):'SubMinorYGridlines'}
165             mmingly = inkex.etree.SubElement(grid, 'g', g_attribs)
167             
168         draw_SVG_rect(0, 0, xmax, ymax, self.options.border_th,
169                       'none', 'Border', grid) #border rectangle
170         
171         #DO THE X DIVISONS======================================
172         sd  = self.options.x_subdivs #sub divs per div
173         ssd = self.options.x_subsubdivs #subsubdivs per subdiv
174         
175         for i in range(0, self.options.x_divs): #Major x divisons
176             if i>0: #dont draw first line (we made a proper border)
177                 draw_SVG_line(self.options.dx*i, 0,
178                               self.options.dx*i,ymax,
179                               self.options.x_divs_th,
180                               'MajorXDiv'+str(i), majglx)
181             
182             if self.options.x_log: #log x subdivs
183                 for j in range (1, sd):
184                     if j>1: #the first loop is only for subsubdivs
185                         draw_SVG_line(self.options.dx*(i+log(j, sd)), 0,
186                                       self.options.dx*(i+log(j, sd)), ymax,
187                                       self.options.x_subdivs_th,
188                                       'MinorXDiv'+str(i)+':'+str(j), minglx)
189                                   
190                     for k in range (1, ssd): #subsub divs
191                         if (j <= self.options.x_half_freq) or (k%2 == 0):#only draw half the subsubdivs past the half-freq point
192                             if (ssd%2 > 0) and (j > self.options.y_half_freq): #half frequency won't work with odd numbers of subsubdivs,
193                                 ssd2 = ssd+1 #make even
194                             else:
195                                 ssd2 = ssd #no change
196                             draw_SVG_line(self.options.dx*(i+log(j+k/float(ssd2),sd )), 0,
197                                           self.options.dx*(i+log(j+k/float(ssd2),sd )), ymax,
198                                           self.options.x_subsubdivs_th,'SubminorXDiv'+str(i)+':'+str(j)+':'+str(k), mminglx)
199             
200             else: #linear x subdivs
201                 for j in range (0, sd):
202                     if j>0: #not for the first loop (this loop is for the subsubdivs before the first subdiv)
203                         draw_SVG_line(self.options.dx*(i+j/float(sd)), 0,
204                                       self.options.dx*(i+j/float(sd)), ymax,
205                                       self.options.x_subdivs_th,
206                                       'MinorXDiv'+str(i)+':'+str(j), minglx)
207                     
208                     for k in range (1, ssd): #subsub divs
209                         draw_SVG_line(self.options.dx*(i+(j*ssd+k)/((float(sd)*ssd))) , 0,
210                                       self.options.dx*(i+(j*ssd+k)/((float(sd)*ssd))) , ymax,
211                                       self.options.x_subsubdivs_th,
212                                       'SubminorXDiv'+str(i)+':'+str(j)+':'+str(k), mminglx)
213          
214         #DO THE Y DIVISONS========================================
215         sd  = self.options.y_subdivs    #sub divs per div
216         ssd = self.options.y_subsubdivs #subsubdivs per subdiv
217                                       
218         for i in range(0, self.options.y_divs): #Major y divisons
219             if i>0:#dont draw first line (we will make a border)
220                 draw_SVG_line(0, self.options.dy*i,
221                               xmax, self.options.dy*i,
222                               self.options.y_divs_th,
223                               'MajorYDiv'+str(i), majgly)
224             
225             if self.options.y_log: #log y subdivs
226                 for j in range (1, sd):
227                     if j>1: #the first loop is only for subsubdivs
228                         draw_SVG_line(0,    self.options.dy*(i+1-log(j,sd)),
229                                       xmax, self.options.dy*(i+1-log(j,sd)),
230                                       self.options.y_subdivs_th,
231                                       'MinorXDiv'+str(i)+':'+str(j), mingly)
232                     
233                     for k in range (1, ssd): #subsub divs
234                         if (j <= self.options.y_half_freq) or (k%2 == 0):#only draw half the subsubdivs past the half-freq point
235                             if (ssd%2 > 0) and (j > self.options.y_half_freq): #half frequency won't work with odd numbers of subsubdivs,
236                                 ssd2 = ssd+1
237                             else:
238                                 ssd2 = ssd #no change
239                             draw_SVG_line(0,    self.options.dx*(i+1-log(j+k/float(ssd2),sd )),
240                                           xmax, self.options.dx*(i+1-log(j+k/float(ssd2),sd )),
241                                           self.options.y_subsubdivs_th,
242                                           'SubminorXDiv'+str(i)+':'+str(j)+':'+str(k), mmingly)
243             else: #linear y subdivs
244                 for j in range (0, self.options.y_subdivs):
245                     if j>0:#not for the first loop (this loop is for the subsubdivs before the first subdiv)
246                         draw_SVG_line(0,    self.options.dy*(i+j/float(sd)),
247                                       xmax, self.options.dy*(i+j/float(sd)),
248                                       self.options.y_subdivs_th,
249                                       'MinorXYiv'+str(i)+':'+str(j), mingly)
250                     
251                     for k in range (1, ssd): #subsub divs
252                         draw_SVG_line(0,    self.options.dy*(i+(j*ssd+k)/((float(sd)*ssd))),
253                                       xmax, self.options.dy*(i+(j*ssd+k)/((float(sd)*ssd))),
254                                       self.options.y_subsubdivs_th,
255                                       'SubminorXDiv'+str(i)+':'+str(j)+':'+str(k), mmingly)
259 e = Grid_Polar()
260 e.affect()
263 # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99