From fce8f6cbcb0de779d18d91619bd08667829d57a4 Mon Sep 17 00:00:00 2001 From: acspike Date: Sat, 25 Feb 2006 14:24:59 +0000 Subject: [PATCH] adding an effect to flatten curves by breaking them into sufficiently flat line segments --- share/extensions/cspsubdiv.py | 39 +++++++++++++++++++++++++++++ share/extensions/ffgeom.py | 11 +++++++++ share/extensions/ffproc.py | 2 +- share/extensions/flatten.inx | 16 ++++++++++++ share/extensions/flatten.py | 46 +++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 share/extensions/cspsubdiv.py create mode 100644 share/extensions/flatten.inx create mode 100755 share/extensions/flatten.py diff --git a/share/extensions/cspsubdiv.py b/share/extensions/cspsubdiv.py new file mode 100644 index 000000000..acf873ae1 --- /dev/null +++ b/share/extensions/cspsubdiv.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +from bezmisc import * +from ffgeom import * + +def maxdist(((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y))): + p0 = Point(p0x,p0y) + p1 = Point(p1x,p1y) + p2 = Point(p2x,p2y) + p3 = Point(p3x,p3y) + + s1 = Segment(p0,p3) + return max(s1.distanceToPoint(p1),s1.distanceToPoint(p2)) + + +def cspsubdiv(csp,flat): + for sp in csp: + subdiv(sp,flat) + +def subdiv(sp,flat,i=1): + p0 = sp[i-1][1] + p1 = sp[i-1][2] + p2 = sp[i][0] + p3 = sp[i][1] + + b = (p0,p1,p2,p3) + m = maxdist(b) + if m <= flat: + try: + subdiv(sp,flat,i+1) + except IndexError: + pass + else: + one, two = beziersplitatt(b,0.5) + sp[i-1][2] = one[1] + sp[i][0] = two[2] + p = [one[2],one[3],two[1]] + sp[i:1] = [p] + subdiv(sp,flat,i) + diff --git a/share/extensions/ffgeom.py b/share/extensions/ffgeom.py index 1e363c762..ab2c74b74 100755 --- a/share/extensions/ffgeom.py +++ b/share/extensions/ffgeom.py @@ -78,6 +78,15 @@ class Segment: return self[1]['y'] - (self[0]['x'] * self.slope()) return NaN def distanceToPoint(self, p): + s2 = Segment(self[0],p) + c1 = dot(s2,self) + if c1 <= 0: + return Segment(p,self[0]).length() + c2 = dot(self,self) + if c2 <= c1: + return Segment(p,self[1]).length() + return self.perpDistanceToPoint(p) + def perpDistanceToPoint(self, p): len = self.length() if len == 0: return NaN return math.fabs(((self[1]['x'] - self[0]['x']) * (self[0]['y'] - p['y'])) - \ @@ -125,3 +134,5 @@ def intersectSegments(s1, s2): return Point(x, y) return Point(NaN, NaN) +def dot(s1, s2): + return s1.delta_x() * s2.delta_x() + s1.delta_y() * s2.delta_y() diff --git a/share/extensions/ffproc.py b/share/extensions/ffproc.py index 7eb6f2dd1..e5c726ced 100755 --- a/share/extensions/ffproc.py +++ b/share/extensions/ffproc.py @@ -37,7 +37,7 @@ def FindFrets(strings, meta, scale, tuning, numfrets): Point((nut[1]['x']+nut[0]['x'])/2.0,(nut[1]['y']+nut[0]['y'])/2.0), Point((bridge[1]['x']+bridge[0]['x'])/2.0,(bridge[1]['y']+bridge[0]['y'])/2.0)) for s in strings: - if nut.distanceToPoint(s[0])>=threshold or bridge.distanceToPoint(s[1])>=threshold: + if nut.perpDistanceToPoint(s[0])>=threshold or bridge.perpDistanceToPoint(s[1])>=threshold: doPartials = False break diff --git a/share/extensions/flatten.inx b/share/extensions/flatten.inx new file mode 100644 index 000000000..1548437f2 --- /dev/null +++ b/share/extensions/flatten.inx @@ -0,0 +1,16 @@ + + <_name>Flatten Bezier + org.ekips.filter.flatten + flatten.py + inkex.py + 10.0 + + path + + + + + + diff --git a/share/extensions/flatten.py b/share/extensions/flatten.py new file mode 100755 index 000000000..b33591e04 --- /dev/null +++ b/share/extensions/flatten.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +''' +Copyright (C) 2006 Aaron Spike, aaron@ekips.org + +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +''' +import inkex, cubicsuperpath, simplepath, cspsubdiv + +class MyEffect(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.OptionParser.add_option("-f", "--flatness", + action="store", type="float", + dest="flat", default=10.0, + help="Minimum flatness of the subdivided curves") + def effect(self): + for id, node in self.selected.iteritems(): + if node.tagName == 'path': + d = node.attributes.getNamedItem('d') + p = cubicsuperpath.parsePath(d.value) + cspsubdiv.cspsubdiv(p, self.options.flat) + np = [] + for sp in p: + first = True + for csp in sp: + cmd = 'L' + if first: + cmd = 'M' + first = False + np.append([cmd,[csp[1][0],csp[1][1]]]) + d.value = simplepath.formatPath(np) + +e = MyEffect() +e.affect() -- 2.30.2