iorodeo avatar iorodeo committed 54eadbb Merge

Merged heads.

Comments (0)

Files changed (7)

 *.stl
 *.pkl
 *.dxf
+*.komodo*
+*.egg-info
+build
+dist
+.komodo*

py2scad/__init__.py

 """
-Copyright 2010  IO Rodeo Inc. 
+Copyright 2010  IO Rodeo Inc.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 from base import SCAD_Prog
 from primitives import *
 from transforms import *
-from highlevel import *
- 
+try:
+    from highlevel import *
+except ImportError:
+    print("The highlevel module requires the numpy/scipy module, it has been disabled.")
 """
-Copyright 2010  IO Rodeo Inc. 
+Copyright 2010  IO Rodeo Inc.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 from utility import TAB_WIDTH
 
 class SCAD_Prog(object):
+    """Wrapper for Openscad program."""
 
-    def __init__(self,fn=None,fa=None,fs=None):
+    def __init__(self, fn=None, fa=None, fs=None):
         self.objlist = []
+        # Global facet settings
         self.fn = fn
         self.fa = fa
         self.fs = fs
 
-    def add(self,obj):
+    def add(self, obj):
         if type(obj) == list:
             self.objlist.extend(obj)
         else:
     def __str__(self):
         rtn_str = ''
         if not self.fn == None:
-            rtn_str = '%s$fn = %d;\n'%(rtn_str,self.fn)
+            rtn_str = '%s$fn = %d;\n'%(rtn_str, self.fn)
         if not self.fa == None:
-            rtn_str = '%s$fa = %d;\n'%(rtn_str,self.fa)
+            rtn_str = '%s$fa = %d;\n'%(rtn_str, self.fa)
         if not self.fs == None:
-            rtn_str = '%s$fs = %d;\n'%(rtn_str,self.fs)
+            rtn_str = '%s$fs = %d;\n'%(rtn_str, self.fs)
 
         for obj in self.objlist:
             rtn_str = '%s%s\n'%(rtn_str,obj)
 
         return rtn_str
 
-    def write(self,filename):
-        fid = open(filename,'w')
+    def write(self, filename):
+        fid = open(filename, 'w')
         fid.write(get_header_str(filename))
-        fid.write('%s'%(self,))
+        fid.write('{0}'.format(self))
         fid.close()
 
 class SCAD_Object(object):
+    """Scad object wrapper base class."""
 
     def __init__(self,center=True,mod=''):
-        self.type = None
-        self.center = center
-        self.cmp = False
-        self.mod = mod
+        self.type = None    # ?
+        self.center = center# Centered or positive quadrent
+        self.cmp = False    # Is compound
+        self.mod = mod      # Rendering modifier (*,%,#,!)
 
     def center_str(self):
         return str(self.center).lower()
         mod_str = self.mod
         return '%s%s%s'%(tab_str, mod_str, self.cmd_str(tab_level=tab_level))
 
-    def write(self,filename,fn=None):
-        fid = open(filename,'w')
-        if not fn == None:
-            fid.write('$fn=%d;\n'%(fn,))
-        fid.write('%s'%(self,))
-        fid.close()
+    def write(self, filename, fn=None):
+        outfile = open(filename,'w')
+        if fn:
+            outfile.write('$fn={0:0.5f};\n'.format(fn))
+        outfile.write('{0}'.format(self))
+        outfile.close()
 
 class SCAD_CMP_Object(SCAD_Object):
+    """Scad compound object wrapper base class."""
 
-    def __init__(self,obj,center=True,mod=''):
-        SCAD_Object.__init__(self,center=center,mod=mod)
-        self.cmp = True 
+    def __init__(self, obj, center=True, mod=''):
+        SCAD_Object.__init__(self, center=center, mod=mod)
+        self.cmp = True
         #self.obj = obj
         if type(obj) == list:
-            self.obj = obj 
+            self.obj = obj
         else:
             self.obj = [obj]
 
-    def cmd_str(self,tab_level=0):
+    def cmd_str(self, tab_level=0):
         return 'Empty SCAD_CMP_Object'
 
     def __str__(self, tab_level=0):
         return rtn_str
 
 def get_header_str(filename):
-    str0 = '//' + '='*70 + '\n'
-    str1 = '// %s\n'%(filename,)
-    str2 = """//
-// Autogenerated using py2scad. Hand editing this file is not advisable 
-// as all modifications will be lost when the program which generated 
-// this file is re-run. 
-// 
-"""
+    import textwrap
+    width = 70
+    str0 = '\n//' + '='*(width-2) + '//\n'
+    # see "http://docs.python.org/library/string.html#formatspec"
+    str1 = '//{0:=^{1}}//'.format(" " + filename + " ", width-2)
+    str1 += '\n//' + ' '*(width-2) + '//\n'
+    str2 = "Autogenerated using py2scad. Hand editing this file is not \
+advisable as all modifications will be lost when the program which generated \
+this file is re-run."
+    # str2 uses width-3 because of the extra space after the initial slashes
+    str2 = "\n".join("// {0:<{1}}//".format(l, width-3) for l in
+                     textwrap.wrap(str2, width=width-3))
     return str0 + str1 + str2 + str0 + '\n'
+
+if __name__ == "__main__":
+    print(get_header_str("filename"))

py2scad/highlevel.py

 """
-Copyright 2010  IO Rodeo Inc. 
+Copyright 2010  IO Rodeo Inc.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 See the License for the specific language governing permissions and
 limitations under the License.
 """
-import scipy
+try:
+    import scipy as numpy
+except ImportError:
+    import numpy
 from primitives import *
 from transforms import *
 from utility import DEG2RAD
 from utility import RAD2DEG
 
-def rounded_box(length,width,height,radius,round_x=True,round_y=True,round_z=True):
+def rounded_box(length, width, height, radius,
+                round_x=True, round_y=True, round_z=True):
     """
     Create a box with rounded corners
     """
 def plate_w_holes(length, width, height, holes=[], hole_mod='', radius=False):
     """
     Create a plate with holes in it.
-    
+
     Arguments:
       length = x dimension of plate
       width  = y dimension of plate
       height = z dimension of plate
-      holes  = list of tuples giving x position, y position and diameter of 
+      holes  = list of tuples giving x position, y position and diameter of
                holes
     """
     if radius == False:
     obj_list = [plate] + cylinders
     plate = Difference(obj_list)
     return plate
-    
+
 def disk_w_holes(height, d1, holes=[], hole_mod=''):
     """
     Create a disk with holes in it.
-    
+
     Arguments:
       d1 = diameter of the disk
       height = z dimension of disk
-      holes  = list of tuples giving x position, y position and diameter of 
+      holes  = list of tuples giving x position, y position and diameter of
                holes
     """
-    
+
     cyl = Cylinder(h=height,r1=d1*0.5,r2=d1*0.5)
     cylinders = []
     for x,y,r in holes:
 def grid_box(length, width, height, num_length, num_width,top_func=None,bot_func=None):
     """
     Create a box with given length, width, and height. The top and bottom surface of the
-    box will be triangulate bases on a grid with num_length and num_width points. 
+    box will be triangulate bases on a grid with num_length and num_width points.
     Optional functions top_func and bot_func can be given to distort the top or bottom
-    surfaces of the box. 
+    surfaces of the box.
     """
     nl = num_length + 1
     nw = num_width + 1
-    xpts = scipy.linspace(-0.5*length,0.5*length,nl)
-    ypts = scipy.linspace(-0.5*width,0.5*width,nw)
+    xpts = numpy.linspace(-0.5*length,0.5*length,nl)
+    ypts = numpy.linspace(-0.5*width,0.5*width,nw)
 
     points_top = []
     points_bot = []
         f = [2*numtop-nl+i,2*numtop-nl+i+1,numtop-nl+i]
         faces_back.append(f)
 
-
     faces_right = []
     faces_left = []
     for j in range(0,nw-1):
         faces_left.append(f)
 
     points = points_top + points_bot
-    faces = faces_top + faces_bot 
-    faces.extend(faces_front) 
+    faces = faces_top + faces_bot
+    faces.extend(faces_front)
     faces.extend(faces_back)
     faces.extend(faces_right)
     faces.extend(faces_left)
 def wedge_cut(obj,ang0,ang1,r,h,numpts=20,mod=''):
     """
     Cut out a wedge from obj from ang0 to ang1 with given radius r
-    and height h. 
+    and height h.
     """
     ang0rad = DEG2RAD*ang0
     ang1rad = DEG2RAD*ang1
-    angs = scipy.linspace(ang0rad,ang1rad,numpts)
-    points_arc = [[r*scipy.cos(a),r*scipy.sin(a)] for a in angs]
+    angs = numpy.linspace(ang0rad,ang1rad,numpts)
+    points_arc = [[r*numpy.cos(a),r*numpy.sin(a)] for a in angs]
     points = [[0,0]]
     points.extend(points_arc)
     paths = [range(0,len(points))]
     cut_ang0 = ang1
     cut_ang1 = ang0 + 360.0
     cyl = Cylinder(h=h,r1=r1,r2=r2)
-    cut_r = max([r1,r2]) + cut_extra 
-    cut_h = h + cut_extra 
+    cut_r = max([r1,r2]) + cut_extra
+    cut_h = h + cut_extra
     cut_cyl = wedge_cut(cyl,cut_ang0,cut_ang1,cut_r,cut_h,mod=mod)
     return cut_cyl
 
     c = Translate(c,v=[r-edge_len,0,0])
     torus = Rotate_Extrude(c)
     disk = Union([disk,torus])
-    return disk 
+    return disk
 
 def rounded_disk(h,r,edge_r):
     pass
     angle of the triangle is located at the origin.
     """
     rect_base = Cube(size=[x,y,z])
-    rect_diff = Cube(size=[2*scipy.sqrt(x**2+y**2),y,2*z])
+    rect_diff = Cube(size=[2*numpy.sqrt(x**2+y**2),y,2*z])
     rect_diff = Translate(rect_diff,v=[0,0.5*y,0])
-    theta = -scipy.arctan2(y,x)*RAD2DEG
+    theta = -numpy.arctan2(y,x)*RAD2DEG
     rect_diff = Rotate(rect_diff,a=theta,v=[0,0,1])
     triangle = Difference([rect_base,rect_diff])
     triangle = Translate(triangle,v=[0.5*x, 0.5*y, 0])
-    return triangle 
+    return triangle
 
 
 def right_triangle_w_tabs(x, y, z, num_x=1, num_y=1, tab_depth='z', tab_epsilon=0.0,
     Creates a polygonal object which is a right triangle in the x,y plane with
     hypotenuse sqrt(x**2 + y**2). The shape is rectangular in the x,z and y,z
     planes with the z dimension given by z. Tabs are placed along the x and y
-    edges of the part. 
-    
+    edges of the part.
+
     Arguments:
     x = x dimension of part
     y = y dimension of part
     Keyword Arguments:
     num_x         = number of tabs along the x dimension of the triangle (default=1)
     num_y         = number of tabs along the y dimension of the triangle (default=1)
-    tab_depth     = the length the tabs should stick out from the part. If set to 
-                    'z' this will be the z dimension or thickness of the part. 
+    tab_depth     = the length the tabs should stick out from the part. If set to
+                    'z' this will be the z dimension or thickness of the part.
                     Otherwise it should be a number. (default = 'z')
     tab_epsilon   = amount the tabs should be over/under sized. 2 times this value
-                    is added to the tabe width. 
-    solid         = specifies whether the part should be solid or not. 
+                    is added to the tabe width.
+    solid         = specifies whether the part should be solid or not.
     removal_frac  = specifies the fraction of the interior to be removed. Only used
                     when solid == False
-    
+
     """
     if tab_depth in ('z','Z'):
         # Sets the depth of the tabs to that of the part z dim (the thickness)
         tab_depth = z
-    
+
     triangle = right_triangle(x,y,z)
     tabs = []
     tabs = []
         # Make x-tabs
         tab_x_width = x/(2.0*num_x+1) + 2*tab_epsilon
         tab_x_base = Cube(size=[tab_x_width,2*tab_depth,z])
-        tab_x_pos = scipy.linspace(0,x,num_x+2)
+        tab_x_pos = numpy.linspace(0,x,num_x+2)
         tab_x_pos = tab_x_pos[1:-1]
         for x_pos in tab_x_pos:
             tabs.append(Translate(tab_x_base,v=[x_pos,0,0]))
         # Make y-tabe
         tab_y_width = y/(2.0*num_y+1) + 2*tab_epsilon
         tab_y_base = Cube(size=[2*tab_depth,tab_y_width,z])
-        tab_y_pos = scipy.linspace(0,y,num_y+2)
+        tab_y_pos = numpy.linspace(0,y,num_y+2)
         tab_y_pos = tab_y_pos[1:-1]
         for y_pos in tab_y_pos:
             tabs.append(Translate(tab_y_base,v=[0,y_pos,0]))
     if solid == False:
         xx,yy = removal_frac*x, removal_frac*y
         sub_triangle = right_triangle(xx,yy,2*z)
-        x_shift = (x - xx)/3.0 
+        x_shift = (x - xx)/3.0
         y_shift = (y - yy)/3.0
         sub_triangle = Translate(sub_triangle,v=[x_shift,y_shift,0])
         triangle = Difference([triangle,sub_triangle])
 
 def right_angle_bracket(length_base, length_face, width, thickness, num_x_tabs=2, num_y_tabs=2,bracket_frac=0.6):
     """
-    Creates a right angle bracket -- not finished yet. 
+    Creates a right angle bracket -- not finished yet.
     """
     length_face_adj = length_face - thickness
     base = Cube(size=[length_base, width, thickness])
     y_shift = 0.5*width-0.5*thickness
     bracket_pos = Translate(bracket,v=[0,y_shift,0])
     bracket_neg = Translate(bracket,v=[0,-y_shift,0])
-    
+
     base.mod = '%'
     face.mod = '%'
     return [base,face,bracket_pos,bracket_neg]

py2scad/primitives.py

 """
-Copyright 2010  IO Rodeo Inc. 
+Copyright 2010  IO Rodeo Inc.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
     def cmd_str(self,tab_level=0):
         size_str = utility.val_to_str(self.size)
         center_str = self.center_str()
-        return 'cube(size=%s,center=%s);'%(size_str,center_str) 
+        return 'cube(size=%s,center=%s);'%(size_str,center_str)
 
 class Sphere(base.SCAD_Object):
 
 
 class Cylinder(base.SCAD_Object):
 
-    def __init__(self, h=1.0, r1=1.0, r2=1.0, center=True,mod=''):
+    def __init__(self, h=1.0, r1=1.0, r2=None, center=True, mod=''):
         base.SCAD_Object.__init__(self,center=center,mod=mod)
         self.h = float(h)
         self.r1 = float(r1)
-        self.r2 = float(r2)
+        # r2 is optional
+        self.r2 = r2
+        if r2:
+            self.r2 = float(r2)
 
     def cmd_str(self,tab_level=0):
+        center_str = self.center_str()
         h_str = utility.val_to_str(self.h)
         r1_str = utility.val_to_str(self.r1)
-        r2_str = utility.val_to_str(self.r2)
-        center_str = self.center_str()
-        return 'cylinder(h=%s,r1=%s,r2=%s,center=%s);'%(h_str, r1_str, r2_str, center_str)
-        
+        if self.r2:
+            r2_str = utility.val_to_str(self.r2)
+            return 'cylinder(h=%s,r1=%s,r2=%s,center=%s);'%(h_str, r1_str, r2_str, center_str)
+        return 'cylinder(h=%s,r=%s,center=%s);'%(h_str, r1_str, center_str)
+
 class Polyhedron(base.SCAD_Object):
 
     def __init__(self, points, faces, center=True, mod=''):

py2scad/transforms.py

 """
-Copyright 2010  IO Rodeo Inc. 
+Copyright 2010  IO Rodeo Inc.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 # 3D transformations ---------------------------------------------------------
 
 class Scale(base.SCAD_CMP_Object):
-
+    """Scale contained object along local x,y,z."""
     def __init__(self,obj,v=[1.0,1.0,1.0], mod=''):
         base.SCAD_CMP_Object.__init__(self, obj, mod=mod)
         self.v = utility.float_list3(v)
         return 'scale(v=%s)'%(v_str)
 
 class Rotate(base.SCAD_CMP_Object):
+    """Rotate contained objects."""
 
-    def __init__(self,obj,a=0.0,v=[1.0,0.0,0.0],mod=''):
+    def __init__(self, obj, v=[1.0,0.0,0.0], a=None, mod=''):
         base.SCAD_CMP_Object.__init__(self,obj,mod=mod)
-        self.a = float(a)
-        self.v = utility.float_list3(v) 
+        self.v = utility.float_list3(v)
+        self.a = a
 
     def cmd_str(self,tab_level=0):
-        a_str = utility.val_to_str(self.a)
         v_str = utility.val_to_str(self.v)
-        return 'rotate(a=%s,v=%s)'%(a_str,v_str)
+        if self.a: # If there's an angle use axis/angle
+            a_str = utility.val_to_str(self.a)
+            return 'rotate(a=%s,v=%s)'%(a_str,v_str)
+        # If not a then interpret v as a vector of angles
+        return 'rotate(a=%s)'%(v_str)
+
 
 class AnimRotate(base.SCAD_CMP_Object):
 
 
     def cmd_str(self,tab_level=0):
         return 'translate(v=%s)'%(self.v,)
-       
+
 class Mirror(base.SCAD_CMP_Object):
 
     def __init__(self,obj,v=[1.0,0.0,0.0],mod=''):
 
     def cmd_str(self,tab_level=0):
         return 'intersection()'
-    
+
 # 2D to 3D Extrusion -----------------------------------------------------------
 
 class Linear_Extrude(base.SCAD_CMP_Object):

py2scad/utility.py

 """
-Copyright 2010  IO Rodeo Inc. 
+Copyright 2010  IO Rodeo Inc.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 import math
 
 TAB_WIDTH = 4
-DEG2RAD = math.pi/180.0
-RAD2DEG = 180.0/math.pi
+#DEG2RAD = math.pi/180.0
+#RAD2DEG = 180.0/math.pi
+DEG2RAD = math.degrees
+RAD2DEG = math.radians
 
 # Utility functions -----------------------------------------------------------
 
     return _v
 
 def val_to_str(x,tab_level=0):
-    tab_str = ' '*TAB_WIDTH*tab_level
+    tab_str = ''
+    if tab_level:
+        tab_str = ' '*TAB_WIDTH*tab_level
     if type(x) == float:
         x_str = '%s%f'%(tab_str,x,)
     else:
     for obj in obj_list:
         fid.write('%s\n'%(obj,))
     fid.close()
-
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.