""" This is the python version of wdb_example.c using the python-brlcad module. usage: python wdb_example.py output.g # want to render to file? rtedge -s 1024 -F output.pix output.g box_n_ball.r pix-png -s 1024 < output.pix > output.png wdb_example.c header text: Create a BRL-CAD geometry database from C code. Note that this is for writing (creating/appending) a database. Note that since the values in the database are stored in millimeters, the arguments to the mk_* routines are constrained to also be in millimeters. python attribution: :author: Bryan Bishop :date: 2013-09-09 :license: BSD """ # sys has argv import sys import random from brlcad.primitives import union, subtract import brlcad.wdb as wdb class brlcad_name_generator(object): def __init__(self): self.num_parts_in_use_by_part_name = {} def get_next_name(self, part_name): try: self.num_parts_in_use_by_part_name[part_name]+=1 except KeyError: self.num_parts_in_use_by_part_name[part_name]=1 name_split = part_name.split('.') name_prefix = '.'.join(name_split[:-1]) name_suffix = '.'+name_split[-1] if len(name_split)>1 else '' return '{}{}{}'.format(name_prefix, self.num_parts_in_use_by_part_name[part_name], name_suffix) class _28BYJ_48(object): def __init__(self, brl_db, get_next_name_func): self.brl_db = brl_db self.get_next_name_func = get_next_name_func self.final_name = None # part properties self.diameter=28 self.depth=19 # mounting wings self.wing_thickness = 1 self.screw_hole_diameter = 4.2 self.wing_width = 7 self.wing_hole_center_to_center = 35 # shaft self.body_to_shaft_base = 1.5 self.shaft_tip_to_body = 10 self.shaft_tip_to_keyway_base = 6 self.shaft_keyway_base_to_shaft_base = self.shaft_tip_to_body - self.body_to_shaft_base - self.shaft_tip_to_keyway_base # create the part sections body = self.body() print 'Body DONE: {}'.format(body) mounting = self.mounting_wings() print 'Mounting wings DONE: {}'.format(mounting) self.shaft() self.final_name = self.get_next_name("COMPLETE.g") print 'final motor name: {}'.format(self.final_name) brl_db.combination(self.final_name, tree=union(body, mounting), ) print 'final motor DONE: {}'.format(self.final_name) def get_next_name(self, sub_component_part_name): return self.get_next_name_func('_28BYJ_48' + '__' + sub_component_part_name) def body(self): main_body = self.get_next_name('main_body.s') # create the motor body centered at x0,y0,z0 self.brl_db.rcc(main_body, base=(0, 0, 0), height=(0, 0, self.depth), radius=self.diameter/2.0) return main_body def mounting_wings(self): # Make an rpp under the sphere (partly overlapping). Note that this really # makes an arb8, but gives us a shortcut for specifying the parameters. wing_block_name = self.get_next_name("mounting_wings_rect.s") self.brl_db.rpp(wing_block_name, pmin=(self.wing_hole_center_to_center/-2.0, # x self.wing_width/-2.0, # y self.depth - self.wing_thickness), # z pmax=(self.wing_hole_center_to_center/2.0, # x self.wing_width/2.0, # y self.depth) # z ) #start the screw holes at z= (depth - thickness), with height thickness right_hole_x = self.wing_hole_center_to_center/2.0 left_hole_x = right_hole_x * -1 curves_and_holes = {'left_wing_curve.s':{'brldb_name':None, 'x':left_hole_x, 'r':self.wing_width/2.0}, 'left_wing_hole.s':{'brldb_name':None, 'x':left_hole_x, 'r':self.screw_hole_diameter/2.0}, 'right_wing_curve.s':{'brldb_name':None, 'x':right_hole_x, 'r':self.wing_width/2.0}, 'right_wing_hole.s':{'brldb_name':None, 'x':right_hole_x, 'r':self.screw_hole_diameter/2.0}} for item_name, item in curves_and_holes.iteritems(): item['brldb_name'] = self.get_next_name(item_name) self.brl_db.rcc(item['brldb_name'], base=(item['x'], 0, self.depth - self.wing_thickness), height=(0, 0, self.wing_thickness), radius=item['r']) print 1 # Make a region that is the union of these two objects. To accomplish # this, we don't need anymore to create any linked list of the items ;-). wings_block_chamfered = self.get_next_name("wings_chamfered.r") self.brl_db.combination(wings_block_chamfered, tree=union(curves_and_holes['left_wing_curve.s']['brldb_name'], curves_and_holes['right_wing_curve.s']['brldb_name'], wing_block_name) ) print '2 name: {}'.format(wings_block_chamfered) # now subtract the holes away wings_block_left_hole_subtracted = self.get_next_name("wings_left_subtracted.r") self.brl_db.combination(wings_block_left_hole_subtracted, tree=subtract(wings_block_chamfered, curves_and_holes['left_wing_hole.s']['brldb_name']) ) print '3 name: {}'.format(wings_block_left_hole_subtracted) wings_block = self.get_next_name("wings_block.r") self.brl_db.combination(wings_block, tree=subtract(wings_block_left_hole_subtracted, curves_and_holes['right_wing_hole.s']['brldb_name']) ) print '4 name: {}'.format(wings_block) return wings_block # Makes the two screw holes # Note that you can provide a single combination name or a list in the # obj_list parameter, it will be handled correctly, all the tedious list # building is done under the hood: """ brl_db.hole( hole_start=(0, 0, 0), hole_depth=(2, 4, 2.5), hole_radius=0.75, obj_list="mounting_wings.r" ) """ def shaft(self): pass def wires(self): pass class aerosol_can_snap_cap(object): def __init__(self): #cap_height = 40 self.rim_inner_diamater = 61.1 # may need to change to 61.0mm self.rim_lip_height = 3 self.rim_trough_height = 2 self.rim_outer_diameter = 63.1 self.rim_outer_top__to_sprayer_bottom = 24.5 self.sprayer_height = 12 self.sprayer_diameter = 10.5 def main(argv): with wdb.WDB(argv[1], "My Database") as brl_db: name_tracker = brlcad_name_generator() motor = _28BYJ_48(brl_db, name_tracker.get_next_name) # All units in the database file are stored in millimeters. This constrains # the arguments to the mk_* routines to also be in millimeters. if __name__ == "__main__": main(sys.argv)