It adds DMX patching & some data in SVG XML elements because it was loaded by a handmade generator doing particules.
import xml.etree.cElementTree as ET
import math
import sys, getopt
# Final setup values
countX = 14
countY = 11
pixelsPerBar = 59
hardwarePitch = 3
exportPitch = 3
targetFile = "bars.svg"
exportText = False
# Set exportPitch to hardwarePitch for the file to import fixture from
# Set exportPitch to zero for the file we use in Le Metropol module
argv = sys.argv[1:]
try:
opts, args = getopt.getopt(argv,"hto:p:e:",[])
except getopt.GetoptError:
print 'generate_svg.py -o <outputfile> -p <hardwarePitch> -e <exportPitch> -t'
print 'examples'
print ' python generate_svg.py -o fixtures.svg -p 3 -e 3 -t'
print ' python generate_svg.py -o bars.svg -p 3 -e 0'
sys.exit(2)
for opt, arg in opts:
if opt in ("-o"):
targetFile = arg
elif opt in ("-t"):
exportText = True
elif opt in ("-p"):
hardwarePitch = int(arg)
elif opt in ("-e"):
exportPitch = int(arg)
gridSizeX = countX * 2
gridSizeY = countY
margin = 4
resX = gridSizeX * (pixelsPerBar + hardwarePitch*2)
resY = gridSizeY * (pixelsPerBar + hardwarePitch*2)
svg = ET.Element("svg", version="1.1", width=str(resX+hardwarePitch*2 + 2*margin), height=str(resY-hardwarePitch*2 + 2*margin))
def getPointPos(x,y):
return [margin + x * (pixelsPerBar + hardwarePitch*2), margin + y * (pixelsPerBar + hardwarePitch*2)]
def getPoint3DPos(x,y):
rotAngle = 2 * 3.141592654 * x / gridSizeX;
return [gridSizeX*(pixelsPerBar + hardwarePitch*2) * math.cos(rotAngle), y * (pixelsPerBar + hardwarePitch*2), gridSizeX*(pixelsPerBar + hardwarePitch*2) * math.sin(rotAngle)]
# Each bar extremity point has a number so we can compute connections between bars
def getPointId(x,y):
if x >= gridSizeX:
return getPointId(0,y)
else:
return x/2 + y*countX
patchingLines=[[[-1,10],[0,9],[-1,8],[-1,6],[0,5],[-1,4],[-1,2],[0,1],[-1,0]],[[0,11],[-1,10],[-1,8],[0,7],[-1,6],[-1,4],[0,3],[-1,2],[-1,0]],[[0,11],[0,9],[1,8],[0,7],[0,5],[1,4],[0,3],[0,1],[1,0]],[[0,11],[1,10],[0,9],[0,7],[1,6],[0,5],[0,3],[1,2],[0,1]]]
def getArtNetPatchForSegment(x1,y1,x2,y2):
if x1%2 == 0:
baseX = x1
elif x2%2 == 0:
baseX = x2
else:
assert (x1==x2), "Should be a vertical on odd numbers"
baseX = x1 + 1
relativeX1 = x1 - baseX
relativeX2 = x2 - baseX
baseUniverse = ((baseX%gridSizeX) / 2) * 4
for line in range(0,4):
patchingLine = patchingLines[line]
for idInLine in range(0,len(patchingLine)-1):
patchP1 = patchingLine[idInLine]
patchP2 = patchingLine[idInLine+1]
universe = baseUniverse+line
if universe >= 16:
universe += 24-16
if universe >= 24+20:
universe += 24-20
if patchP1[0] == relativeX1 and patchP1[1] == y1 and patchP2[0] == relativeX2 and patchP2[1] == y2:
return {"universe":universe, "channel":1+idInLine * 60,"reversed":False}
if patchP1[0] == relativeX2 and patchP1[1] == y2 and patchP2[0] == relativeX1 and patchP2[1] == y1:
return {"universe":universe, "channel":1+idInLine * 60,"reversed":True}
print("Error: patching not found for " + str(x1) + "," + str(y1) + " - " + str(x2) + "," + str(y2))
print(" relative: " + str(relativeX1) + "," + str(y1) + " - " + str(relativeX2) + "," + str(y2))
print(" baseX: " + str(baseX))
return {}
# Create the SVG file
for y in range(0,gridSizeY+1):
for x in range(0,gridSizeX+1):
if x % 2 != y % 2:
# 3 lines going down from this point
segStartId = getPointId(x,y)
if y < gridSizeY and x > 0: # Down left
segStart = getPointPos(x,y)
segStart[0] -= exportPitch
segStart[1] += exportPitch
segEnd = getPointPos(x-1,y+1)
segEndId = getPointId(x-1,y+1)
segEnd[0] += exportPitch
segEnd[1] -= exportPitch
segmentId = segStartId * 3 + 0;
artNetPatch=getArtNetPatchForSegment(x,y,x-1,y+1)
if artNetPatch["reversed"]:
ET.SubElement(svg, "line", x2=str(segStart[0]), y2=str(segStart[1]), x1=str(segEnd[0]), y1=str(segEnd[1]), fill="none", stroke="#000000", fixtureDefinition="Generic - 60x1L", id="l"+str(segmentId), endPointId=str(segStartId), startPointId=str(segEndId), fixtureUniverse=str(artNetPatch["universe"]), fixtureChannel=str(artNetPatch["channel"]))
else:
ET.SubElement(svg, "line", x1=str(segStart[0]), y1=str(segStart[1]), x2=str(segEnd[0]), y2=str(segEnd[1]), fill="none", stroke="#000000", fixtureDefinition="Generic - 60x1L", id="l"+str(segmentId), startPointId=str(segStartId), endPointId=str(segEndId), fixtureUniverse=str(artNetPatch["universe"]), fixtureChannel=str(artNetPatch["channel"]))
if exportText:
textElem = ET.SubElement(svg, "text", x=str((segStart[0]+segEnd[0])/2), y=str((segStart[1]+segEnd[1])/2), fill="red")
textElem.text = str(segmentId)
if y < gridSizeY-1: # Straight Down
segStart = getPointPos(x,y)
segStart[1] += exportPitch
segEnd = getPointPos(x,y+2)
segEndId = getPointId(x,y+2)
segEnd[1] -= exportPitch
segmentId = segStartId * 3 + 1;
artNetPatch=getArtNetPatchForSegment(x,y,x,y+2)
if artNetPatch["reversed"]:
ET.SubElement(svg, "line", x2=str(segStart[0]), y2=str(segStart[1]), x1=str(segEnd[0]), y1=str(segEnd[1]), fill="none", stroke="#000000", fixtureDefinition="Generic - 60x1L", id="l"+str(segmentId), endPointId=str(segStartId), startPointId=str(segEndId), fixtureUniverse=str(artNetPatch["universe"]), fixtureChannel=str(artNetPatch["channel"]))
else:
ET.SubElement(svg, "line", x1=str(segStart[0]), y1=str(segStart[1]), x2=str(segEnd[0]), y2=str(segEnd[1]), fill="none", stroke="#000000", fixtureDefinition="Generic - 60x1L", id="l"+str(segmentId), startPointId=str(segStartId), endPointId=str(segEndId), fixtureUniverse=str(artNetPatch["universe"]), fixtureChannel=str(artNetPatch["channel"]))
if exportText:
textElem = ET.SubElement(svg, "text", x=str((segStart[0]+segEnd[0])/2), y=str((segStart[1]+segEnd[1])/2), fill="red")
textElem.text = str(segmentId)
if y < gridSizeY and x < gridSizeX: # Down right
segStart = getPointPos(x,y)
segStart[0] += exportPitch
segStart[1] += exportPitch
segEnd = getPointPos(x+1,y+1)
segEndId = getPointId(x+1,y+1)
segEnd[0] -= exportPitch
segEnd[1] -= exportPitch
segmentId = segStartId * 3 + 2;
artNetPatch=getArtNetPatchForSegment(x,y,x+1,y+1)
if artNetPatch["reversed"]:
ET.SubElement(svg, "line", x2=str(segStart[0]), y2=str(segStart[1]), x1=str(segEnd[0]), y1=str(segEnd[1]), fill="none", stroke="#000000", fixtureDefinition="Generic - 60x1L", id="l"+str(segmentId), endPointId=str(segStartId), startPointId=str(segEndId), fixtureUniverse=str(artNetPatch["universe"]), fixtureChannel=str(artNetPatch["channel"]))
else:
ET.SubElement(svg, "line", x1=str(segStart[0]), y1=str(segStart[1]), x2=str(segEnd[0]), y2=str(segEnd[1]), fill="none", stroke="#000000", fixtureDefinition="Generic - 60x1L", id="l"+str(segmentId), startPointId=str(segStartId), endPointId=str(segEndId), fixtureUniverse=str(artNetPatch["universe"]), fixtureChannel=str(artNetPatch["channel"]))
if exportText:
textElem = ET.SubElement(svg, "text", x=str((segStart[0]+segEnd[0])/2), y=str((segStart[1]+segEnd[1])/2), fill="red")
textElem.text = str(segmentId)
segStart = getPointPos(x,y)
if exportText:
textElem = ET.SubElement(svg, "text", x=str(segStart[0]), y=str(segStart[1]+1), fill="green")
textElem.text = str(segStartId)
tree = ET.ElementTree(svg)
tree.write(targetFile)
# Create a 3D OBJ file for preview
objFileContent = ""
vIndices = {}
vIdx = 1
# Vertices
for x in range(0,gridSizeX):
vIndices[x]={}
for y in range(0,gridSizeY+1):
if x % 2 != y % 2:
pos3D = getPoint3DPos(x,y)
objFileContent += "v " + str(pos3D[0]) + " " + str(pos3D[1]) + " " + str(pos3D[2]) + "\n"
vIndices[x][y] = vIdx
vIdx += 1
objFileContent += "\n"
for x in range(0,gridSizeX+1):
for y in range(0,gridSizeY+1):
if x % 2 != y % 2:
if y < gridSizeY and x > 0: # Down left
objFileContent += "f " + str(vIndices[(x) % gridSizeX][y]) + " " + str(vIndices[(x-1) % gridSizeX][y+1]) + " " + str(vIndices[(x) % gridSizeX][y]) + "\n"
pass
if y < gridSizeY-1: # Straight Down
objFileContent += "f " + str(vIndices[(x) % gridSizeX][y]) + " " + str(vIndices[(x) % gridSizeX][y+2]) + " " + str(vIndices[(x) % gridSizeX][y]) + "\n"
pass
if y < gridSizeY and x < gridSizeX: # Down right
objFileContent += "f " + str(vIndices[(x) % gridSizeX][y]) + " " + str(vIndices[(x+1) % gridSizeX][y+1]) + " " + str(vIndices[(x) % gridSizeX][y]) + "\n"
pass
text_file = open("bars.obj", "w")
text_file.write(objFileContent)
text_file.close()