polyhedron_3d.py revision e4a094fa5446f7e5e226a3b10fdb7bf676808863
'''
Copyright (C) 2007 John Beard john.j.beard@gmail.com
##This extension draws 3d objects from a Wavefront .obj 3D file stored in a local folder
##Many settings for appearance, lighting, rotation, etc are available.
# ^y
# |
# __--``| |_--``| __--
# __--`` | __--``| |_--``
# | z | | |_--``|
# | <----|--------|-----_0-----|----------------
# | | |_--`` | |
# | __--`` <-``| |_--``
# |__--`` x |__--``|
# IMAGE PLANE SCENE|
# |
#Vertices are given as "v" followed by three numbers (x,y,z).
#All files need a vertex list
#v x.xxx y.yyy z.zzz
#Faces are given by a list of vertices
#(vertex 1 is the first in the list above, 2 the second, etc):
#f 1 2 3
#Edges are given by a list of vertices. These will be broken down
#into adjacent pairs automatically.
#l 1 2 3
#Faces are rendered according to the painter's algorithm and perhaps
#back-face culling, if selected. The parameter to sort the faces by
#is user-selectable between max, min and average z-value of the vertices
######LICENCE#######
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
'''
# standard library
import sys
import re
from math import *
# local library
import inkex
import simplestyle
# third party
try:
from numpy import *
except:
inkex.errormsg(_("Failed to import the numpy module. This module is required by this extension. Please install it and try again. On a Debian-like system this can be done with the command 'sudo apt-get install python-numpy'."))
#FILE IO ROUTINES
def get_filename(self_options):
else:
return file
if __name__ == '__main__':
else:
return path
#regular expressions
getname = '(.[nN]ame:\\s*)(.*)'
getedgeline = '(l\\s+)(.*)'
getfaceline = '(f\\s+)(.*)'
getnextint = '(\\d+)([/\\d]*)(.*)'#we need to deal with 123\343\123 or 123\\456 as equivalent to 123 (we are ignoring the other options in the obj file)
if m:
if m: #we have a valid vertex
if m: #we have a line beginning 'l '
vtxlist = [] #buffer
while line:
if m2:
else:
line = None
if m: #we have a line beginning 'f '
vtxlist = []#buffer
while line:
if m2:
else:
line = None
#RENDERING AND SVG OUTPUT FUNCTIONS
style = { 'stroke': '#000000', 'stroke-width':str(st.th), 'fill': st.fill, 'stroke-opacity':st.s_opac, 'fill-opacity':st.f_opac}
if i == 0:#for first point
d = 'M'#move to
else:
d = d + 'L'#line to
d = d + 'z' #close the polygon
if shading:
st.fill = get_darkened_colour(fill_col, face[1]/pi)#darken proportionally to angle to lighting vector
else:
def get_darkened_colour( (r,g,b), factor):
#return a hex triplet of colour, reduced in lightness proportionally to a value between 0 and 1
def make_rotation_log(options):
#makes a string recording the axes and angles of each roation, so an object can be repeated
#MATHEMATICAL FUNCTIONS
def get_normal( pts, face): #returns the normal vector for the plane passing though the first three elements of face of pts
#n = pt[0]->pt[1] x pt[0]->pt[3]
def get_unit_normal(pts, face, cw_wound): #returns the unit normal for the plane passing through the first three points of face, taking account of winding
if cw_wound:
else:
if axis == 'x':
elif axis == 'y':
elif axis == 'z':
return matrix
[ 0 , 0 , 1 ]]))
[ 0 , 1 , 0 ],
transformed_pts = []
transformed_pts.append((trans_mat * mat(vtx).T).T.tolist()[0] )#transform the points at add to the list
return transformed_pts
return max_z
return min_z
sum = 0
def get_z_sort_param(pts, face, method): #returns the z-sorting parameter specified by 'method' ('max', 'min', 'cent')
z_sort_param = ''
if method == 'max':
elif method == 'min':
else:
return z_sort_param
#OBJ DATA MANIPULATION
del list[i]
else:
return list
edge_list = []
return remove_duplicates(edge_list)
self.r = 2
#edges can be generated from this information
else:
else:
else:
#MODEL FILE SETTINGS
#VEIW SETTINGS
#STYLE SETTINGS
#INITIALISE AND LOAD DATA
#INKSCAPE GROUP TO CONTAIN THE POLYHEDRON
#Put in in the centre of the current view
#we will put all the rotations in the object name, so it can be repeated in
'transform':poly_transform }
#TRANFORMATION OF THE OBJECT (ROTATION, SCALE, ETC)
trans_mat = trans_mat*so.scl #scale by linear factor (do this only after the transforms to reduce round-off)
transformed_pts = get_transformed_pts(obj.vtx, trans_mat) #the points as projected in the z-axis onto the viewplane
#RENDERING OF THE OBJECT
draw_SVG_dot([transformed_pts[i][0],transformed_pts[i][1]], st, 'Point'+str(i), poly)#plot points using transformed_pts x and y coords
else:#we already have an edge list
z_list = []
z_list.append((z_sort_param, angle, norm, i))#record the maximum z-value of the face and angle to light, along with the face ID and normal
else:#we cannot generate a list of faces from the edges without a lot of computation
inkex.errormsg(_('Face Data Not Found. Ensure file contains face data, and check the file is imported as "Face-Specified" under the "Model File" tab.\n'))
else:
if __name__ == '__main__':
e = Poly_3D()
e.affect()
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99