# GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import struct class ThreeDeeParseError(Exception): pass class ThreeDee(): """ 3D model parser base class. Derrived classes are used for basic analysis of 3D models, and are not intended to be used for 3D rendering. """ def __init__(self, fileob): self.verts = [] self.average = [0, 0, 0] self.min = [None, None, None] self.max = [None, None, None] self.width = 0 # x axis self.depth = 0 # y axis self.height = 0 # z axis self.load(fileob) if not len(self.verts): raise ThreeDeeParseError("Empty model.") for vector in self.verts: for i in range(3): num = vector[i] self.average[i] += num if not self.min[i]: self.min[i] = num self.max[i] = num else: if self.min[i] > num: self.min[i] = num if self.max[i] < num: self.max[i] = num for i in range(3): self.average[i]/=len(self.verts) self.width = abs(self.min[0] - self.max[0]) self.depth = abs(self.min[1] - self.max[1]) self.height = abs(self.min[2] - self.max[2]) def load(self, fileob): """Override this method in your subclass.""" pass class ObjModel(ThreeDee): """ Parser for textureless wavefront obj files. File format reference: http://en.wikipedia.org/wiki/Wavefront_.obj_file """ def __vector(self, line, expected=3): nums = map(float, line.strip().split(" ")[1:]) return tuple(nums[:expected]) def load(self, fileob): for line in fileob: line = line.strip() if line[0] == "v": self.verts.append(self.__vector(line)) class BinaryStlModel(ThreeDee): """ Parser for ascii-encoded stl files. File format reference: http://en.wikipedia.org/wiki/STL_%28file_format%29#Binary_STL """ def load(self, fileob): fileob.seek(80) # skip the header count = struct.unpack("