Convertisseur STL vers SCAD

De Wiki LOGre
Aller à : navigation, rechercher


Convertisseur de fichier STL en fichier SCAD.

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
""" STL to SCAD converter.
 
This code is based on Riham javascript code.
See http://www.thingiverse.com/thing:62666
 
Ascii STL file:
 
solid _40x10
    facet normal 0.000000e+000 0.000000e+000 1.000000e+000
        outer loop
            vertex 1.286803e+001 2.957990e+001 1.200000e+001
            vertex 1.173648e+001 2.984808e+001 1.200000e+001
            vertex 1.115715e+001 2.953001e+001 1.200000e+001
        endloop
    endfacet
    facet normal 0.000000e+000 0.000000e+000 1.000000e+000
        outer loop
            vertex 1.115715e+001 2.953001e+001 1.200000e+001
            vertex 1.173648e+001 2.984808e+001 1.200000e+001
            vertex 1.058145e+001 2.998308e+001 1.200000e+001
        endloop
    endfacet
    ...
ensolid
 
Binary STL file:
 
"""
 
import re
import sys
import struct
import os.path
 
 
def parseAscii(inputFile):
    """
    """
    inputFile.seek(0)
    inputStr = inputFile.read()
 
    modules = []
 
    solidName = None
    vertices = None
    triangles = None
    triangle = None
 
    for solidStr in re.findall(r"solid\s(.*?)endsolid", inputStr, re.S):
        solidName = re.match(r"^(.*)$", solidStr, re.M).group(0)
        print "Processing object %s..." % solidName
        vertices = []
        triangles = []
        for facetStr in re.findall(r"facet\s(.*?)endfacet", solidStr, re.S):
            for outerLoopStr in re.findall(r"outer\sloop(.*?)endloop", facetStr, re.S):
                triangle = []
                for vertexStr in re.findall(r"vertex\s(.*)$", outerLoopStr, re.M):
                    vertex = [float(coord) for coord in vertexStr.split()]
                    try:
                        triangle.append(vertices.index(vertex))
                    except ValueError:
                        vertices.append(str(vertex))
                        triangle.append(len(vertices) - 1)
            triangles.append(str(triangle))
        modules.append((solidName, vertices, triangles))
 
        return modules
 
 
def parseBinary(inputFile, solidName="stl2scad"):
    """
    """
 
    # Skip header
    inputFile.seek(80)
 
    nbTriangles = struct.unpack("<I", inputFile.read(4))[0]
    print "found %d triangles" % nbTriangles
 
    modules = []
    vertices = []
    triangles = []
 
    triangle = None
 
    # Iterate over triangles
    for i in range(nbTriangles):
        triangle = []
 
        # Skip normal vector (3x uint32)
        inputFile.seek(3*4, 1)
 
        # Iterate over vertices
        for j in range(3):
            vertex = struct.unpack("<fff", inputFile.read(3*4))
            #print repr(s), repr(vertex)
            try:
                triangle.append(vertices.index(vertex))
            except ValueError:
                vertices.append(str(list(vertex)))
                triangle.append(len(vertices) - 1)
 
        triangles.append(str(triangle))
 
        # Skip byte count
        inputFile.seek(2, 1)
 
    modules.append((solidName, vertices, triangles))
 
    return modules
 
 
def convert(outputFile, modules):
    """
    """
    for solidName, vertices, triangles in modules:
        points_ = ",\n\t\t\t".join(vertices)
        triangles_ = ",\n\t\t\t".join(triangles)
        module = "module %s() {\n\tpolyhedron(\n\t\tpoints=[\n\t\t\t%s\n\t\t],\n\t\ttriangles=[\n\t\t\t%s\n\t\t]\n\t);\n}\n\n\n%s();\n" % (solidName, points_, triangles_, solidName)
        outputFile.write(module)
 
    outputFile.close()
 
 
def main():
    inputFileName = sys.argv[1]
    inputFile = file(inputFileName)
 
    # Check if ascii or binary
    if inputFile.read(5) == "solid":
        print "ascii file"
        modules = parseAscii(inputFile)
    else:
        print "binary file"
        modules = parseBinary(inputFile)
 
    outputFileName = "%s%s%s" % (os.path.splitext(inputFileName)[0], os.path.extsep, "scad")
    outputFile = file(outputFileName, "w")
    convert(outputFile, modules)
 
    print "%s saved" % outputFileName
 
 
if __name__ == "__main__":
    main()