summaryrefslogtreecommitdiff
path: root/trunk/users/vasile/brlcad
diff options
context:
space:
mode:
authorjvasile <jvasile@cb376a5e-1013-0410-a455-b6b1f9ac8223>2008-07-17 13:10:40 +0000
committerjvasile <jvasile@cb376a5e-1013-0410-a455-b6b1f9ac8223>2008-07-17 13:10:40 +0000
commit504ab493b75aead78f3877957cfc140ee5c2919d (patch)
tree53c36a5bc88319711ec5975d9043aa2146452776 /trunk/users/vasile/brlcad
parentdeaca87bb0108531fa9d255c7e0badf9ee48a881 (diff)
downloadreprap-backup-504ab493b75aead78f3877957cfc140ee5c2919d.tar.gz
reprap-backup-504ab493b75aead78f3877957cfc140ee5c2919d.zip
Big changes to the class stack. Breaks v0.1 compatibility, but that is ok
git-svn-id: https://reprap.svn.sourceforge.net/svnroot/reprap@1760 cb376a5e-1013-0410-a455-b6b1f9ac8223
Diffstat (limited to 'trunk/users/vasile/brlcad')
-rw-r--r--trunk/users/vasile/brlcad/brlcad.py358
-rw-r--r--trunk/users/vasile/brlcad/brlcad_mechanical.py29
2 files changed, 320 insertions, 67 deletions
diff --git a/trunk/users/vasile/brlcad/brlcad.py b/trunk/users/vasile/brlcad/brlcad.py
index 5a28f812..afa0ec2a 100644
--- a/trunk/users/vasile/brlcad/brlcad.py
+++ b/trunk/users/vasile/brlcad/brlcad.py
@@ -15,6 +15,8 @@ license = '''## This is a freed work; you can redistribute it and/or modify it
import sys, os
+VERSION = 0.2
+
class Vector:
def __init__(self,*args):
if len(args) == 1:
@@ -40,80 +42,279 @@ def unique_name(stub, suffix):
unique_names[full] += 1
return stub + '.' + str(unique_names[full]) + suffix
-def build_name(stub, suffix, **kwargs):
+def build_name(stub, ending, **kwargs):
+ '''There are a lot of kwargs options to control how objects are named.
+
+ If you specify a name with 'name', the object will bear that exact
+ name, with no suffix or unique number. You are responsible for
+ making sure the name is unique.
+
+ 'suffix' is added to names. It's usually a single letter
+ indicating s for shape or r for region.
+
+ 'basename' overrides the stub. To this, a unique number and the
+ suffix will be added.
+
+ 'unique_name' can be set to False, and that will turn off the numbering.'''
+
+ if 'name' in kwargs:
+ return kwargs['name']
+
if 'suffix' in kwargs:
suffix = kwargs['suffix']
+ else:
+ suffix = ending
if suffix: suffix = '.' + suffix
- if 'name' in kwargs:
+
+ if 'basename' in kwargs:
if 'unique_name' in kwargs and kwargs['unique_name']==False:
- return kwargs['name'] + suffix
+ return kwargs['basename'] + suffix
else:
- return unique_name(kwargs['name'], suffix)
+ return unique_name(kwargs['basename'], suffix)
else:
return unique_name(stub, suffix)
-class Statement:
+class Statement():
+ isstatement = True
+ name='' # statements don't have names, but this keeps group from complaining
def __init__(self, statement, args=[]):
- args = list(args)
- for i in range(len(args)):
- if type(args[i]) == tuple or type(args[i]) == list:
- args[i] = Vector(args[i])
- self.args = args
+
+ self.args=[]
+ if type(args) == str:
+ self.args.append(args)
+ else:
+ for i in range(len(args)):
+ if type(args[i]) == tuple or type(args[i]) == list:
+ self.args.append(Vector(args[i]))
+ else:
+ self.args.append(args[i])
+
self.statement = statement
+
def __str__(self):
- return '%s %s' % (self.statement, ' '.join([str(s) for s in self.args]))
+ return '%s %s\n' % (self.statement, ' '.join([str(s) for s in self.args]))
-class Script():
- '''A script is just a list of statements to send to mged.
- TODO: Maybe this class should derive from list?'''
- def __init__(self, *statements):
- self.statements = list(statements)
- self.index = len(statements)
+class Shape():
+ isshape = True
+ def __init__(self, args=[], **kwargs):
+ '''A Shape is any physical item we can depict with brl-cad, from a
+ primitive to a screw to a hole to an entire machine.
+
+ Each element in args is a Statement or a Shape that makes this
+ item.
+
+ kwargs['rotate'] = rotate vector or a tuple containing rotate
+ vector and rotate vertex.
+
+ kwargs['scale'] - not implemented
+ kwargs['translate'] - not implemented
+
+ Specify the Shape by instantiating it along with the
+ statements and shapes that comprise it. Typically, you'll use
+ rotate or translate after instantiating to move it into
+ position.
+
+ self.children stores a list of Shapes that comprise this one.
+
+ TODO: Every shape needs a default vertex for translation and
+ rotation purposes. '''
+
+ self.name = build_name('shape', 's', **kwargs)
+
+ if not hasattr(self, 'statements'):
+ self.statements = []
+
+ if not hasattr(self, 'children'):
+ self.children = [] # an array of Shapes
+
+ for a in args:
+ if hasattr(a, 'isstatement'):
+ self.statements.append(a)
+ elif hasattr(a, 'isshape'):
+ self.children.append(a)
+ elif type(a) == type('str'):
+ self.statements.append(Statement(a))
+ else:
+ print >>sys.stderr, self.name, 'contains ', type(a)
+ sys.exit(2)
+
+ Shape.guess_vertex(self)
+
+ if not hasattr(self, 'vertex'):
+ sys.stderr.write('Shape (%s) needs vertex\n' % (self.name))
+ sys.exit(2)
+
+ if 'group' in kwargs and kwargs['group']:
+ self.group()
+
+ if 'rotate' in kwargs:
+ if type(kwargs['rotate'] == tuple) or type(kwargs['rotate'] == list):
+ if len(kwargs['rotate']) == 3:
+ self.rotate(kwargs['rotate'])
+ elif len(kwargs['rotate']) == 2:
+ self.rotate(kwargs['rotate'][0],kwargs['rotate'][1])
+ else:
+ print >>sys.stderr, ('%s: rotate takes 1 vector or 2 vectors in a tuple.' %
+ (self.name))
+ sys.exit(2)
+ else:
+ print >>sys.stderr, '%s: rotate takes 1 or 2 tuples/lists.' % (self.name)
+ sys.exit(2)
+
def __str__(self):
- return ''.join(['%s\n' % (s) for s in self.statements])
+ '''Accessing an Object as a string will yield all the statements and
+ the children's statements.'''
- def __iter__(self):
- return self
- def next(self):
- if self.index == len(statements):
- raise StopIteration
- self.index = self.index + 1
- return self.statements[self.index]
+ return ''.join([str(c) for c in self.children]) + \
+ ''.join([str(s) for s in self.statements])
- def append(self, *statements):
- for i in statements:
- self.statements.append(i)
- return self
+ def combination(self, command):
+ '''Unimplemented and/or Untested: Add a statement to the stack making this
+ a combination. Populate self.name with the name of that
+ combination.'''
+
+ self.statements.append(Statement('c', (command,)))
+
+ def group(self):
+ '''Take all the Shapes that comprise this item, and make a group of
+ self.name. Append the group statement to self.
+
+ If kwargs['group']==True, this will be done as part of __init__'''
+
+ self.statements.append(Kill(self.name))
+
+ args = [self.name]
+ for c in self.children:
+ if hasattr(c, 'isshape'):
+ args.append(c.name)
+
+ if len(args) < 2:
+ print >>sys.stderr, self.name, 'needs more items to group'
+ sys.exit(2)
+
+ self.statements.append(Statement('g', args))
+ return self.name
-class Shape(Statement):
+ def guess_vertex(self):
+ '''If vertex doesn't exist, adopt vertex of first shape in children.
+
+ If this doesn't find the right vertex, you'll have to set it
+ manually *before* you call init. Otherwise, init will
+ complain about lack of a vertex and halt.'''
+
+ if not hasattr(self, 'vertex'):
+ for c in self.children:
+ if hasattr(c, 'vertex'):
+ self.vertex = c.vertex
+ return self.vertex
+
+ def rotate(self, rotation, vertex=None):
+ if vertex == None:
+ vertex = self.vertex
+
+ for c in self.children:
+ if hasattr(c, 'rotate'):
+ c.rotate(rotation, vertex)
+
+ def translate(self, translate, vertex=None):
+ '''translate is a tuple containing the amount to move along each axis.
+ vertex is the point from which we move. All other Shapes and
+ Shapes that make up this Shape are moved relative to the
+ vertex.'''
+
+ if vertex == None:
+ vertex = self.vertex
+
+ for c in self.children:
+ if hasattr(c, 'rotate'):
+ c.translate(translate, vertex)
+
+
+class Primitive(Shape):
+ "Primitive shapes executed in one or more statements."
+ isprimitive=True
def __init__(self, shape, args=[], **kwargs):
- "Primitive shapes"
self.name = build_name(shape, 's', **kwargs)
- Statement.__init__(self,'in %s %s' % (self.name, shape),args)
-
-class Region(Statement):
- def __init__(self, region_command, **kwargs):
- self.name = build_name('region', 'r', **kwargs)
- Statement.__init__(self,"r", (self.name, region_command))
-
-class Group(Statement):
- '''*shapes is a list of objects or object names to be added to the
- group. This class respects all the Statement keyword arguments,
- such as name, suffix and unique_name.'''
- def __init__(self, *shapes, **kwargs):
- shapes = list(shapes)
- self.name = build_name('group', 'g', **kwargs)
- for i in range(len(shapes)):
- if not isinstance(shapes[i], basestring):
- shapes[i] = shapes[i].name
- Statement.__init__(self, 'g', (self.name, ' '.join(shapes)))
-
-class Comment(Statement):
- def __init__(self, comment):
- Statement.__init__(self,"\n##", (comment,))
+ self.statements = []
+
+ self.guess_vertex(args)
+
+ Shape.__init__(self, ( Kill(self.name),
+ Statement('in %s %s' % (self.name, shape),args),),
+ name=self.name, **kwargs)
+
+ def guess_vertex(self, args):
+ ## Guess at the vertex. If this won't find the right vertex,
+ ## you'll have to set it manually.
+ i = 0
+ while not hasattr(self, 'vertex') and i < len(args):
+ if type(args[i]) == tuple and len(args[i]) == 3:
+ self.vertex = args[i]
+ i += 1
+
+ def rotate(self, rotation, vertex=None):
+ if vertex == None:
+ vertex = self.vertex
+
+ xrot, yrot, zrot = rotation
+ xvert, yvert, zvert = vertex
+
+ self.statements.append('sed %s\nkeypoint %f %f %f\nrot %f %f %f\naccept\n' % (
+ self.name, xvert, yvert, zvert, xrot, yrot, zrot))
+
+ def translate(self, xtra, ytra=None, ztra=None):
+ '''Translate shape to new coordinates.
+
+ Note that this is different from MGED's internal translate
+ statement. MGED moves the shape to the indicated coordinates.
+ This function moves the shape relative to the current
+ coordinates. translate(1, 2, -3) moves the shape 1 to the
+ right, 2 up and 3 back.'''
+
+ if type(xtra) == tuple:
+ xtra, ytra, ztra = xtra
+
+ self.statements.append('sed %s\ntra %f %f %f\naccept' % (
+ self.name, xtra, ytra, ztra))
+
+class Cone(Primitive):
+ def __init__(self, vertex, height_vector, base_radius, top_radius, **kwargs):
+ Primitive.__init__(self, "trc", (vertex, height_vector, base_radius, top_radius), **kwargs)
+
+class Cylinder(Primitive):
+ def __init__(self, vertex, height_vector, radius, **kwargs):
+ Primitive.__init__(self, "rcc", (vertex, height_vector, radius), **kwargs)
+
+class Box(Primitive):
+ def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax, **kwargs):
+ self.vertex = (xmin, ymin, zmin)
+ if not 'basename' in kwargs:
+ kwargs['basename'] = 'box'
+ Primitive.__init__(self, "rpp", (xmin, xmax, ymin, ymax, zmin, zmax), **kwargs)
+
+class Arb8(Primitive):
+ def __init__(self, v1, v2, v3, v4, v5, v6, v7, v8, **kwargs):
+ Primitive.__init__(self, "arb8", (v1, v2, v3, v4, v5, v6, v7, v8), **kwargs)
+
+
+## Implement some simplistic commands
+from string import Template
+commands = {
+'Comment':"##",
+'Exit':'exit',
+'Kill':'kill',
+'Killall':'killall',
+'Killtree': 'killtree',
+'Quit':'quit',
+'Source':'source',
+}
+for c in commands:
+ exec Template('''class $command(Statement):
+ def __init__(self, arg=''):
+ Statement.__init__(self, '$brl', arg)''').substitute(command = c, brl = commands[c])
class Sed(Statement):
## Enter editing mode
@@ -122,7 +323,7 @@ class Sed(Statement):
class Title(Statement):
## TODO: escape quotes
def __init__(self, title, args=[]):
- Statement.__init__(self,"title", (title,))
+ Statement.__init__(self,"title", title)
class Units(Statement):
def __init__(self, units):
@@ -134,19 +335,44 @@ class Units(Statement):
if not units in good_units:
sys.stdout.write('Unknown units! Ignoring units statement. Defaulting to mm.\n')
units = 'mm'
- Statement.__init__(self,"units", (units,))
+ Statement.__init__(self,"units", units)
-class Cone(Shape):
- def __init__(self, vertex, height_vector, base_radius, top_radius, **kwargs):
- Shape.__init__(self, "trc", (vertex, height_vector, base_radius, top_radius), **kwargs)
+class Script():
+ '''A script is just a list of statements to send to mged.
+ TODO: Maybe this class should derive from list?'''
-class Cylinder(Shape):
- def __init__(self, vertex, height_vector, radius, **kwargs):
- Shape.__init__(self, "rcc", (vertex, height_vector, radius), **kwargs)
+ def __init__(self, *statements):
+ self.statements = list(statements)
+ def __str__(self):
+ return ''.join(['%s' % (s) for s in self.statements])
-class Box(Shape):
- def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax, **kwargs):
- Shape.__init__(self, "rpp", (xmin, xmax, ymin, ymax, zmin, zmax), **kwargs)
+ def append(self, *statements):
+ for i in statements:
+ self.statements.append(i)
+ return self
+
+
+class Box_rounded_edge_corners(Shape):
+ def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax, radius, **kwargs):
+ if xmin > xmax:
+ xmin, xmax = xmax, xmin
+ if ymin > ymax:
+ ymin, ymax = ymax, ymin
+ if zmin > zmax:
+ zmin, zmax = zmax, zmin
+
+ if radius > (xmax-xmin) / 2 or radius > (zmax-zmin)/2:
+ sys.stdout.write('Radius %f too large!\n' % (float(radius)))
+ sys.exit(2)
+
+ step = radius
+
+ Shape.__init__(self, [
+ Box(xmin+step, xmax-step, ymin, ymax, zmin, zmax),
+ Box(xmin, xmax, ymin, ymax, zmin+step, zmax-step),
+ Cylinder((xmin+step, ymin, zmin+step), (0, ymax-ymin, 0), radius),
+ Cylinder((xmin+step, ymin, zmax-step), (0, ymax-ymin, 0), radius),
+ Cylinder((xmax-step, ymin, zmin+step), (0, ymax-ymin, 0), radius),
+ Cylinder((xmax-step, ymin, zmax-step), (0, ymax-ymin, 0), radius)
+ ], group=True, basename='brec', suffix='t')
-#class Box_rounded_edge_corners(Script):
-# def __init__(self, vertex, height
diff --git a/trunk/users/vasile/brlcad/brlcad_mechanical.py b/trunk/users/vasile/brlcad/brlcad_mechanical.py
index a5e80caa..482b4923 100644
--- a/trunk/users/vasile/brlcad/brlcad_mechanical.py
+++ b/trunk/users/vasile/brlcad/brlcad_mechanical.py
@@ -13,7 +13,34 @@
## to the Free Software Foundation, Inc., 51 Franklin Street, 5th
## Floor, Boston, MA 02110-1301 USA
-import brlcad
+from brlcad import *
+
+class stepper_motor(Shape):
+ '''Vertex is center point box, along the center of the cylinder.
+
+ TODO: implement mounting holes'''
+
+ def __init__(self, vertex, base_height, base_width,
+ mount_hole_rad,
+ motor_height, motor_rad,
+ spindle_height, spindle_rad, **kwargs):
+
+ x, y, z = vertex
+ by = base_height
+ my = motor_height
+
+ bw = float(base_width) / 2
+
+ self.vertex = vertex
+
+ Shape.__init__(self, [
+ Comment('Stepper Motor'),
+
+ Cylinder((x, y+by, z), (0,motor_height,0), motor_rad),
+ Cylinder((x, y+by+my, z), (0,spindle_height,0), spindle_rad),
+ Box_rounded_edge_corners(x-bw,x+bw, y,y+by, z-bw,z+bw, bw/10),
+ ], basename='stepper', suffix='', group=True, **kwargs)
+
class Threaded_rod():
'''Threaded rod. Horrible detail right now'''