Selection of Face of a STL by Face Normal value Threshold












-2















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










share|improve this question

























  • 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
















-2















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










share|improve this question

























  • 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














-2












-2








-2








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










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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



















  • 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












1 Answer
1






active

oldest

votes


















0














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:
enter image description here






share|improve this answer

























    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    0














    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:
    enter image description here






    share|improve this answer






























      0














      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:
      enter image description here






      share|improve this answer




























        0












        0








        0







        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:
        enter image description here






        share|improve this 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 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:
        enter image description here







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 7 at 15:03

























        answered Jan 3 at 21:07









        A.ComerA.Comer

        31518




        31518
































            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith