# ##### BEGIN GPL LICENSE BLOCK ##### # # This program 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 2 # of the License, or (at your option) any later version. # # This program 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # ##### END GPL LICENSE BLOCK ##### # """ Import and export STL files Used as a blender script, it load all the stl files in the scene: blender --python stl_utils.py -- file1.stl file2.stl file3.stl ... """ # TODO: endien class ListDict(dict): """ Set struct with order. You can: - insert data into without doubles - get the list of data in insertion order with self.list Like collections.OrderedDict, but quicker, can be replaced if ODict is optimised. """ def __init__(self): dict.__init__(self) self.list = [] self._len = 0 def add(self, item): """ Add a value to the Set, return its position in it. """ value = self.setdefault(item, self._len) if value == self._len: self.list.append(item) self._len += 1 return value # an stl binary file is # - 80 bytes of description # - 4 bytes of size (unsigned int) # - size triangles : # # - 12 bytes of normal # - 9 * 4 bytes of coordinate (3*3 floats) # - 2 bytes of garbage (usually 0) BINARY_HEADER = 80 BINARY_STRIDE = 12 * 4 + 2 def _header_version(): import bpy return "Exported from Blender-" + bpy.app.version_string def _is_ascii_file(data): """ This function returns True if the data represents an ASCII file. Please note that a False value does not necessary means that the data represents a binary file. It can be a (very *RARE* in real life, but can easily be forged) ascii file. """ import os import struct # Skip header... data.seek(BINARY_HEADER) size = struct.unpack('>> tris, tri_nors, pts = read_stl(filepath) >>> pts = list(pts) >>> >>> # print the coordinate of the triangle n >>> print(pts[i] for i in tris[n]) """ import time start_time = time.process_time() tris, tri_nors, pts = [], [], ListDict() with open(filepath, 'rb') as data: # check for ascii or binary gen = _ascii_read if _is_ascii_file(data) else _binary_read for nor, pt in gen(data): # Add the triangle and the point. # If the point is already in the list of points, the # index returned by pts.add() will be the one from the # first equal point inserted. tris.append([pts.add(p) for p in pt]) tri_nors.append(nor) print('Import finished in %.4f sec.' % (time.process_time() - start_time)) return tris, tri_nors, pts.list if __name__ == '__main__': import sys import bpy from io_mesh_stl import blender_utils filepaths = sys.argv[sys.argv.index('--') + 1:] for filepath in filepaths: objName = bpy.path.display_name(filepath) tris, pts = read_stl(filepath) blender_utils.create_and_link_mesh(objName, tris, pts)