Selection of Face of a STL by Face Normal value Threshold

2024/7/5 11:32:54

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

Answer

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 structdef Unique(inputList):""" Given an M x N list, this function gets the unique rows by treating allM Ntuples as single objects. This function also returns the indexingto convert the unique returned list back to the original non-unique list."""hashTable=dict()indexList=[]uniqueList=[]indx=0for ntuple in inputList:if not ntuple in hashTable:hashTable[ntuple]=indxindexList.append(indx)uniqueList.append(ntuple)indx+=1else:indexList.append(hashTable.get(ntuple))      return uniqueList, indexListdef IsBinarySTL(filename):try:with open(filename,'r') as f:test=f.readline()except UnicodeDecodeError:return Trueif len(test) < 5:return Trueelif test[0:5].lower() == 'solid':return False  # ASCII STLelse:return Truedef 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 outputListdef GetListFromBinary(filename):""" Returns vertex listing from binary STL file """outputList=[]with open(filename,'rb') as f:f.seek(80) # skip headernFacets=struct.unpack('I',f.read(4))[0] # number of facets in piecefor i in range(nFacets):f.seek(12,1) # skip normaloutputList.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 attributereturn outputListif 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 characters2.) length of attributes must be equal to length of facets3.) attributes must be integers"""nspaces = 80 - len(header)header += nspaces*'\0'nFacets = np.shape(facets)[0]stl = vertices[facets,:].tolist()with open(filename,'wb') as f: # binaryf.write(struct.pack('80s', header.encode('utf-8'))) # headerf.write(struct.pack('I',nFacets)) # number of facetsfor i in range(nFacets):f.write(struct.pack('fff',0,0,0)) # normals set to 0for 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 filenormals = GetNormals(vertices, facets)  # compute normals# Get some value related to normalsattributes = []for i in range(np.shape(normals)[0]):attributes.append(int(255*np.sum(normals[i])**2))# Write new stl fileWriteSTL("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: enter image description here

https://en.xdnf.cn/q/120208.html

Related Q&A

Python , Changing a font size of a string variable

I have a variable that gets sent to a email as text but the text is all pretty much a standard size with everything the same. I would like to add some emphasis to it as well as make it bigger and make …

Python http.server command gives Syntax Error [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.This question was caused by a typo or a problem that can no longer be reproduced. While similar q…

If statement to check if the value of a variable is in a JSON file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to repro…

Assign variables to a pandas dataframe when specific cell is empty

I am assigning some variables to values from a data frame. The data frame created using this code data = [[tom, 10], ["", 15], [juli, 14]] df = pd.DataFrame(data, columns=[Name, Age])So after…

Try Except for one variable in multiple variables

I am reading every row in a dataframe and assigning its values in each column to the variables The dataframe created using this code data = [[tom, 10], [, 15], [juli, 14]] df = pd.DataFrame(data, colum…

Print method invalid syntax reversing a string [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.This question was caused by a typo or a problem that can no longer be reproduced. While similar q…

How QRegularExpression can be passed to Qt::MatchRegularExpression

I am trying this sample code that I found which is really really good. I am also trying to figure out the same thing to find an item and scroll to it, but this time I wanted to match the the string whi…

Python list rearrange the elements in a required order

My main list has 44 names as elements. I want to rearrange them in a specific order. I am giving here an example. Note that elements in my actual list are some technical names. No way related to what I…

GMB API accounts.locations.reviews.list

Can i get source code to get reviews using gmb python code also heard mybusiness is discontinued. I tried using my business api is discontinued can i get the implementation process to look for extract…

How to get words from an online text archive such as pastebin?

Im trying to get the words(users) from a text file hosted online, such as from www.site.com/mytextfile.txt or pastebin.com/raw/1111111. I will have multiple "users", one in each line. My code…