From e7bafc69cc367122b93ff2659a151d2792e387a7 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Sun, 25 Apr 2010 22:57:01 -0400 Subject: [PATCH] add 'area' calculation to Measure extension --- share/extensions/measure.inx | 83 ++++++++++++++++++++---------------- share/extensions/measure.py | 49 ++++++++++++++++++++- 2 files changed, 93 insertions(+), 39 deletions(-) diff --git a/share/extensions/measure.inx b/share/extensions/measure.inx index 8f2f41159..513ff7d70 100644 --- a/share/extensions/measure.inx +++ b/share/extensions/measure.inx @@ -1,40 +1,49 @@ - <_name>Measure Path - com.njhurst.filter.measure_length - measure.py - inkex.py - - - 12 - -6 - 2 - 1 - - - - px - pt - in - ft - yd - mm - cm - m - km - - - - <_param name="measurehelp" type="description">This effect measures the length of the selected path and adds it as a text-on-path object with the selected unit. The number of significant digits can be controlled by the Precision field. The Offset field controls the distance from the text to the path. The Scale factor can be used to make measurements in scaled drawings. For example, if 1 cm in the drawing equals 2.5 m in the real world, Scale must be set to 250. - - - - path - - - - - + <_name>Measure Path + com.njhurst.filter.measure_length + measure.py + inkex.py + + + + Length + Area + + 12 + -6 + 2 + 1 + + + + px + pt + in + ft + yd + mm + cm + m + km + + + + <_param name="measurehelp" type="description" xml:space="preserve">This effect measures the length, or area, of the selected path and adds it as a text-on-path object with the selected unit. + + * The number of significant digits can be controlled by the Precision field. + * The Offset field controls the distance from the text to the path. + * The Scale factor can be used to make measurements in scaled drawings. For example, if 1 cm in the drawing equals 2.5 m in the real world, Scale must be set to 250. + * When calculating area, the result should be precise for polygons and Bezier curves. If a circle is used, the area may be too high by as much as 0.03%. + + + + path + + + + + diff --git a/share/extensions/measure.py b/share/extensions/measure.py index 68586530b..0335f3fe9 100644 --- a/share/extensions/measure.py +++ b/share/extensions/measure.py @@ -4,6 +4,7 @@ This extension module can measure arbitrary path and object length It adds a text to the selected path containing the length in a given unit. +Copyright (C) 2010 Alvin Penner Copyright (C) 2006 Georg Wiora Copyright (C) 2006 Nathan Hurst Copyright (C) 2005 Aaron Spike, aaron@ekips.org @@ -70,10 +71,33 @@ def csplength(csp): lengths[-1].append(l) total += l return lengths, total +def csparea(csp): + area = 0.0 + n0 = 0.0 + x0 = 0.0 + y0 = 0.0 + for sp in csp: + for i in range(len(sp)): # calculate polygon area + area += 0.5*sp[i-1][1][0]*(sp[i][1][1] - sp[i-2][1][1]) + if abs(sp[i-1][1][0]-sp[i][1][0]) > 0.001 or abs(sp[i-1][1][1]-sp[i][1][1]) > 0.001: + n0 += 1.0 + x0 += sp[i][1][0] + y0 += sp[i][1][1] + for i in range(1, len(sp)): # add contribution from cubic Bezier + bezarea = ( 0.0*sp[i-1][1][1] + 2.0*sp[i-1][2][1] + 1.0*sp[i][0][1] - 3.0*sp[i][1][1])*sp[i-1][1][0] + bezarea += (-2.0*sp[i-1][1][1] + 0.0*sp[i-1][2][1] + 1.0*sp[i][0][1] + 1.0*sp[i][1][1])*sp[i-1][2][0] + bezarea += (-1.0*sp[i-1][1][1] - 1.0*sp[i-1][2][1] + 0.0*sp[i][0][1] + 2.0*sp[i][1][1])*sp[i][0][0] + bezarea += ( 3.0*sp[i-1][1][1] - 1.0*sp[i-1][2][1] - 2.0*sp[i][0][1] + 0.0*sp[i][1][1])*sp[i][1][0] + area += 0.15*bezarea + return abs(area), x0/n0, y0/n0 class Length(inkex.Effect): def __init__(self): inkex.Effect.__init__(self) + self.OptionParser.add_option("--type", + action="store", type="string", + dest="type", default="length", + help="Type of measurement") self.OptionParser.add_option("-f", "--fontsize", action="store", type="int", dest="fontsize", default=20, @@ -125,11 +149,18 @@ class Length(inkex.Effect): a =[] p = cubicsuperpath.parsePath(node.get('d')) num = 1 - slengths, stotal = csplength(p) factor = 1.0/inkex.unittouu('1'+self.options.unit) + if self.options.type == "length": + slengths, stotal = csplength(p) + else: + stotal,x0,y0 = csparea(p) + stotal *= factor*self.options.scale # Format the length as string lenstr = locale.format("%(len)25."+str(prec)+"f",{'len':round(stotal*factor*self.options.scale,prec)}).strip() - self.addTextOnPath(self.group,0, 0,lenstr+' '+self.options.unit, id, self.options.offset) + if self.options.type == "length": + self.addTextOnPath(self.group,0, 0,lenstr+' '+self.options.unit, id, self.options.offset) + else: + self.addTextWithTspan(self.group,x0,y0,lenstr+' '+self.options.unit+'^2', id, self.options.offset) def addTextOnPath(self,node,x,y,text, id,dy=0): @@ -148,6 +179,20 @@ class Length(inkex.Effect): node.set('x', str(x)) node.set('y', str(y)) + def addTextWithTspan(self,node,x,y,text,id,dy=0): + new = inkex.etree.SubElement(node,inkex.addNS('tspan','svg'), {inkex.addNS('role','sodipodi'): 'line'}) + s = {'text-align': 'center', 'vertical-align': 'bottom', + 'text-anchor': 'middle', 'font-size': str(self.options.fontsize), + 'fill-opacity': '1.0', 'stroke': 'none', + 'font-weight': 'normal', 'font-style': 'normal', 'fill': '#000000'} + new.set('style', simplestyle.formatStyle(s)) + new.set(inkex.addNS('href','xlink'), '#'+id) + new.set('startOffset', "50%") + new.set('dy', str(dy)) + new.text = str(text) + node.set('x', str(x)) + node.set('y', str(y)) + if __name__ == '__main__': e = Length() e.affect() -- 2.30.2