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 class Dimension(pathmodifier.PathModifier):
41 def __init__(self):
42 inkex.Effect.__init__(self)
43 self.OptionParser.add_option("-x", "--xoffset",
44 action="store", type="float",
45 dest="xoffset", default=100.0,
46 help="x offset of the vertical dimension arrow")
47 self.OptionParser.add_option("-y", "--yoffset",
48 action="store", type="float",
49 dest="yoffset", default=100.0,
50 help="y offset of the horizontal dimension arrow")
52 def addMarker(self, name, rotate):
53 defs = self.xpathSingle('/svg:svg//svg:defs')
54 if defs == None:
55 defs = inkex.etree.SubElement(self.document.getroot(),inkex.addNS('defs','svg'))
56 marker = inkex.etree.SubElement(defs ,inkex.addNS('marker','svg'))
57 marker.set('id', name)
58 marker.set('orient', 'auto')
59 marker.set('refX', '0.0')
60 marker.set('refY', '0.0')
61 marker.set('style', 'overflow:visible')
62 marker.set(inkex.addNS('stockid','inkscape'), name)
64 arrow = inkex.etree.Element("path")
65 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 ')
66 if rotate:
67 arrow.set('transform', 'scale(0.8) rotate(180) translate(12.5,0)')
68 else:
69 arrow.set('transform', 'scale(0.8) translate(12.5,0)')
70 arrow.set('style', 'fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none')
71 marker.append(arrow)
73 def dimHLine(self, y, xlat):
74 line = inkex.etree.Element("path")
75 x1 = self.bbox[0] - xlat[0] * self.xoffset
76 x2 = self.bbox[1]
77 y = y - xlat[1] * self.yoffset
78 line.set('d', 'M %f %f H %f' % (x1, y, x2))
79 return line
81 def dimVLine(self, x, xlat):
82 line = inkex.etree.Element("path")
83 x = x - xlat[0] * self.xoffset
84 y1 = self.bbox[2] - xlat[1] * self.yoffset
85 y2 = self.bbox[3]
86 line.set('d', 'M %f %f V %f' % (x, y1, y2))
87 return line
89 def effect(self):
90 self.xoffset = self.options.xoffset
91 self.yoffset = self.options.yoffset
93 self.bbox = computeBBox(self.selected.values())
95 # Avoid ugly failure on rects and texts.
96 try:
97 testing_the_water = self.bbox[0]
98 except TypeError:
99 sys.exit(_('Unable to process this object. Try changing it into a path first.'))
101 layer = self.current_layer
103 self.addMarker('Arrow1Lstart', False)
104 self.addMarker('Arrow1Lend', True)
106 group = inkex.etree.Element("g")
107 group.set('fill', 'none')
108 group.set('stroke', 'black')
110 line = self.dimHLine(self.bbox[2], [0, 1])
111 line.set('marker-start', 'url(#Arrow1Lstart)')
112 line.set('marker-end', 'url(#Arrow1Lend)')
113 line.set('stroke-width', '1')
114 group.append(line)
116 line = self.dimVLine(self.bbox[0], [0, 2])
117 line.set('stroke-width', '0.5')
118 group.append(line)
120 line = self.dimVLine(self.bbox[1], [0, 2])
121 line.set('stroke-width', '0.5')
122 group.append(line)
124 line = self.dimVLine(self.bbox[0], [1, 0])
125 line.set('marker-start', 'url(#Arrow1Lstart)')
126 line.set('marker-end', 'url(#Arrow1Lend)')
127 line.set('stroke-width', '1')
128 group.append(line)
130 line = self.dimHLine(self.bbox[2], [2, 0])
131 line.set('stroke-width', '0.5')
132 group.append(line)
134 line = self.dimHLine(self.bbox[3], [2, 0])
135 line.set('stroke-width', '0.5')
136 group.append(line)
138 for id, node in self.selected.iteritems():
139 group.append(node)
141 layer.append(group)
143 if __name__ == '__main__':
144 e = Dimension()
145 e.affect()
148 # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99