--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/printrun-src/printrun/svg2gcode/cubicsuperpath.py Fri Jun 03 09:42:44 2016 +0200 @@ -0,0 +1,169 @@ +#!/usr/bin/env python +""" +cubicsuperpath.py + +Copyright (C) 2005 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 simplepath +from math import * + +def matprod(mlist): + prod=mlist[0] + for m in mlist[1:]: + a00=prod[0][0]*m[0][0]+prod[0][1]*m[1][0] + a01=prod[0][0]*m[0][1]+prod[0][1]*m[1][1] + a10=prod[1][0]*m[0][0]+prod[1][1]*m[1][0] + a11=prod[1][0]*m[0][1]+prod[1][1]*m[1][1] + prod=[[a00,a01],[a10,a11]] + return prod +def rotmat(teta): + return [[cos(teta),-sin(teta)],[sin(teta),cos(teta)]] +def applymat(mat, pt): + x=mat[0][0]*pt[0]+mat[0][1]*pt[1] + y=mat[1][0]*pt[0]+mat[1][1]*pt[1] + pt[0]=x + pt[1]=y +def norm(pt): + return sqrt(pt[0]*pt[0]+pt[1]*pt[1]) + +def ArcToPath(p1,params): + A=p1[:] + rx,ry,teta,longflag,sweepflag,x2,y2=params[:] + teta = teta*pi/180.0 + B=[x2,y2] + if rx==0 or ry==0: + return([[A,A,A],[B,B,B]]) + mat=matprod((rotmat(teta),[[1/rx,0],[0,1/ry]],rotmat(-teta))) + applymat(mat, A) + applymat(mat, B) + k=[-(B[1]-A[1]),B[0]-A[0]] + d=k[0]*k[0]+k[1]*k[1] + k[0]/=sqrt(d) + k[1]/=sqrt(d) + d=sqrt(max(0,1-d/4)) + if longflag==sweepflag: + d*=-1 + O=[(B[0]+A[0])/2+d*k[0],(B[1]+A[1])/2+d*k[1]] + OA=[A[0]-O[0],A[1]-O[1]] + OB=[B[0]-O[0],B[1]-O[1]] + start=acos(OA[0]/norm(OA)) + if OA[1]<0: + start*=-1 + end=acos(OB[0]/norm(OB)) + if OB[1]<0: + end*=-1 + + if sweepflag and start>end: + end +=2*pi + if (not sweepflag) and start<end: + end -=2*pi + + NbSectors=int(abs(start-end)*2/pi)+1 + dTeta=(end-start)/NbSectors + #v=dTeta*2/pi*0.552 + #v=dTeta*2/pi*4*(sqrt(2)-1)/3 + v = 4*tan(dTeta/4)/3 + #if not sweepflag: + # v*=-1 + p=[] + for i in range(0,NbSectors+1,1): + angle=start+i*dTeta + v1=[O[0]+cos(angle)-(-v)*sin(angle),O[1]+sin(angle)+(-v)*cos(angle)] + pt=[O[0]+cos(angle) ,O[1]+sin(angle) ] + v2=[O[0]+cos(angle)- v *sin(angle),O[1]+sin(angle)+ v *cos(angle)] + p.append([v1,pt,v2]) + p[ 0][0]=p[ 0][1][:] + p[-1][2]=p[-1][1][:] + + mat=matprod((rotmat(teta),[[rx,0],[0,ry]],rotmat(-teta))) + for pts in p: + applymat(mat, pts[0]) + applymat(mat, pts[1]) + applymat(mat, pts[2]) + return(p) + +def CubicSuperPath(simplepath): + csp = [] + subpath = -1 + subpathstart = [] + last = [] + lastctrl = [] + for s in simplepath: + cmd, params = s + if cmd == 'M': + if last: + csp[subpath].append([lastctrl[:],last[:],last[:]]) + subpath += 1 + csp.append([]) + subpathstart = params[:] + last = params[:] + lastctrl = params[:] + elif cmd == 'L': + csp[subpath].append([lastctrl[:],last[:],last[:]]) + last = params[:] + lastctrl = params[:] + elif cmd == 'C': + csp[subpath].append([lastctrl[:],last[:],params[:2]]) + last = params[-2:] + lastctrl = params[2:4] + elif cmd == 'Q': + q0=last[:] + q1=params[0:2] + q2=params[2:4] + x0= q0[0] + x1=1./3*q0[0]+2./3*q1[0] + x2= 2./3*q1[0]+1./3*q2[0] + x3= q2[0] + y0= q0[1] + y1=1./3*q0[1]+2./3*q1[1] + y2= 2./3*q1[1]+1./3*q2[1] + y3= q2[1] + csp[subpath].append([lastctrl[:],[x0,y0],[x1,y1]]) + last = [x3,y3] + lastctrl = [x2,y2] + elif cmd == 'A': + arcp=ArcToPath(last[:],params[:]) + arcp[ 0][0]=lastctrl[:] + last=arcp[-1][1] + lastctrl = arcp[-1][0] + csp[subpath]+=arcp[:-1] + elif cmd == 'Z': + csp[subpath].append([lastctrl[:],last[:],last[:]]) + last = subpathstart[:] + lastctrl = subpathstart[:] + #append final superpoint + csp[subpath].append([lastctrl[:],last[:],last[:]]) + return csp + +def unCubicSuperPath(csp): + a = [] + for subpath in csp: + if subpath: + a.append(['M',subpath[0][1][:]]) + for i in range(1,len(subpath)): + a.append(['C',subpath[i-1][2][:] + subpath[i][0][:] + subpath[i][1][:]]) + return a + +def parsePath(d): + return CubicSuperPath(simplepath.parsePath(d)) + +def formatPath(p): + return simplepath.formatPath(unCubicSuperPath(p)) + + +# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99