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