Selection of Face of a STL by Face Normal value Threshold
I want to write a script in Python which can generate facegroups in a STL as per the Face Normal value condition. For example, Provided is the snap of Stl, Different colour signifies the face group containing the triangular faces satisfying my given face normal threshold. Is there any simple way to do this in python?
Face Group STL
python mesh meshlab numpy-stl
add a comment |
I want to write a script in Python which can generate facegroups in a STL as per the Face Normal value condition. For example, Provided is the snap of Stl, Different colour signifies the face group containing the triangular faces satisfying my given face normal threshold. Is there any simple way to do this in python?
Face Group STL
python mesh meshlab numpy-stl
What exactly are you wanting to do? Change the 2-byte attribute of the .stl file to some value dependent on the facet normal?
– A.Comer
Jan 2 at 16:29
Yes @A.Comer. I want to group triangles depending on curvature criteria
– Swagatam Sengupta
Jan 3 at 4:28
add a comment |
I want to write a script in Python which can generate facegroups in a STL as per the Face Normal value condition. For example, Provided is the snap of Stl, Different colour signifies the face group containing the triangular faces satisfying my given face normal threshold. Is there any simple way to do this in python?
Face Group STL
python mesh meshlab numpy-stl
I want to write a script in Python which can generate facegroups in a STL as per the Face Normal value condition. For example, Provided is the snap of Stl, Different colour signifies the face group containing the triangular faces satisfying my given face normal threshold. Is there any simple way to do this in python?
Face Group STL
python mesh meshlab numpy-stl
python mesh meshlab numpy-stl
edited Jan 9 at 12:12
Ilio Catallo
2,1171637
2,1171637
asked Jan 2 at 12:07


Swagatam SenguptaSwagatam Sengupta
86
86
What exactly are you wanting to do? Change the 2-byte attribute of the .stl file to some value dependent on the facet normal?
– A.Comer
Jan 2 at 16:29
Yes @A.Comer. I want to group triangles depending on curvature criteria
– Swagatam Sengupta
Jan 3 at 4:28
add a comment |
What exactly are you wanting to do? Change the 2-byte attribute of the .stl file to some value dependent on the facet normal?
– A.Comer
Jan 2 at 16:29
Yes @A.Comer. I want to group triangles depending on curvature criteria
– Swagatam Sengupta
Jan 3 at 4:28
What exactly are you wanting to do? Change the 2-byte attribute of the .stl file to some value dependent on the facet normal?
– A.Comer
Jan 2 at 16:29
What exactly are you wanting to do? Change the 2-byte attribute of the .stl file to some value dependent on the facet normal?
– A.Comer
Jan 2 at 16:29
Yes @A.Comer. I want to group triangles depending on curvature criteria
– Swagatam Sengupta
Jan 3 at 4:28
Yes @A.Comer. I want to group triangles depending on curvature criteria
– Swagatam Sengupta
Jan 3 at 4:28
add a comment |
1 Answer
1
active
oldest
votes
I'm sure there's a python library to load stl files, but I've always just written my own, since the file format is pretty simple (see the Wikipedia article for file format description).
Here is my code to read the stl file:
import numpy as np
import struct
def Unique(inputList):
"""
Given an M x N list, this function gets the unique rows by treating all
M Ntuples as single objects. This function also returns the indexing
to convert the unique returned list back to the original non-unique list.
"""
hashTable=dict()
indexList=
uniqueList=
indx=0
for ntuple in inputList:
if not ntuple in hashTable:
hashTable[ntuple]=indx
indexList.append(indx)
uniqueList.append(ntuple)
indx+=1
else:
indexList.append(hashTable.get(ntuple))
return uniqueList, indexList
def IsBinarySTL(filename):
try:
with open(filename,'r') as f:
test=f.readline()
except UnicodeDecodeError:
return True
if len(test) < 5:
return True
elif test[0:5].lower() == 'solid':
return False # ASCII STL
else:
return True
def ReadSTL(filename):
""" Returns numpy arrays for vertices and facet indexing """
def GetListFromASCII(filename):
""" Returns vertex listing from ASCII STL file """
outputList=
with open(filename,'r') as f:
lines=[line.split() for line in f.readlines()]
for line in lines:
if line[0] == 'vertex':
outputList.append(tuple([float(x) for x in line[1:]]))
return outputList
def GetListFromBinary(filename):
""" Returns vertex listing from binary STL file """
outputList=
with open(filename,'rb') as f:
f.seek(80) # skip header
nFacets=struct.unpack('I',f.read(4))[0] # number of facets in piece
for i in range(nFacets):
f.seek(12,1) # skip normal
outputList.append(struct.unpack('fff',f.read(12))) # append each vertex triple to list (each facet has 3 vertices)
outputList.append(struct.unpack('fff',f.read(12)))
outputList.append(struct.unpack('fff',f.read(12)))
f.seek(2,1) # skip attribute
return outputList
if IsBinarySTL(filename):
vertexList = GetListFromBinary(filename)
else:
vertexList = GetListFromASCII(filename)
coords, tempindxs = Unique(vertexList)
indxs = list()
templist = list()
for i in range(len(tempindxs)):
if (i > 0 ) and not (i % 3):
indxs.append(templist)
templist = list()
templist.append(tempindxs[i])
indxs.append(templist)
return np.array(coords), np.array(indxs)
And here is code to compute the facet normals (assuming right-hand-rule)
def GetNormals(vertices, facets):
""" Returns normals for each facet of mesh """
u = vertices[facets[:,1],:] - vertices[facets[:,0],:]
v = vertices[facets[:,2],:] - vertices[facets[:,0],:]
normals = np.cross(u,v)
norms = np.sqrt(np.sum(normals*normals, axis=1))
return normals/norms[:, np.newaxis]
Finally, code to write out the stl file (assuming a list of attributes for each facet):
def WriteSTL(filename, vertices, facets, attributes, header):
"""
Writes vertices and facets to an stl file. Notes:
1.) header can not be longer than 80 characters
2.) length of attributes must be equal to length of facets
3.) attributes must be integers
"""
nspaces = 80 - len(header)
header += nspaces*''
nFacets = np.shape(facets)[0]
stl = vertices[facets,:].tolist()
with open(filename,'wb') as f: # binary
f.write(struct.pack('80s', header.encode('utf-8'))) # header
f.write(struct.pack('I',nFacets)) # number of facets
for i in range(nFacets):
f.write(struct.pack('fff',0,0,0)) # normals set to 0
for j in range(3):
f.write(struct.pack('fff',stl[i][j][0], stl[i][j][1], stl[i][j][2])) # 3 vertices per facet
f.write(struct.pack("H", attributes[i])) # 2-byte attribute
Putting this all together, you can do something like the following:
if __name__ == "__main__":
filename = "bunny.stl"
vertices, facets = ReadSTL(filename) # parse stl file
normals = GetNormals(vertices, facets) # compute normals
# Get some value related to normals
attributes =
for i in range(np.shape(normals)[0]):
attributes.append(int(255*np.sum(normals[i])**2))
# Write new stl file
WriteSTL("output.stl", vertices, facets, attributes, "stlheader")
this code snippet reads an stl file, computes the normals, and then assigns an attribute value based on the squared-sum of each normal (note that the attribute must be an integer).
The input and output of this script look like the following:
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54006078%2fselection-of-face-of-a-stl-by-face-normal-value-threshold%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I'm sure there's a python library to load stl files, but I've always just written my own, since the file format is pretty simple (see the Wikipedia article for file format description).
Here is my code to read the stl file:
import numpy as np
import struct
def Unique(inputList):
"""
Given an M x N list, this function gets the unique rows by treating all
M Ntuples as single objects. This function also returns the indexing
to convert the unique returned list back to the original non-unique list.
"""
hashTable=dict()
indexList=
uniqueList=
indx=0
for ntuple in inputList:
if not ntuple in hashTable:
hashTable[ntuple]=indx
indexList.append(indx)
uniqueList.append(ntuple)
indx+=1
else:
indexList.append(hashTable.get(ntuple))
return uniqueList, indexList
def IsBinarySTL(filename):
try:
with open(filename,'r') as f:
test=f.readline()
except UnicodeDecodeError:
return True
if len(test) < 5:
return True
elif test[0:5].lower() == 'solid':
return False # ASCII STL
else:
return True
def ReadSTL(filename):
""" Returns numpy arrays for vertices and facet indexing """
def GetListFromASCII(filename):
""" Returns vertex listing from ASCII STL file """
outputList=
with open(filename,'r') as f:
lines=[line.split() for line in f.readlines()]
for line in lines:
if line[0] == 'vertex':
outputList.append(tuple([float(x) for x in line[1:]]))
return outputList
def GetListFromBinary(filename):
""" Returns vertex listing from binary STL file """
outputList=
with open(filename,'rb') as f:
f.seek(80) # skip header
nFacets=struct.unpack('I',f.read(4))[0] # number of facets in piece
for i in range(nFacets):
f.seek(12,1) # skip normal
outputList.append(struct.unpack('fff',f.read(12))) # append each vertex triple to list (each facet has 3 vertices)
outputList.append(struct.unpack('fff',f.read(12)))
outputList.append(struct.unpack('fff',f.read(12)))
f.seek(2,1) # skip attribute
return outputList
if IsBinarySTL(filename):
vertexList = GetListFromBinary(filename)
else:
vertexList = GetListFromASCII(filename)
coords, tempindxs = Unique(vertexList)
indxs = list()
templist = list()
for i in range(len(tempindxs)):
if (i > 0 ) and not (i % 3):
indxs.append(templist)
templist = list()
templist.append(tempindxs[i])
indxs.append(templist)
return np.array(coords), np.array(indxs)
And here is code to compute the facet normals (assuming right-hand-rule)
def GetNormals(vertices, facets):
""" Returns normals for each facet of mesh """
u = vertices[facets[:,1],:] - vertices[facets[:,0],:]
v = vertices[facets[:,2],:] - vertices[facets[:,0],:]
normals = np.cross(u,v)
norms = np.sqrt(np.sum(normals*normals, axis=1))
return normals/norms[:, np.newaxis]
Finally, code to write out the stl file (assuming a list of attributes for each facet):
def WriteSTL(filename, vertices, facets, attributes, header):
"""
Writes vertices and facets to an stl file. Notes:
1.) header can not be longer than 80 characters
2.) length of attributes must be equal to length of facets
3.) attributes must be integers
"""
nspaces = 80 - len(header)
header += nspaces*''
nFacets = np.shape(facets)[0]
stl = vertices[facets,:].tolist()
with open(filename,'wb') as f: # binary
f.write(struct.pack('80s', header.encode('utf-8'))) # header
f.write(struct.pack('I',nFacets)) # number of facets
for i in range(nFacets):
f.write(struct.pack('fff',0,0,0)) # normals set to 0
for j in range(3):
f.write(struct.pack('fff',stl[i][j][0], stl[i][j][1], stl[i][j][2])) # 3 vertices per facet
f.write(struct.pack("H", attributes[i])) # 2-byte attribute
Putting this all together, you can do something like the following:
if __name__ == "__main__":
filename = "bunny.stl"
vertices, facets = ReadSTL(filename) # parse stl file
normals = GetNormals(vertices, facets) # compute normals
# Get some value related to normals
attributes =
for i in range(np.shape(normals)[0]):
attributes.append(int(255*np.sum(normals[i])**2))
# Write new stl file
WriteSTL("output.stl", vertices, facets, attributes, "stlheader")
this code snippet reads an stl file, computes the normals, and then assigns an attribute value based on the squared-sum of each normal (note that the attribute must be an integer).
The input and output of this script look like the following:
add a comment |
I'm sure there's a python library to load stl files, but I've always just written my own, since the file format is pretty simple (see the Wikipedia article for file format description).
Here is my code to read the stl file:
import numpy as np
import struct
def Unique(inputList):
"""
Given an M x N list, this function gets the unique rows by treating all
M Ntuples as single objects. This function also returns the indexing
to convert the unique returned list back to the original non-unique list.
"""
hashTable=dict()
indexList=
uniqueList=
indx=0
for ntuple in inputList:
if not ntuple in hashTable:
hashTable[ntuple]=indx
indexList.append(indx)
uniqueList.append(ntuple)
indx+=1
else:
indexList.append(hashTable.get(ntuple))
return uniqueList, indexList
def IsBinarySTL(filename):
try:
with open(filename,'r') as f:
test=f.readline()
except UnicodeDecodeError:
return True
if len(test) < 5:
return True
elif test[0:5].lower() == 'solid':
return False # ASCII STL
else:
return True
def ReadSTL(filename):
""" Returns numpy arrays for vertices and facet indexing """
def GetListFromASCII(filename):
""" Returns vertex listing from ASCII STL file """
outputList=
with open(filename,'r') as f:
lines=[line.split() for line in f.readlines()]
for line in lines:
if line[0] == 'vertex':
outputList.append(tuple([float(x) for x in line[1:]]))
return outputList
def GetListFromBinary(filename):
""" Returns vertex listing from binary STL file """
outputList=
with open(filename,'rb') as f:
f.seek(80) # skip header
nFacets=struct.unpack('I',f.read(4))[0] # number of facets in piece
for i in range(nFacets):
f.seek(12,1) # skip normal
outputList.append(struct.unpack('fff',f.read(12))) # append each vertex triple to list (each facet has 3 vertices)
outputList.append(struct.unpack('fff',f.read(12)))
outputList.append(struct.unpack('fff',f.read(12)))
f.seek(2,1) # skip attribute
return outputList
if IsBinarySTL(filename):
vertexList = GetListFromBinary(filename)
else:
vertexList = GetListFromASCII(filename)
coords, tempindxs = Unique(vertexList)
indxs = list()
templist = list()
for i in range(len(tempindxs)):
if (i > 0 ) and not (i % 3):
indxs.append(templist)
templist = list()
templist.append(tempindxs[i])
indxs.append(templist)
return np.array(coords), np.array(indxs)
And here is code to compute the facet normals (assuming right-hand-rule)
def GetNormals(vertices, facets):
""" Returns normals for each facet of mesh """
u = vertices[facets[:,1],:] - vertices[facets[:,0],:]
v = vertices[facets[:,2],:] - vertices[facets[:,0],:]
normals = np.cross(u,v)
norms = np.sqrt(np.sum(normals*normals, axis=1))
return normals/norms[:, np.newaxis]
Finally, code to write out the stl file (assuming a list of attributes for each facet):
def WriteSTL(filename, vertices, facets, attributes, header):
"""
Writes vertices and facets to an stl file. Notes:
1.) header can not be longer than 80 characters
2.) length of attributes must be equal to length of facets
3.) attributes must be integers
"""
nspaces = 80 - len(header)
header += nspaces*''
nFacets = np.shape(facets)[0]
stl = vertices[facets,:].tolist()
with open(filename,'wb') as f: # binary
f.write(struct.pack('80s', header.encode('utf-8'))) # header
f.write(struct.pack('I',nFacets)) # number of facets
for i in range(nFacets):
f.write(struct.pack('fff',0,0,0)) # normals set to 0
for j in range(3):
f.write(struct.pack('fff',stl[i][j][0], stl[i][j][1], stl[i][j][2])) # 3 vertices per facet
f.write(struct.pack("H", attributes[i])) # 2-byte attribute
Putting this all together, you can do something like the following:
if __name__ == "__main__":
filename = "bunny.stl"
vertices, facets = ReadSTL(filename) # parse stl file
normals = GetNormals(vertices, facets) # compute normals
# Get some value related to normals
attributes =
for i in range(np.shape(normals)[0]):
attributes.append(int(255*np.sum(normals[i])**2))
# Write new stl file
WriteSTL("output.stl", vertices, facets, attributes, "stlheader")
this code snippet reads an stl file, computes the normals, and then assigns an attribute value based on the squared-sum of each normal (note that the attribute must be an integer).
The input and output of this script look like the following:
add a comment |
I'm sure there's a python library to load stl files, but I've always just written my own, since the file format is pretty simple (see the Wikipedia article for file format description).
Here is my code to read the stl file:
import numpy as np
import struct
def Unique(inputList):
"""
Given an M x N list, this function gets the unique rows by treating all
M Ntuples as single objects. This function also returns the indexing
to convert the unique returned list back to the original non-unique list.
"""
hashTable=dict()
indexList=
uniqueList=
indx=0
for ntuple in inputList:
if not ntuple in hashTable:
hashTable[ntuple]=indx
indexList.append(indx)
uniqueList.append(ntuple)
indx+=1
else:
indexList.append(hashTable.get(ntuple))
return uniqueList, indexList
def IsBinarySTL(filename):
try:
with open(filename,'r') as f:
test=f.readline()
except UnicodeDecodeError:
return True
if len(test) < 5:
return True
elif test[0:5].lower() == 'solid':
return False # ASCII STL
else:
return True
def ReadSTL(filename):
""" Returns numpy arrays for vertices and facet indexing """
def GetListFromASCII(filename):
""" Returns vertex listing from ASCII STL file """
outputList=
with open(filename,'r') as f:
lines=[line.split() for line in f.readlines()]
for line in lines:
if line[0] == 'vertex':
outputList.append(tuple([float(x) for x in line[1:]]))
return outputList
def GetListFromBinary(filename):
""" Returns vertex listing from binary STL file """
outputList=
with open(filename,'rb') as f:
f.seek(80) # skip header
nFacets=struct.unpack('I',f.read(4))[0] # number of facets in piece
for i in range(nFacets):
f.seek(12,1) # skip normal
outputList.append(struct.unpack('fff',f.read(12))) # append each vertex triple to list (each facet has 3 vertices)
outputList.append(struct.unpack('fff',f.read(12)))
outputList.append(struct.unpack('fff',f.read(12)))
f.seek(2,1) # skip attribute
return outputList
if IsBinarySTL(filename):
vertexList = GetListFromBinary(filename)
else:
vertexList = GetListFromASCII(filename)
coords, tempindxs = Unique(vertexList)
indxs = list()
templist = list()
for i in range(len(tempindxs)):
if (i > 0 ) and not (i % 3):
indxs.append(templist)
templist = list()
templist.append(tempindxs[i])
indxs.append(templist)
return np.array(coords), np.array(indxs)
And here is code to compute the facet normals (assuming right-hand-rule)
def GetNormals(vertices, facets):
""" Returns normals for each facet of mesh """
u = vertices[facets[:,1],:] - vertices[facets[:,0],:]
v = vertices[facets[:,2],:] - vertices[facets[:,0],:]
normals = np.cross(u,v)
norms = np.sqrt(np.sum(normals*normals, axis=1))
return normals/norms[:, np.newaxis]
Finally, code to write out the stl file (assuming a list of attributes for each facet):
def WriteSTL(filename, vertices, facets, attributes, header):
"""
Writes vertices and facets to an stl file. Notes:
1.) header can not be longer than 80 characters
2.) length of attributes must be equal to length of facets
3.) attributes must be integers
"""
nspaces = 80 - len(header)
header += nspaces*''
nFacets = np.shape(facets)[0]
stl = vertices[facets,:].tolist()
with open(filename,'wb') as f: # binary
f.write(struct.pack('80s', header.encode('utf-8'))) # header
f.write(struct.pack('I',nFacets)) # number of facets
for i in range(nFacets):
f.write(struct.pack('fff',0,0,0)) # normals set to 0
for j in range(3):
f.write(struct.pack('fff',stl[i][j][0], stl[i][j][1], stl[i][j][2])) # 3 vertices per facet
f.write(struct.pack("H", attributes[i])) # 2-byte attribute
Putting this all together, you can do something like the following:
if __name__ == "__main__":
filename = "bunny.stl"
vertices, facets = ReadSTL(filename) # parse stl file
normals = GetNormals(vertices, facets) # compute normals
# Get some value related to normals
attributes =
for i in range(np.shape(normals)[0]):
attributes.append(int(255*np.sum(normals[i])**2))
# Write new stl file
WriteSTL("output.stl", vertices, facets, attributes, "stlheader")
this code snippet reads an stl file, computes the normals, and then assigns an attribute value based on the squared-sum of each normal (note that the attribute must be an integer).
The input and output of this script look like the following:
I'm sure there's a python library to load stl files, but I've always just written my own, since the file format is pretty simple (see the Wikipedia article for file format description).
Here is my code to read the stl file:
import numpy as np
import struct
def Unique(inputList):
"""
Given an M x N list, this function gets the unique rows by treating all
M Ntuples as single objects. This function also returns the indexing
to convert the unique returned list back to the original non-unique list.
"""
hashTable=dict()
indexList=
uniqueList=
indx=0
for ntuple in inputList:
if not ntuple in hashTable:
hashTable[ntuple]=indx
indexList.append(indx)
uniqueList.append(ntuple)
indx+=1
else:
indexList.append(hashTable.get(ntuple))
return uniqueList, indexList
def IsBinarySTL(filename):
try:
with open(filename,'r') as f:
test=f.readline()
except UnicodeDecodeError:
return True
if len(test) < 5:
return True
elif test[0:5].lower() == 'solid':
return False # ASCII STL
else:
return True
def ReadSTL(filename):
""" Returns numpy arrays for vertices and facet indexing """
def GetListFromASCII(filename):
""" Returns vertex listing from ASCII STL file """
outputList=
with open(filename,'r') as f:
lines=[line.split() for line in f.readlines()]
for line in lines:
if line[0] == 'vertex':
outputList.append(tuple([float(x) for x in line[1:]]))
return outputList
def GetListFromBinary(filename):
""" Returns vertex listing from binary STL file """
outputList=
with open(filename,'rb') as f:
f.seek(80) # skip header
nFacets=struct.unpack('I',f.read(4))[0] # number of facets in piece
for i in range(nFacets):
f.seek(12,1) # skip normal
outputList.append(struct.unpack('fff',f.read(12))) # append each vertex triple to list (each facet has 3 vertices)
outputList.append(struct.unpack('fff',f.read(12)))
outputList.append(struct.unpack('fff',f.read(12)))
f.seek(2,1) # skip attribute
return outputList
if IsBinarySTL(filename):
vertexList = GetListFromBinary(filename)
else:
vertexList = GetListFromASCII(filename)
coords, tempindxs = Unique(vertexList)
indxs = list()
templist = list()
for i in range(len(tempindxs)):
if (i > 0 ) and not (i % 3):
indxs.append(templist)
templist = list()
templist.append(tempindxs[i])
indxs.append(templist)
return np.array(coords), np.array(indxs)
And here is code to compute the facet normals (assuming right-hand-rule)
def GetNormals(vertices, facets):
""" Returns normals for each facet of mesh """
u = vertices[facets[:,1],:] - vertices[facets[:,0],:]
v = vertices[facets[:,2],:] - vertices[facets[:,0],:]
normals = np.cross(u,v)
norms = np.sqrt(np.sum(normals*normals, axis=1))
return normals/norms[:, np.newaxis]
Finally, code to write out the stl file (assuming a list of attributes for each facet):
def WriteSTL(filename, vertices, facets, attributes, header):
"""
Writes vertices and facets to an stl file. Notes:
1.) header can not be longer than 80 characters
2.) length of attributes must be equal to length of facets
3.) attributes must be integers
"""
nspaces = 80 - len(header)
header += nspaces*''
nFacets = np.shape(facets)[0]
stl = vertices[facets,:].tolist()
with open(filename,'wb') as f: # binary
f.write(struct.pack('80s', header.encode('utf-8'))) # header
f.write(struct.pack('I',nFacets)) # number of facets
for i in range(nFacets):
f.write(struct.pack('fff',0,0,0)) # normals set to 0
for j in range(3):
f.write(struct.pack('fff',stl[i][j][0], stl[i][j][1], stl[i][j][2])) # 3 vertices per facet
f.write(struct.pack("H", attributes[i])) # 2-byte attribute
Putting this all together, you can do something like the following:
if __name__ == "__main__":
filename = "bunny.stl"
vertices, facets = ReadSTL(filename) # parse stl file
normals = GetNormals(vertices, facets) # compute normals
# Get some value related to normals
attributes =
for i in range(np.shape(normals)[0]):
attributes.append(int(255*np.sum(normals[i])**2))
# Write new stl file
WriteSTL("output.stl", vertices, facets, attributes, "stlheader")
this code snippet reads an stl file, computes the normals, and then assigns an attribute value based on the squared-sum of each normal (note that the attribute must be an integer).
The input and output of this script look like the following:
edited Jan 7 at 15:03
answered Jan 3 at 21:07
A.ComerA.Comer
31518
31518
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54006078%2fselection-of-face-of-a-stl-by-face-normal-value-threshold%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What exactly are you wanting to do? Change the 2-byte attribute of the .stl file to some value dependent on the facet normal?
– A.Comer
Jan 2 at 16:29
Yes @A.Comer. I want to group triangles depending on curvature criteria
– Swagatam Sengupta
Jan 3 at 4:28