Light Plotter with Intel Edison (12 / 16 steg)
Steg 12: XY-koordinater från ett SVG (Python kod)
Intro
Vi behöver ett enkelt sätt att skapa bilder som vi vill uppmärksamma, så jag valde att rita SVGs (scalable vector graphics) hjälp Inkscape (som är gratis). En SVG är faktiskt en XML-baserad filtyp, så du kan tolka det enkelt nog med python. Det kan bli mycket komplicerat, men om vi begränsar våra ritningar till sökvägen objekt, det är enkelt.
Python koden jag har skrivit nedan kan köras på din dator så att du kan visa utdata, när du förstår det är det lätt att genomföra samma sak på Edison i vår controller.
Ritning
Första intakt inkscape och dra något enkelt med linjeverktyget (min ritning av Intel-logotypen bifogas)
Se till att koordinaterna är inställda till absolut på följande sätt:
- Skift + Ctrl + p
- ingång/utgång
- SVG-utdata
- sökvägen data
- sökvägen strängformat: absolut
Om du rita komplicerade banor eller använda spårning verktyg, se till att först "bryta isär" stigar eller skriptet inte kommer att hantera dem.
När du har tillämpat den inställningen, markera hela bilden (ctrl + a) och flytta den till uppdatera koordinaterna och spara som en svg
Använda absoluta koordinater dramatiskt minskar den bearbetning som vi behöver göra för att vända ut SVG banor i linjesegment definieras av parar av x, y koordinater.
Python-koden
Här är en liten bit av python kod som läser i en SVG-fil och använda "minidom"-modulen, analyserar filen för banor.
Varje väg består av en serie av kommandon (som är "eller"L") följt av en koordinat. Här är några exempel (Läs detta för praktiska detaljer: länk):
- Är "betyder,"flytta pennan till denna koordinat"
- är "medel"flytta pennan detta långt, släkting till nuvarande position"
- "L" betyder, "flytta pennan till denna koordinat, medan du ritar en linje"
- är "medel"flytta pennan detta långt, släkting till nuvarande position, medan du ritar en linje"
- "Z" eller "z":. "Rita en linje tillbaka till där vi började (nära formen)
Jag valde bara att ta itu med "M", "L" och "Z" i det här exemplet, därav kravet på absoluta koordinater.
Jag har även tagit lite kod som använder Matplotlib (ett python plotting verktyg) att dra SVG och spara den som en PNG för visning.
importera minidom från xml.dom
importera re
klass svgHandler:
def __init__(self):
Self.filename = ""
Self.Lines = [] #list segment av formuläret [x 0 y0 x1 y1 RGB] där x och y är 0-1 flyter
def importFile(self,filename):
doc = minidom.parse(filename) # parseString finns även
banor = doc.getElementsByTagName('path')
doc.unlink()
pathsandcolours =]
Self.Lines =]
"""
Gå igenom banorna och förvara sina samordna strängar och färger i en lista över tupler
"""
för p i sökvägar:
styleValues = p.attributes['style'].value.split(";")
val i styleValues:
om val.split(":") [0] == "stroke":
RGB = val.split(":") [1]
pathsandcolours.append((p.getAttribute('d'),RGB))
"""
För varje sökväg och dess motsvarande färg, konvertera till en uppsättning av linjesegment i formuläret [x 0 y0 x1 y1 RGB]
"""
xMin = float("inf")
xMax =-float("inf")
yMin = float("inf")
yMax =-float("inf")
unScaledLines =]
för väg, rgb i pathsandcolours:
pathCoords = re.split(r'([CcLlMmZz])',path)
startX = 0
startY = 0
lastX = 0
lastY = 0
newLine = sant
closeLine = False
#we utgår från absoluta koordinater i SVG
skriva ut pathCoords
för coord i pathCoords:
Coord = coord.strip()
om len(coord) == 0:
passera
Elif coord == är ': # är "är flytta markören till absolut position
newLine = sant
Elif coord == 'L': #' L' är Rita linje till absolut position
newLine = False
Elif coord == "Z" eller coord.strip() == "z": #close linje till första punkten
closeLine = sant
annat:
försök:
x = float(re.split(r'[\s,]',coord)[0])
y = float(re.split(r'[\s,]',coord)[1])
xMin = min(xMin,x)
yMin = min(yMin,y)
xMax = max(xMax,x)
yMax = max(yMax,y)
om closeLine:
lastX = x
lastY = y
startX = x
startY = y
unScaledLines.append([lastX,lastY,startX,startY,rgb])
Elif newLine:
lastX = x
lastY = y
startX = x
startY = y
annat:
unScaledLines.append([lastX,lastY,x,y,rgb])
#self.lines.append([lastX,lastY,x,y,rgb])
lastX = x
lastY = y
utom:
skriva ut "ohanterat kommando:", coord
#print "xMin, yMin", xMin, yMin
#print "xMax, yMax", xMax, yMax
xTotal = xMax-xMin
yTotal = yMax-yMin
för x0, y0, x 1, y1, rgb i unScaledLines:
X0normalised = (x0-xMin) / xTotal
X1normalised = (x1-xMin) / xTotal
Y0normalised = (y0-yMin) / yTotal
Y1normalised = (y1-yMin) / yTotal
Self.Lines.append([X0normalised,Y0normalised,X1normalised,Y1normalised,RGB])
def plotPath(self):
importera matplotlib.pyplot som plt
PLT.GCA().invert_yaxis()
för x0, y0, x 1, y1, rgb i self.lines:
skriva ut int(rgb[1:3],16),int(rgb[3:5],16),int(rgb[5:7],16)
PLT.Plot([x0,x1],[y0,Y1],Color=RGB)
PLT.savefig(Self.filename.Split('.') [0] + ".png")
PLT.show()
svgh = svgHandler()
svgh.importFile("example.svg")
svgh.plotPath()