From e277736a64d0dfc4dba152258dc512f6ad710ba3 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Tue, 20 Jul 2010 19:00:21 -0400 Subject: [PATCH] fix Bug 308204, add Visual bbox option --- share/extensions/dimension.inx | 24 ++++++++++------- share/extensions/dimension.py | 36 +++++++++++++++++++++++-- share/extensions/simpletransform.py | 41 ++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/share/extensions/dimension.inx b/share/extensions/dimension.inx index 114a3688e..cce244d4a 100644 --- a/share/extensions/dimension.inx +++ b/share/extensions/dimension.inx @@ -1,19 +1,23 @@ - <_name>Dimensions - se.lewerin.filter.dimension + <_name>Dimensions + se.lewerin.filter.dimension dimension.py inkex.py pathmodifier.py 50 50 - + + <_option value="geometric">Geometric + <_option value="visual">Visual + + path - - - - - + + + + + diff --git a/share/extensions/dimension.py b/share/extensions/dimension.py index cda3a96fd..1b84642ea 100644 --- a/share/extensions/dimension.py +++ b/share/extensions/dimension.py @@ -37,6 +37,12 @@ from simpletransform import * import gettext _ = gettext.gettext +try: + from subprocess import Popen, PIPE + bsubprocess = True +except: + bsubprocess = False + class Dimension(pathmodifier.PathModifier): def __init__(self): inkex.Effect.__init__(self) @@ -48,6 +54,10 @@ class Dimension(pathmodifier.PathModifier): action="store", type="float", dest="yoffset", default=100.0, help="y offset of the horizontal dimension arrow") + self.OptionParser.add_option("-t", "--type", + action="store", type="string", + dest="type", default="geometric", + help="Bounding box type") def addMarker(self, name, rotate): defs = self.xpathSingle('/svg:svg//svg:defs') @@ -90,7 +100,28 @@ class Dimension(pathmodifier.PathModifier): self.xoffset = self.options.xoffset self.yoffset = self.options.yoffset - self.bbox = computeBBox(self.selected.values()) + # query inkscape about the bounding box + if len(self.options.ids) == 0: + inkex.errormsg(_("Please select an object.")) + exit() + if self.options.type == "geometric": + self.bbox = computeBBox(self.selected.values()) + else: + q = {'x':0,'y':0,'width':0,'height':0} + file = self.args[-1] + id = self.options.ids[0] + for query in q.keys(): + if bsubprocess: + p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE) + rc = p.wait() + q[query] = float(p.stdout.read()) + err = p.stderr.read() + else: + f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:] + q[query] = float(f.read()) + f.close() + err.close() + self.bbox = (q['x'], q['x']+q['width'], q['y'], q['y']+q['height']) # Avoid ugly failure on rects and texts. try: @@ -103,7 +134,8 @@ class Dimension(pathmodifier.PathModifier): self.addMarker('Arrow1Lstart', False) self.addMarker('Arrow1Lend', True) - group = inkex.etree.Element("g") + group = inkex.etree.SubElement(layer, 'g') + # group = inkex.etree.Element("g") group.set('fill', 'none') group.set('stroke', 'black') diff --git a/share/extensions/simpletransform.py b/share/extensions/simpletransform.py index c89d771ec..08aa4c55f 100644 --- a/share/extensions/simpletransform.py +++ b/share/extensions/simpletransform.py @@ -1,6 +1,7 @@ #!/usr/bin/env python ''' Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr +Copyright (C) 2010 Alvin Penner, penner@vaxxine.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -142,6 +143,44 @@ def roughBBox(path): yMax = max(yMax,pt[1]) return xmin,xMax,ymin,yMax +def refinedBBox(path): + xmin,xMax,ymin,yMax = path[0][0][1][0],path[0][0][1][0],path[0][0][1][1],path[0][0][1][1] + for pathcomp in path: + for i in range(1, len(pathcomp)): + cmin, cmax = cubicExtrema(pathcomp[i-1][1][0], pathcomp[i-1][2][0], pathcomp[i][0][0], pathcomp[i][1][0]) + xmin = min(xmin, cmin) + xMax = max(xMax, cmax) + cmin, cmax = cubicExtrema(pathcomp[i-1][1][1], pathcomp[i-1][2][1], pathcomp[i][0][1], pathcomp[i][1][1]) + ymin = min(ymin, cmin) + yMax = max(yMax, cmax) + return xmin,xMax,ymin,yMax + +def cubicExtrema(y0, y1, y2, y3): + cmin = min(y0, y3) + cmax = max(y0, y3) + d1 = y1 - y0 + d2 = y2 - y1 + d3 = y3 - y2 + if (d1 - 2*d2 + d3): + if (d2*d2 > d1*d3): + t = (d1 - d2 + math.sqrt(d2*d2 - d1*d3))/(d1 - 2*d2 + d3) + if (t > 0) and (t < 1): + y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t + cmin = min(cmin, y) + cmax = max(cmax, y) + t = (d1 - d2 - math.sqrt(d2*d2 - d1*d3))/(d1 - 2*d2 + d3) + if (t > 0) and (t < 1): + y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t + cmin = min(cmin, y) + cmax = max(cmax, y) + elif (d3 - d1): + t = -d1/(d3 - d1) + if (t > 0) and (t < 1): + y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t + cmin = min(cmin, y) + cmax = max(cmax, y) + return cmin, cmax + def computeBBox(aList,mat=[[1,0,0],[0,1,0]]): bbox=None for node in aList: @@ -179,7 +218,7 @@ def computeBBox(aList,mat=[[1,0,0],[0,1,0]]): if d is not None: p = cubicsuperpath.parsePath(d) applyTransformToPath(m,p) - bbox=boxunion(roughBBox(p),bbox) + bbox=boxunion(refinedBBox(p),bbox) elif node.tag == inkex.addNS('use','svg') or node.tag=='use': refid=node.get(inkex.addNS('href','xlink')) -- 2.30.2