~vaifrax/inkscape/bugfix170049

« back to all changes in this revision

Viewing changes to share/extensions/wavy.py

  • Committer: mental
  • Date: 2006-01-16 02:36:01 UTC
  • Revision ID: mental@users.sourceforge.net-20060116023601-wkr0h7edl5veyudq
moving trunk for module inkscape

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python 
 
2
'''
 
3
Copyright (C) 2005 Aaron Spike, aaron@ekips.org
 
4
 
 
5
This program is free software; you can redistribute it and/or modify
 
6
it under the terms of the GNU General Public License as published by
 
7
the Free Software Foundation; either version 2 of the License, or
 
8
(at your option) any later version.
 
9
 
 
10
This program is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
GNU General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU General Public License
 
16
along with this program; if not, write to the Free Software
 
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
 
 
20
 
 
21
drawwave() was translated into python from the postscript version
 
22
described at http://www.ghostscript.com/person/toby/ and located
 
23
at http://www.telegraphics.com.au/sw/sine.ps . 
 
24
http://www.tinaja.com/glib/bezsine.pdf shows another method for
 
25
approximating sine with beziers.
 
26
 
 
27
The orginal postscript version displayed the following copyright 
 
28
notice and was released under the terms of the GPL:
 
29
Copyright (C) 2001-3 Toby Thain, toby@telegraphics.com.au
 
30
'''
 
31
import inkex, simplepath, simplestyle
 
32
from math import *
 
33
from random import *
 
34
 
 
35
def drawwave(samples, periods, width, height, left, top, 
 
36
                fx = "sin(x)", fpx = "cos(x)", fponum = True):
 
37
 
 
38
        # step is the distance between nodes on x
 
39
        step = 2*pi / samples
 
40
        third = step / 3.0
 
41
        
 
42
        # coords and scales based on the source rect
 
43
        xoff = left
 
44
        yoff = top + (height / 2)
 
45
        scalex = width / (2*pi * periods)
 
46
        scaley = height / 2
 
47
        procx = lambda x: x * scalex + xoff
 
48
        procy = lambda y: y * scaley + yoff
 
49
 
 
50
        # functions specified by the user
 
51
        if fx != "":
 
52
                f = eval('lambda x: ' + fx)
 
53
        if fpx != "":
 
54
                fp = eval('lambda x: ' + fpx)
 
55
 
 
56
        # initialize function and derivative for 0;
 
57
        # they are carried over from one iteration to the next, to avoid extra function calculations            
 
58
        y0 = f(0) 
 
59
        if fponum == True: # numerical derivative, using 0.001*step as the small differential
 
60
                d0 = (f(0 + 0.001*step) - y0)/(0.001*step)
 
61
        else: # derivative given by the user
 
62
                d0 = fp(0)
 
63
 
 
64
        a = [] # path array 
 
65
        a.append(['M',[procx(0.0), procy(y0)]]) # initial moveto
 
66
 
 
67
        for i in range(int(samples * periods)):
 
68
                x = i * step 
 
69
                y1 = f(x + step)
 
70
                if fponum == True: # numerical derivative
 
71
                        d1 = (y1 - f(x + step - 0.001*step))/(0.001*step)
 
72
                else: # derivative given by the user
 
73
                        d1 = fp(x + step)
 
74
                # create curve
 
75
                a.append(['C',[procx(x + third), procy(y0 + (d0 * third)), 
 
76
                        procx(x + (step - third)), procy(y1 - (d1 * third)),
 
77
                        procx(x + step), procy(y1)]])
 
78
                y0 = y1 # next segment's y0 is this segment's y1
 
79
                d0 = d1 # we assume the function is smooth everywhere, so carry over the derivative too
 
80
                    
 
81
        return a
 
82
 
 
83
class Wavy(inkex.Effect):
 
84
        def __init__(self):
 
85
                inkex.Effect.__init__(self)
 
86
                self.OptionParser.add_option("-p", "--periods",
 
87
                                                action="store", type="float", 
 
88
                                                dest="periods", default=4.0,
 
89
                                                help="Periods (2*Pi each)")
 
90
                self.OptionParser.add_option("-s", "--samples",
 
91
                                                action="store", type="int", 
 
92
                                                dest="samples", default=8,
 
93
                                                help="Samples per period")      
 
94
                self.OptionParser.add_option("--fofx",
 
95
                                                action="store", type="string", 
 
96
                                                dest="fofx", default="sin(x)",
 
97
                                                help="f(x) for plotting")       
 
98
                self.OptionParser.add_option("--fponum",
 
99
                                                action="store", type="inkbool", 
 
100
                                                dest="fponum", default=True,
 
101
                                                help="Calculate the first derivative numerically")      
 
102
                self.OptionParser.add_option("--fpofx",
 
103
                                                action="store", type="string", 
 
104
                                                dest="fpofx", default="cos(x)",
 
105
                                                help="f'(x) for plotting")      
 
106
        def effect(self):
 
107
                for id, node in self.selected.iteritems():
 
108
                        if node.tagName == 'rect':
 
109
                                new = self.document.createElement('svg:path')
 
110
                                x = float(node.attributes.getNamedItem('x').value)
 
111
                                y = float(node.attributes.getNamedItem('y').value)
 
112
                                w = float(node.attributes.getNamedItem('width').value)
 
113
                                h = float(node.attributes.getNamedItem('height').value)
 
114
 
 
115
                                s = node.attributes.getNamedItem('style').value
 
116
                                new.setAttribute('style', s)
 
117
                                try:
 
118
                                        t = node.attributes.getNamedItem('transform').value
 
119
                                        new.setAttribute('transform', t)
 
120
                                except AttributeError:
 
121
                                        pass
 
122
                                new.setAttribute('d', simplepath.formatPath(
 
123
                                                        drawwave(self.options.samples, 
 
124
                                                                self.options.periods,
 
125
                                                                w,h,x,y,
 
126
                                                                self.options.fofx, 
 
127
                                                                self.options.fpofx,
 
128
                                                                self.options.fponum)))
 
129
                                node.parentNode.appendChild(new)
 
130
                                node.parentNode.removeChild(node)
 
131
 
 
132
e = Wavy()
 
133
e.affect()