#!/usr/bin/env python3 import math import codecs import inkex from inkex.paths import Path from geometry.Circle import Circle from geometry.Vertex import Vertex from geometry.Triangle import Triangle from geometry.Plus import Plus from geometry.Minus import Minus from lxml import etree ALL=".//" def fixTo360(radian): if radian <0: return math.pi*2.0+radian return radian def widenDir(start,end): d21x = end.x - start.x; d21y = end.y - start.y; return fixTo360(-math.atan2(d21x, d21y)); def lineDir(start,end): d21x = end.x - start.x; d21y = end.y - start.y; #inkex.errormsg("d21y "+str(d21y)+" d21x "+str(d21x)+" d21y/d21x"+str(d21y/d21x)) rad=math.atan2(d21y, d21x); #inkex.errormsg(u"Line direction"+str(math.degrees(rad))) return fixTo360(rad) #radian<The assumption is that 0 will not come def invert(radian): return radian-math.pi def fixWithin90(radian): if math.fabs(radian)>math.pi/2.0: #I want you to be +-90 (forward direction) return invert(radian) return radian def fixOver90(radian): if math.fabs(radian)<math.pi/2.0: return invert(radian) return radian def fixWithinAb180(radian): if math.fabs(radian)<math.pi: return radian if radian <0: return math.pi*2.0+radian return radian-math.pi*2.0 def printRadian(fp,message,radian): fp.write(message+":"+str(math.degrees(radian))+"\n") def stripline(bone,linewidth,logname): fp = codecs.open(logname, "w", "utf_8" ) i = 0; segmentNum = len(bone)-1; elementNum=(segmentNum*2+2)*5 outVertexArray = [] #4 vertices per line segment+Extra amount added to the end point vertexIdx = 0 #First apex start =bone[0] end =bone[1] lastRad=0 lastUsedRad=0 radY = widenDir(start,end) lineRad=lineDir(start,end) fp.write(u"0th vertex") printRadian(fp,u"lineRad",lineRad) originalRad=radY #Indicates the direction of bending cornerDir=radY-lastRad printRadian(fp,u"radY",radY) diffRad=0 printRadian(fp,u"diffRad:",diffRad) printRadian(fp,u"radY-lineRad:",radY-lineRad) printRadian(fp,u"sin(radY-lineRad:)",math.sin(radY-lineRad)) adjustedRad=radY printRadian(fp,u"The first drawing angle",adjustedRad) fp.write("\n") direction=True lastRad=radY lastUsedRad=adjustedRad LEFT=Vertex(linewidth,0) RIGHT=Vertex(-linewidth,0) #variable v=Vertex(0,0) v.set(LEFT) v.rotate(adjustedRad) flag = False #if radY< 0 else False outVertexArray.append([start+v,flag]) v.set(RIGHT) v.rotate(adjustedRad) flag = True# if radY< 0 else False outVertexArray.append([start+v,flag]) for i in range(1,segmentNum): start =bone[i] end =bone[i+1] originalRad = widenDir(start,end) radY=(originalRad+lastRad)*0.5#Values from 0 to 360 degrees fp.write(str(i)+u"Th vertex") diffRad=(originalRad-lastRad) if math.fabs(math.fabs(diffRad)-math.pi)<=(45.0*math.pi/180.0):#To erase the pointed triangle when making a U-turn printRadian(fp,u"Correction of U-turn point:diffRad",diffRad) fp.write(u"Difference"+str(math.fabs(math.fabs(diffRad)-math.pi))) radY=originalRad printRadian(fp,u"radY:",radY) printRadian(fp,u"diffRad:",diffRad) printRadian(fp,u"radY-lineRad:",radY-lineRad) printRadian(fp,u"sin(radY-lineRad:)",math.sin(radY-lineRad)) #Twist prevention if math.sin(radY-lineRad)>0: radY=invert(radY) lineRad=lineDir(start,end) printRadian(fp,u"lineRad:",lineRad) adjustedRad=radY printRadian(fp,u"diffRad:",diffRad) squareRad=lineDir(start,end) #printRadian(u"squareRad",squareRad) printRadian(fp,u"Drawing angle after conversion:",radY) v.set(LEFT) #1〜√2 I want you to be in the range coef=(1+0.41421356237*math.fabs(math.sin(diffRad*0.5))) fp.write("coef="+str(coef)) v.x*=coef v.rotate(adjustedRad) flag = False outVertexArray.append([start+v,flag]) v.set(RIGHT) v.x*=coef v.rotate(adjustedRad) flag = True outVertexArray.append([start+v,flag]) lastRad=originalRad lastUsedRad=adjustedRad fp.write("\n") #The last round fp.write(str(i)+u"Th vertex") adjustedRad=originalRad printRadian(fp,u"Last drawing angle:",originalRad) v.set(LEFT) v.rotate(adjustedRad) flag = False# if originalRad< 0 else False outVertexArray.append([end+v,flag]) v.set(RIGHT) v.rotate(adjustedRad) flag = True# if originalRad< 0 else False outVertexArray.append([end+v,flag]) fp.close() return outVertexArray class StripLine(inkex.EffectExtension): def add_arguments(self, pars): pars.add_argument("--linewidth", type=int, default="10", help="Line thickness") pars.add_argument("--logfilename", default="10", help="Log file name") def effect(self): linewidth=self.options.linewidth # Get the main root element SVG svg = self.document.getroot() pathlist = svg.findall(ALL+"{"+inkex.NSS['svg']+"}path") for path in pathlist: if path == None: inkex.errormsg("Please write the path! !") #Get vertex coordinates of path vals=path.path.to_arrays() bone=[] for cmd,vert in vals: #Sometimes there is an empty, so countermeasures against it if len(vert) != 0: bone.append(Vertex(vert[0],vert[1])) if len(bone) != 0: outVertexArray=stripline(bone,linewidth,self.options.logfilename) pointer=0 for t in range(len(outVertexArray)-2): tri=Triangle(outVertexArray[pointer][0],outVertexArray[pointer+1][0],outVertexArray[pointer+2][0]) stripstr=tri.toSVG() color2="blue" if outVertexArray[pointer][1]: color="blue" else: color="red" pointer+=1 attributes={"points":stripstr, "style":"fill:"+color2+";stroke:"+color2+";stroke-width:"+str(linewidth/3),"fill-opacity":"0.5"} pth =etree.Element("polygon",attributes) svg.append(pth) pointer=0 #Draw a point indicating +- for t in range(len(outVertexArray)): if outVertexArray[pointer][1]: point=Plus(outVertexArray[pointer][0].x,outVertexArray[pointer][0].y,linewidth/3) color="blue" else: point=Minus(outVertexArray[pointer][0].x,outVertexArray[pointer][0].y,linewidth/3) color="red" if pointer==0: color="#6f0018"#Dark red point.appendToSVG(color,svg) #svg.append(Circle.toSVG(outVertexArray[pointer][0].x,outVertexArray[pointer][0].y,linewidth/3,color,0)) pointer+=1 pointer=0 pathstr="M " for t in range(len(outVertexArray)): pathstr+=str(outVertexArray[pointer][0].x)+" "+str(outVertexArray[pointer][0].y)+" " pointer+=1 att3={"d":pathstr,"r":"1","fill":"none","stroke-width":"1","stroke":"white"} pt=etree.Element("path",att3) if __name__ == '__main__': StripLine().run()