Printrun/printrun/stltool.py

251 lines
8.0 KiB
Python
Raw Normal View History

2012-01-23 11:36:49 +00:00
# This file is part of the Printrun suite.
#
2012-01-23 11:36:49 +00:00
# Printrun 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 3 of the License, or
# (at your option) any later version.
#
2012-01-23 11:36:49 +00:00
# Printrun 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.
#
2012-01-23 11:36:49 +00:00
# You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import sys, struct, math
2012-08-08 07:38:48 +00:00
def cross(v1, v2):
2012-08-08 07:58:09 +00:00
return [v1[1]*v2[2]-v1[2]*v2[1], v1[2]*v2[0]-v1[0]*v2[2], v1[0]*v2[1]-v1[1]*v2[0]]
def genfacet(v):
2012-08-08 07:58:09 +00:00
veca = [v[1][0]-v[0][0], v[1][1]-v[0][1], v[1][2]-v[0][2]]
vecb = [v[2][0]-v[1][0], v[2][1]-v[1][1], v[2][2]-v[1][2]]
2012-08-08 07:38:48 +00:00
vecx = cross(veca, vecb)
vlen = math.sqrt(sum(map(lambda x:x*x, vecx)))
if vlen == 0:
vlen = 1
normal = map(lambda x:x/vlen, vecx)
return [normal, v]
2012-08-08 07:58:09 +00:00
I = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
]
def transpose(matrix):
return zip(*matrix)
#return [[v[i] for v in matrix] for i in xrange(len(matrix[0]))]
2012-08-08 07:38:48 +00:00
def multmatrix(vector, matrix):
return map(sum, transpose(map(lambda x:[x[0]*p for p in x[1]], zip(vector, transpose(matrix)))))
2012-08-08 07:38:48 +00:00
def applymatrix(facet, matrix = I):
#return facet
2012-08-08 07:58:09 +00:00
#return [map(lambda x:-1.0*x, multmatrix(facet[0]+[1], matrix)[:3]), map(lambda x:multmatrix(x+[1], matrix)[:3], facet[1])]
return genfacet(map(lambda x:multmatrix(x+[1], matrix)[:3], facet[1]))
f = [[0, 0, 0],[[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565]]]
m = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 1],
[0, 0, 0, 1]
]
2012-08-08 07:58:09 +00:00
def emitstl(filename, facets = [], objname = "stltool_export", binary = 1):
if filename is None:
return
2011-09-22 10:43:27 +00:00
if binary:
2012-08-08 07:58:09 +00:00
f = open(filename, "wb")
2012-08-08 07:38:48 +00:00
buf = "".join(["\0"]*80)
2012-08-08 07:58:09 +00:00
buf+=struct.pack("<I", len(facets))
2012-08-08 07:38:48 +00:00
facetformat = struct.Struct("<ffffffffffffH")
2011-09-22 10:43:27 +00:00
for i in facets:
2012-08-08 07:38:48 +00:00
l = list(i[0][:])
2011-09-22 10:43:27 +00:00
for j in i[1]:
l+=j[:]
l+=[0]
#print len(l)
buf+=facetformat.pack(*l)
f.write(buf)
f.close()
return
2011-09-22 10:43:27 +00:00
2012-08-08 07:58:09 +00:00
f = open(filename, "w")
f.write("solid "+objname+"\n")
for i in facets:
2012-08-08 07:38:48 +00:00
f.write(" facet normal "+" ".join(map(str, i[0]))+"\n outer loop\n")
for j in i[1]:
2012-08-08 07:38:48 +00:00
f.write(" vertex "+" ".join(map(str, j))+"\n")
f.write(" endloop"+"\n")
f.write(" endfacet"+"\n")
f.write("endsolid "+objname+"\n")
f.close()
class stl:
2012-08-08 07:38:48 +00:00
def __init__(self, filename = None):
2012-08-08 07:58:09 +00:00
self.facet = [[0, 0, 0],[[0, 0, 0],[0, 0, 0],[0, 0, 0]]]
self.facets = []
self.facetsminz = []
self.facetsmaxz = []
2012-08-08 07:38:48 +00:00
self.name = ""
self.insolid = 0
self.infacet = 0
self.inloop = 0
self.facetloc = 0
if filename is None:
return
2012-08-08 07:38:48 +00:00
self.f = list(open(filename))
if not self.f[0].startswith("solid"):
2011-07-29 22:11:17 +00:00
print "Not an ascii stl solid - attempting to parse as binary"
2012-08-08 07:58:09 +00:00
f = open(filename, "rb")
2012-08-08 07:38:48 +00:00
buf = f.read(84)
2011-07-29 22:11:17 +00:00
while(len(buf)<84):
2012-08-08 07:38:48 +00:00
newdata = f.read(84-len(buf))
2011-07-29 22:11:17 +00:00
if not len(newdata):
break
buf+=newdata
2012-08-08 07:58:09 +00:00
facetcount = struct.unpack_from("<I", buf, 80)
2012-08-08 07:38:48 +00:00
facetformat = struct.Struct("<ffffffffffffH")
2011-07-29 22:11:17 +00:00
for i in xrange(facetcount[0]):
2012-08-08 07:38:48 +00:00
buf = f.read(50)
2011-07-29 22:11:17 +00:00
while(len(buf)<50):
2012-08-08 07:38:48 +00:00
newdata = f.read(50-len(buf))
2011-07-29 22:11:17 +00:00
if not len(newdata):
break
buf+=newdata
2012-08-08 07:38:48 +00:00
fd = list(facetformat.unpack(buf))
self.name = "binary soloid"
2012-08-08 07:58:09 +00:00
self.facet = [fd[:3],[fd[3:6], fd[6:9], fd[9:12]]]
2011-07-29 22:11:17 +00:00
self.facets+=[self.facet]
2012-08-08 07:38:48 +00:00
facet = self.facet
2012-08-08 07:58:09 +00:00
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
2011-07-29 22:11:17 +00:00
f.close()
return
for i in self.f:
if not self.parseline(i):
return
2012-08-08 07:58:09 +00:00
def translate(self, v = [0, 0, 0]):
matrix = [
[1, 0, 0, v[0]],
[0, 1, 0, v[1]],
[0, 0, 1, v[2]],
[0, 0, 0, 1]
]
return self.transform(matrix)
2012-08-08 07:58:09 +00:00
def rotate(self, v = [0, 0, 0]):
import math
2012-08-08 07:38:48 +00:00
z = v[2]
2012-08-08 07:58:09 +00:00
matrix1 = [
[math.cos(math.radians(z)),-math.sin(math.radians(z)), 0, 0],
[math.sin(math.radians(z)), math.cos(math.radians(z)), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
]
2012-08-08 07:38:48 +00:00
y = v[0]
2012-08-08 07:58:09 +00:00
matrix2 = [
[1, 0, 0, 0],
[0, math.cos(math.radians(y)),-math.sin(math.radians(y)), 0],
[0, math.sin(math.radians(y)), math.cos(math.radians(y)), 0],
[0, 0, 0, 1]
]
2012-08-08 07:38:48 +00:00
x = v[1]
2012-08-08 07:58:09 +00:00
matrix3 = [
[math.cos(math.radians(x)), 0,-math.sin(math.radians(x)), 0],
[0, 1, 0, 0],
[math.sin(math.radians(x)), 0, math.cos(math.radians(x)), 0],
[0, 0, 0, 1]
]
return self.transform(matrix1).transform(matrix2).transform(matrix3)
2012-08-08 07:58:09 +00:00
def scale(self, v = [0, 0, 0]):
matrix = [
[v[0], 0, 0, 0],
[0, v[1], 0, 0],
[0, 0, v[2], 0],
[0, 0, 0, 1]
]
return self.transform(matrix)
2012-08-08 07:38:48 +00:00
def transform(self, m = I):
s = stl()
2012-08-08 07:58:09 +00:00
s.facets = [applymatrix(i, m) for i in self.facets]
2012-08-08 07:38:48 +00:00
s.insolid = 0
s.infacet = 0
s.inloop = 0
s.facetloc = 0
s.name = self.name
for facet in s.facets:
2012-08-08 07:58:09 +00:00
s.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
s.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
return s
2012-08-08 07:38:48 +00:00
def export(self, f = sys.stdout):
f.write("solid "+self.name+"\n")
for i in self.facets:
2012-08-08 07:38:48 +00:00
f.write(" facet normal "+" ".join(map(str, i[0]))+"\n")
f.write(" outer loop"+"\n")
for j in i[1]:
2012-08-08 07:38:48 +00:00
f.write(" vertex "+" ".join(map(str, j))+"\n")
f.write(" endloop"+"\n")
f.write(" endfacet"+"\n")
f.write("endsolid "+self.name+"\n")
f.flush()
2012-08-08 07:38:48 +00:00
def parseline(self, l):
l = l.strip()
if l.startswith("solid"):
2012-08-08 07:38:48 +00:00
self.insolid = 1
self.name = l[6:]
#print self.name
elif l.startswith("endsolid"):
2012-08-08 07:38:48 +00:00
self.insolid = 0
return 0
elif l.startswith("facet normal"):
2012-08-08 07:58:09 +00:00
l = l.replace(", ",".")
2012-08-08 07:38:48 +00:00
self.infacet = 11
self.facetloc = 0
2012-08-08 07:58:09 +00:00
self.facet = [[0, 0, 0],[[0, 0, 0],[0, 0, 0],[0, 0, 0]]]
2012-08-08 07:38:48 +00:00
self.facet[0]=map(float, l.split()[2:])
elif l.startswith("endfacet"):
2012-08-08 07:38:48 +00:00
self.infacet = 0
self.facets+=[self.facet]
2012-08-08 07:38:48 +00:00
facet = self.facet
2012-08-08 07:58:09 +00:00
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
elif l.startswith("vertex"):
2012-08-08 07:58:09 +00:00
l = l.replace(", ",".")
2012-08-08 07:38:48 +00:00
self.facet[1][self.facetloc]=map(float, l.split()[1:])
self.facetloc+=1
return 1
2012-08-08 07:38:48 +00:00
if __name__ == "__main__":
s = stl("../../Downloads/frame-vertex-neo-foot-x4.stl")
for i in xrange(11, 11):
working = s.facets[:]
for j in reversed(sorted(s.facetsminz)):
if(j[0]>i):
working.remove(j[1])
else:
break
for j in (sorted(s.facetsmaxz)):
if(j[0]<i):
working.remove(j[1])
else:
break
2012-08-08 07:38:48 +00:00
print i, len(working)
2012-08-08 07:58:09 +00:00
emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl", s.facets, "emitted_object")
#stl("../prusamendel/stl/mendelplate.stl")