1#!/usr/local/bin/python3.8 2# coding=utf-8 3# 4# Copyright (C) 2007 Peter Lewerin, peter.lewerin@tele2.se 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; if not, write to the Free Software 18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19# 20""" 21An Inkscape effect for adding CAD style dimensions to selected objects 22in a drawing. 23 24It uses the selection's bounding box, so if the bounding box has empty 25space in the x- or y-direction (such as with some stars) the results 26will look strange. Strokes might also overlap the edge of the 27bounding box. 28 29The dimension arrows aren't measured: use the "Visualize Path/Measure 30Path" effect to add measurements. 31 32This code contains snippets from existing effects in the Inkscape 33extensions library, and marker data from markers.svg. 34""" 35 36import inkex 37from inkex import Group, Marker, PathElement 38 39import pathmodifier 40 41class Dimension(pathmodifier.PathModifier): 42 """Add dimensions as a path modifier""" 43 def add_arguments(self, pars): 44 pars.add_argument("--xoffset", type=float, default=100.0,\ 45 help="x offset of the vertical dimension arrow") 46 pars.add_argument("--yoffset", type=float, default=100.0,\ 47 help="y offset of the horizontal dimension arrow") 48 pars.add_argument("--type", default="geometric", help="Bounding box type") 49 50 def add_marker(self, name, rotate): 51 """Create a marker in the defs of the svg""" 52 marker = Marker() 53 marker.set('id', name) 54 marker.set('orient', 'auto') 55 marker.set('refX', '0.0') 56 marker.set('refY', '0.0') 57 marker.set('style', 'overflow:visible') 58 marker.set('inkscape:stockid', name) 59 self.svg.defs.append(marker) 60 61 arrow = PathElement(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 ') 62 if rotate: 63 arrow.set('transform', 'scale(0.8) rotate(180) translate(12.5,0)') 64 else: 65 arrow.set('transform', 'scale(0.8) translate(12.5,0)') 66 arrow.set('style', 'fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none') 67 marker.append(arrow) 68 69 def horz_line(self, y, xlat, bbox): 70 """Create a horzontal line""" 71 line = PathElement() 72 x1 = bbox.left - xlat[0] * self.options.xoffset 73 x2 = bbox.right 74 y1 = y - xlat[1] * self.options.yoffset 75 line.set('d', 'M %f %f H %f' % (x1, y1, x2)) 76 return line 77 78 def vert_line(self, x, xlat, bbox): 79 """Create a vertical line""" 80 line = PathElement() 81 x = x - xlat[0] * self.options.xoffset 82 y1 = bbox.top - xlat[1] * self.options.yoffset 83 y2 = bbox.bottom 84 line.set('d', 'M %f %f V %f' % (x, y1, y2)) 85 return line 86 87 def effect(self): 88 scale = self.svg.unittouu('1px') # convert to document units 89 self.options.xoffset *= scale 90 self.options.yoffset *= scale 91 92 if not self.svg.selected: 93 raise inkex.AbortExtension("Please select an object") 94 if self.options.type == "geometric": 95 bbox = self.svg.selection.bounding_box() 96 else: 97 bbox = self.svg.selection.first().bounding_box() 98 99 layer = self.svg.get_current_layer() 100 101 self.add_marker('Arrow1Lstart', False) 102 self.add_marker('Arrow1Lend', True) 103 104 group = Group() 105 layer.append(group) 106 group.set('fill', 'none') 107 group.set('stroke', 'black') 108 109 line = self.horz_line(bbox.top, [0, 1], bbox) 110 line.set('marker-start', 'url(#Arrow1Lstart)') 111 line.set('marker-end', 'url(#Arrow1Lend)') 112 line.set('stroke-width', str(scale)) 113 group.append(line) 114 115 line = self.vert_line(bbox.left, [0, 2], bbox) 116 line.set('stroke-width', str(0.5 * scale)) 117 group.append(line) 118 119 line = self.vert_line(bbox.right, [0, 2], bbox) 120 line.set('stroke-width', str(0.5 * scale)) 121 group.append(line) 122 123 line = self.vert_line(bbox.left, [1, 0], bbox) 124 line.set('marker-start', 'url(#Arrow1Lstart)') 125 line.set('marker-end', 'url(#Arrow1Lend)') 126 line.set('stroke-width', str(scale)) 127 group.append(line) 128 129 line = self.horz_line(bbox.top, [2, 0], bbox) 130 line.set('stroke-width', str(0.5 * scale)) 131 group.append(line) 132 133 line = self.horz_line(bbox.bottom, [2, 0], bbox) 134 line.set('stroke-width', str(0.5 * scale)) 135 group.append(line) 136 137 for node in self.svg.selected.values(): 138 group.append(node) 139 140 layer.append(group) 141 return None 142 143 144if __name__ == '__main__': 145 Dimension().run() 146