Code

adding an effect to flatten curves by breaking them into sufficiently flat line segments
authoracspike <acspike@users.sourceforge.net>
Sat, 25 Feb 2006 14:24:59 +0000 (14:24 +0000)
committeracspike <acspike@users.sourceforge.net>
Sat, 25 Feb 2006 14:24:59 +0000 (14:24 +0000)
share/extensions/cspsubdiv.py [new file with mode: 0644]
share/extensions/ffgeom.py
share/extensions/ffproc.py
share/extensions/flatten.inx [new file with mode: 0644]
share/extensions/flatten.py [new file with mode: 0755]

diff --git a/share/extensions/cspsubdiv.py b/share/extensions/cspsubdiv.py
new file mode 100644 (file)
index 0000000..acf873a
--- /dev/null
@@ -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)
+               
index 1e363c7627a0855a55ba1aa37af37718105c3d13..ab2c74b74c46767577c24aa817fbedb3f96f0e5a 100755 (executable)
@@ -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()
index 7eb6f2dd1b3463f87194e45a9924e2071a4019f0..e5c726ced77e6401fe2273b2c6dfa693d7c939c4 100755 (executable)
@@ -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 (file)
index 0000000..1548437
--- /dev/null
@@ -0,0 +1,16 @@
+<inkscape-extension>
+   <_name>Flatten Bezier</_name>
+   <id>org.ekips.filter.flatten</id>
+       <dependency type="executable" location="extensions">flatten.py</dependency>
+       <dependency type="executable" location="extensions">inkex.py</dependency>
+       <param name="flatness" type="float" min="0.0" max="1000.0" _gui-text="Flatness">10.0</param>
+   <effect>
+               <object-type>path</object-type>
+                <effects-menu>
+                    <submenu _name="Modify Path"/>
+                </effects-menu>
+   </effect>
+   <script>
+       <command reldir="extensions" interpreter="python">flatten.py</command>
+   </script>
+</inkscape-extension>
diff --git a/share/extensions/flatten.py b/share/extensions/flatten.py
new file mode 100755 (executable)
index 0000000..b33591e
--- /dev/null
@@ -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()