231 lines
7.8 KiB
Python
231 lines
7.8 KiB
Python
|
#!/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 StripLineEffect(inkex.Effect):
|
|||
|
def __init__(self):
|
|||
|
inkex.Effect.__init__(self)
|
|||
|
self.arg_parser.add_argument("--linewidth", type=int, default="10", help="Line thickness")
|
|||
|
self.arg_parser.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.get('d')).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]))
|
|||
|
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)
|
|||
|
|
|||
|
StripLineEffect().run()
|