Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / share / extensions / cubicsuperpath.py
1 #!/usr/bin/env python
2 """
3 cubicsuperpath.py
5 Copyright (C) 2005 Aaron Spike, aaron@ekips.org
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 """
22 import simplepath 
23 from math import *
25 def matprod(mlist):
26     prod=mlist[0]
27     for m in mlist[1:]:
28         a00=prod[0][0]*m[0][0]+prod[0][1]*m[1][0]
29         a01=prod[0][0]*m[0][1]+prod[0][1]*m[1][1]
30         a10=prod[1][0]*m[0][0]+prod[1][1]*m[1][0]
31         a11=prod[1][0]*m[0][1]+prod[1][1]*m[1][1]
32         prod=[[a00,a01],[a10,a11]]
33     return prod
34 def rotmat(teta):
35     return [[cos(teta),-sin(teta)],[sin(teta),cos(teta)]]
36 def applymat(mat, pt):
37     x=mat[0][0]*pt[0]+mat[0][1]*pt[1]
38     y=mat[1][0]*pt[0]+mat[1][1]*pt[1]
39     pt[0]=x
40     pt[1]=y
41 def norm(pt):
42     return sqrt(pt[0]*pt[0]+pt[1]*pt[1])
44 def ArcToPath(p1,params):
45     A=p1[:]
46     rx,ry,teta,longflag,sweepflag,x2,y2=params[:]
47     teta = teta*pi/180.0
48     B=[x2,y2]
49     if rx==0 or ry==0:
50         return([[A,A,A],[B,B,B]])
51     mat=matprod((rotmat(teta),[[1/rx,0],[0,1/ry]],rotmat(-teta)))
52     applymat(mat, A)
53     applymat(mat, B)
54     k=[-(B[1]-A[1]),B[0]-A[0]]
55     d=k[0]*k[0]+k[1]*k[1]
56     k[0]/=sqrt(d)
57     k[1]/=sqrt(d)
58     d=sqrt(max(0,1-d/4))
59     if longflag==sweepflag:
60         d*=-1
61     O=[(B[0]+A[0])/2+d*k[0],(B[1]+A[1])/2+d*k[1]]
62     OA=[A[0]-O[0],A[1]-O[1]]
63     OB=[B[0]-O[0],B[1]-O[1]]
64     start=acos(OA[0]/norm(OA))
65     if OA[1]<0:
66         start*=-1
67     end=acos(OB[0]/norm(OB))
68     if OB[1]<0:
69         end*=-1
71     if sweepflag and start>end:
72         end +=2*pi
73     if (not sweepflag) and start<end:
74         end -=2*pi
76     NbSectors=int(abs(start-end)*2/pi)+1
77     dTeta=(end-start)/NbSectors
78     #v=dTeta*2/pi*0.552
79     #v=dTeta*2/pi*4*(sqrt(2)-1)/3
80     v = 4*tan(dTeta/4)/3
81     #if not sweepflag:
82     #    v*=-1
83     p=[]
84     for i in range(0,NbSectors+1,1):
85         angle=start+i*dTeta
86         v1=[O[0]+cos(angle)-(-v)*sin(angle),O[1]+sin(angle)+(-v)*cos(angle)]
87         pt=[O[0]+cos(angle)                ,O[1]+sin(angle)                ]
88         v2=[O[0]+cos(angle)-  v *sin(angle),O[1]+sin(angle)+  v *cos(angle)]
89         p.append([v1,pt,v2])
90     p[ 0][0]=p[ 0][1][:]
91     p[-1][2]=p[-1][1][:]
93     mat=matprod((rotmat(teta),[[rx,0],[0,ry]],rotmat(-teta)))
94     for pts in p:
95         applymat(mat, pts[0])
96         applymat(mat, pts[1])
97         applymat(mat, pts[2])
98     return(p)
99     
100 def CubicSuperPath(simplepath):
101     csp = []
102     subpath = -1
103     subpathstart = []
104     last = []
105     lastctrl = []
106     for s in simplepath:
107         cmd, params = s        
108         if cmd == 'M':
109             if last:
110                 csp[subpath].append([lastctrl[:],last[:],last[:]])
111             subpath += 1
112             csp.append([])
113             subpathstart =  params[:]
114             last = params[:]
115             lastctrl = params[:]
116         elif cmd == 'L':
117             csp[subpath].append([lastctrl[:],last[:],last[:]])
118             last = params[:]
119             lastctrl = params[:]
120         elif cmd == 'C':
121             csp[subpath].append([lastctrl[:],last[:],params[:2]])
122             last = params[-2:]
123             lastctrl = params[2:4]
124         elif cmd == 'Q':
125             q0=last[:]
126             q1=params[0:2]
127             q2=params[2:4]
128             x0=     q0[0]
129             x1=1./3*q0[0]+2./3*q1[0]
130             x2=           2./3*q1[0]+1./3*q2[0]
131             x3=                           q2[0]
132             y0=     q0[1]
133             y1=1./3*q0[1]+2./3*q1[1]
134             y2=           2./3*q1[1]+1./3*q2[1]
135             y3=                           q2[1]
136             csp[subpath].append([lastctrl[:],[x0,y0],[x1,y1]])
137             last = [x3,y3]
138             lastctrl = [x2,y2]
139         elif cmd == 'A':
140             arcp=ArcToPath(last[:],params[:])
141             arcp[ 0][0]=lastctrl[:]
142             last=arcp[-1][1]
143             lastctrl = arcp[-1][0]
144             csp[subpath]+=arcp[:-1]
145         elif cmd == 'Z':
146             csp[subpath].append([lastctrl[:],last[:],last[:]])
147             last = subpathstart[:]
148             lastctrl = subpathstart[:]
149     #append final superpoint
150     csp[subpath].append([lastctrl[:],last[:],last[:]])
151     return csp    
153 def unCubicSuperPath(csp):
154     a = []
155     for subpath in csp:
156         if subpath:
157             a.append(['M',subpath[0][1][:]])
158             for i in range(1,len(subpath)):
159                 a.append(['C',subpath[i-1][2][:] + subpath[i][0][:] + subpath[i][1][:]])
160     return a
162 def parsePath(d):
163     return CubicSuperPath(simplepath.parsePath(d))
165 def formatPath(p):
166     return simplepath.formatPath(unCubicSuperPath(p))
169 # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99