Code

Prune initial timer work.
[inkscape.git] / share / extensions / dimension.py
1 #!/usr/bin/env python 
2 '''
3 dimension.py
4 An Inkscape effect for adding CAD style dimensions to selected objects
5 in a drawing.
7 It uses the selection's bounding box, so if the bounding box has empty
8 space in the x- or y-direction (such as with some stars) the results
9 will look strange.  Strokes might also overlap the edge of the 
10 bounding box.
12 The dimension arrows aren't measured: use the "Visualize Path/Measure
13 Path" effect to add measurements.
15 This code contains snippets from existing effects in the Inkscape
16 extensions library, and marker data from markers.svg.
18 Copyright (C) 2007 Peter Lewerin, peter.lewerin@tele2.se
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 2 of the License, or
23 (at your option) any later version.
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 GNU General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33 '''
35 import sys, inkex, pathmodifier
36 from simpletransform import *
37 import gettext
38 _ = gettext.gettext
40 try:
41     from subprocess import Popen, PIPE
42     bsubprocess = True
43 except:
44     bsubprocess = False
46 class Dimension(pathmodifier.PathModifier):
47     def __init__(self):
48         inkex.Effect.__init__(self)
49         self.OptionParser.add_option("-x", "--xoffset",
50                         action="store", type="float", 
51                         dest="xoffset", default=100.0,
52                         help="x offset of the vertical dimension arrow")    
53         self.OptionParser.add_option("-y", "--yoffset",
54                         action="store", type="float", 
55                         dest="yoffset", default=100.0,
56                         help="y offset of the horizontal dimension arrow")    
57         self.OptionParser.add_option("-t", "--type",
58                         action="store", type="string", 
59                         dest="type", default="geometric",
60                         help="Bounding box type")
62     def addMarker(self, name, rotate):
63         defs = self.xpathSingle('/svg:svg//svg:defs')
64         if defs == None:
65             defs = inkex.etree.SubElement(self.document.getroot(),inkex.addNS('defs','svg'))
66         marker = inkex.etree.SubElement(defs ,inkex.addNS('marker','svg'))
67         marker.set('id', name)
68         marker.set('orient', 'auto')
69         marker.set('refX', '0.0')
70         marker.set('refY', '0.0')
71         marker.set('style', 'overflow:visible')
72         marker.set(inkex.addNS('stockid','inkscape'), name)
74         arrow = inkex.etree.Element("path")
75         arrow.set('d', 'M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z ')
76         if rotate:
77             arrow.set('transform', 'scale(0.8) rotate(180) translate(12.5,0)')
78         else:
79             arrow.set('transform', 'scale(0.8) translate(12.5,0)')
80         arrow.set('style', 'fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none')
81         marker.append(arrow)
83     def dimHLine(self, y, xlat):
84         line = inkex.etree.Element("path")
85         x1 = self.bbox[0] - xlat[0] * self.xoffset
86         x2 = self.bbox[1]
87         y = y - xlat[1] * self.yoffset
88         line.set('d', 'M %f %f H %f' % (x1, y, x2))
89         return line
91     def dimVLine(self, x, xlat):
92         line = inkex.etree.Element("path")
93         x = x - xlat[0] * self.xoffset
94         y1 = self.bbox[2] - xlat[1] * self.yoffset
95         y2 = self.bbox[3]
96         line.set('d', 'M %f %f V %f' % (x, y1, y2))
97         return line
99     def effect(self):
100         self.xoffset = self.options.xoffset
101         self.yoffset = self.options.yoffset
103         # query inkscape about the bounding box
104         if len(self.options.ids) == 0:
105             inkex.errormsg(_("Please select an object."))
106             exit()
107         if self.options.type == "geometric":
108             self.bbox = computeBBox(self.selected.values())
109         else:
110             q = {'x':0,'y':0,'width':0,'height':0}
111             file = self.args[-1]
112             id = self.options.ids[0]
113             for query in q.keys():
114                 if bsubprocess:
115                     p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE)
116                     rc = p.wait()
117                     q[query] = float(p.stdout.read())
118                     err = p.stderr.read()
119                 else:
120                     f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:]
121                     q[query] = float(f.read())
122                     f.close()
123                     err.close()
124             self.bbox = (q['x'], q['x']+q['width'], q['y'], q['y']+q['height'])
126         # Avoid ugly failure on rects and texts.
127         try:
128             testing_the_water = self.bbox[0]
129         except TypeError:
130             sys.exit(_('Unable to process this object.  Try changing it into a path first.'))
132         layer = self.current_layer
134         self.addMarker('Arrow1Lstart', False)
135         self.addMarker('Arrow1Lend',  True)
137         group = inkex.etree.SubElement(layer, 'g')
138         # group = inkex.etree.Element("g")
139         group.set('fill', 'none')
140         group.set('stroke', 'black')
142         line = self.dimHLine(self.bbox[2], [0, 1])
143         line.set('marker-start', 'url(#Arrow1Lstart)')
144         line.set('marker-end', 'url(#Arrow1Lend)')
145         line.set('stroke-width', '1')
146         group.append(line)
148         line = self.dimVLine(self.bbox[0], [0, 2])
149         line.set('stroke-width', '0.5')
150         group.append(line)
151         
152         line = self.dimVLine(self.bbox[1], [0, 2])
153         line.set('stroke-width', '0.5')
154         group.append(line)
155         
156         line = self.dimVLine(self.bbox[0], [1, 0])
157         line.set('marker-start', 'url(#Arrow1Lstart)')
158         line.set('marker-end', 'url(#Arrow1Lend)')
159         line.set('stroke-width', '1')
160         group.append(line)
161         
162         line = self.dimHLine(self.bbox[2], [2, 0])
163         line.set('stroke-width', '0.5')
164         group.append(line)
166         line = self.dimHLine(self.bbox[3], [2, 0])
167         line.set('stroke-width', '0.5')
168         group.append(line)
170         for id, node in self.selected.iteritems():
171             group.append(node)
172         
173         layer.append(group)
175 if __name__ == '__main__':
176     e = Dimension()
177     e.affect()
180 # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99