def brick(xsize, ysize, fillet=True): unit = 5.0 height = 10.0 draft = 1.0 # degrees of draft on faces for plastic ejection knob_rad = 1.8 # radius of the brick knob for mating with other bricks knob_height = 2.0 knob_draft = 5.0 # degrees of draft for the knob wall_thickness = 1.0 # plastic wall thickness fillet_rad = 0.4 # the default radius to use for rounded edges outerbrick = solidbrick(xsize, ysize, 0.0, unit, height, draft, knob_rad, knob_height, knob_draft) if fillet: to_fillet = [] for count, edge_center in enumerate(outerbrick.subcenters('edge')): if (abs(edge_center[2]) < 0.1 or (abs(edge_center[2] - height) < 0.1 and abs(edge_center[0] - (0.5 * unit)) % unit < 0.1 and abs(edge_center[1] - (0.5 * unit)) % unit < 0.1)): pass else: to_fillet.append(count) outerbrick.fillet(fillet_rad, to_fillet) innerbrick = solidbrick(xsize, ysize, wall_thickness, unit, height - wall_thickness, draft, knob_rad - wall_thickness, knob_height, knob_draft) base = cm.box(2 * unit * xsize, 2 * unit * ysize, 1.0) base.translate((-0.5 * unit * xsize, -0.5 * unit * ysize, -1.0)) innerbrick = innerbrick + base if fillet: to_fillet = [] for count, edge_center in enumerate(innerbrick.subcenters('edge')): if (abs(edge_center[2]) < 0.1 or (abs(edge_center[2] - (height - wall_thickness)) < 0.1 and abs(edge_center[0] - (0.5 * unit)) % unit < 0.1 and abs(edge_center[1] - (0.5 * unit)) % unit < 0.1)): to_fillet.append(count) innerbrick.fillet(fillet_rad, to_fillet) brick = outerbrick - innerbrick post_rad = ((math.sqrt(2.0) * unit) - (2 * knob_rad)) / 2.0 drad = (height - (0.5 * wall_thickness)) * math.tan(math.radians(draft)) post_base_rad = post_rad + drad post = cm.cone(post_rad, post_base_rad, height - (0.5 * wall_thickness)) if fillet: post.fillet(fillet_rad, [(0.0, 0.0, 0.0)]) post.translate((unit, unit, 0.0)) for x in range(xsize - 1): for y in range(ysize - 1): brick = brick + cm.translated(post, (x * unit, y * unit, 0.0)) return brick
def trms_translate(): s1 = cm.box(1.0, 2.0, 3.0) s2 = cm.translated(s1, (2.0, -6.0, 4.0)) v.viewstandard(viewtype='iso') v.display(s1, (1.0, 0.0, 0.0)) v.display(s2, (0.0, 0.0, 1.0)) v.fit() v.save('trms_translate.png') v.clear()
def translated(self, pdir): """ translation along pdir Parameter --------- pdir : (x,y,z) """ new = copy.deepcopy(self) new.shell = cm.translated(self.shell, pdir) new.lfaces = new.shell.subshapes('Face') for k, f in enumerate(new.lfaces): new.pos[k] = f.center()[0:2] return new
def solidbrick(xsize, ysize, wall_offset, unit, height, draft, knob_rad, knob_height, knob_draft, save_images=0): dx = height * math.tan(math.radians(draft)) wbottom = cm.rectangle(unit * xsize - 2 * wall_offset, unit * ysize - 2 * wall_offset) wtop = cm.rectangle(unit * xsize - 2 * dx - 2 * wall_offset, unit * ysize - 2 * dx - 2 * wall_offset) wtop.translate((dx, dx, height)) brick = cm.loft([wbottom, wtop], True) brick.translate((wall_offset, wall_offset, 0.0)) if save_images: v.display(brick) v.fit() v.save('example1_box.png') drad = knob_height * math.tan(math.radians(knob_draft)) knob_top_rad = knob_rad - drad knob_base_rad = knob_rad + drad knob = cm.cone(knob_base_rad, knob_top_rad, 2 * knob_height) knob.translate((0.5 * unit, 0.5 * unit, height - knob_height)) if save_images: v.display(knob, color=(1.0, 0.0, 0.0)) v.fit() v.save('example1_boxwknob.png') for x in range(xsize): for y in range(ysize): brick = brick + cm.translated(knob, (x * unit, y * unit, 0.0)) if save_images: v.clear() v.display(brick) v.save('example1_boxwknobs.png') return brick
def solidbrick(xsize, ysize, wall_offset, unit, height, draft, knob_rad, knob_height, knob_draft): dx = height * math.tan(math.radians(draft)) wbottom = cm.rectangle(unit * xsize - 2 * wall_offset, unit * ysize - 2 * wall_offset) wtop = cm.rectangle(unit * xsize - 2 * dx - 2 * wall_offset, unit * ysize - 2 * dx - 2 * wall_offset) wtop.translate((dx, dx, height)) brick = cm.loft([wbottom, wtop], True) brick.translate((wall_offset, wall_offset, 0.0)) drad = knob_height * math.tan(math.radians(knob_draft)) knob_top_rad = knob_rad - drad knob_base_rad = knob_rad + drad knob = cm.cone(knob_base_rad, knob_top_rad, 2 * knob_height) knob.translate((0.5 * unit, 0.5 * unit, height - knob_height)) for x in range(xsize): for y in range(ysize): brick = brick + cm.translated(knob, (x * unit, y * unit, 0.0)) return brick
head_diameter = 8.5 head_height = 5.0 key_size = 4.0 socket_depth = 2.5 if length - threaded_length > 0.: body = cm.cylinder(threaded_diameter / 2, length) + \ cm.cylinder(unthreaded_diameter / 2, length - threaded_length) else: body = cm.cylinder(threaded_diameter / 2, length) socket = cm.translated( cm.prism( cm.filling # ngon is written in a circle of a given radius, # the socket definition is the diameter of the # circle written in the hexagon # -> multiply by 2 / sqrt(3) (cm.ngon(2 / 3**.5 * key_size / 2., 6)), (0, 0, socket_depth)), (0, 0, -head_height)) head = cm.translated(cm.cylinder(head_diameter / 2., head_height), (0, 0, -head_height)) - socket part = head + body if __name__ == "__main__": import ccad.display as cd v = cd.view() v.display(part) cd.start()
def example1(): import numpy as np unit = 5.0 height = 10.0 draft = 1.0 # degrees of draft on faces for plastic ejection knob_rad = 1.8 # radius of the brick knob for mating with other bricks knob_height = 2.0 knob_draft = 5.0 # degrees of draft for the knob wall_thickness = 1.0 # plastic wall thickness fillet_rad = 0.4 # the default radius to use for rounded edges xsize = 4 ysize = 2 outerbrick = solidbrick(xsize, ysize, 0.0, unit, height, draft, knob_rad, knob_height, knob_draft, save_images=1) to_fillet = [] for count, edge_center in enumerate(outerbrick.subcenters('edge')): if (abs(edge_center[2]) < 0.1 or (abs(edge_center[2] - height) < 0.1 and abs(edge_center[0] - (0.5 * unit)) % unit < 0.1 and abs(edge_center[1] - (0.5 * unit)) % unit < 0.1)): pass else: to_fillet.append(count) outerbrick.fillet(fillet_rad, to_fillet) v.clear() v.display(outerbrick) v.fit() v.save('example1_outerbrick.png') innerbrick = solidbrick(xsize, ysize, wall_thickness, unit, height - wall_thickness, draft, knob_rad - wall_thickness, knob_height, knob_draft) base = cm.box(2 * unit * xsize, 2 * unit * ysize, 1.0) base.translate((-0.5 * unit * xsize, -0.5 * unit * ysize, -1.0)) innerbrick = innerbrick + base v.clear() v.display(innerbrick) v.fit() v.save('example1_innerbrick.png') to_fillet = [] for count, edge_center in enumerate(innerbrick.subcenters('edge')): if (abs(edge_center[2]) < 0.1 or (abs(edge_center[2] - (height - wall_thickness)) < 0.1 and abs(edge_center[0] - (0.5 * unit)) % unit < 0.1 and abs(edge_center[1] - (0.5 * unit)) % unit < 0.1)): to_fillet.append(count) innerbrick.fillet(fillet_rad, to_fillet) v.clear() v.display(innerbrick) v.fit() v.save('example1_innerbrickfillet.png') brick = outerbrick - innerbrick v.clear() v.display(brick) v.set_projection((0.0, 0.0, 0.0), (math.sqrt(0.45), -math.sqrt(0.1), -math.sqrt(0.45)), (0.0, -1.0, 0.0)) v.fit() v.save('example1_brick.png') post_rad = (math.sqrt(2.0) * unit - 2 * knob_rad) / 2.0 drad = (height - 0.5 * wall_thickness) * math.tan(math.radians(draft)) post_base_rad = post_rad + drad post = cm.cone(post_rad, post_base_rad, height - 0.5 * wall_thickness) post.fillet(fillet_rad, [(0.0, 0.0, 0.0)]) v.clear() v.display(post) v.viewstandard(viewtype='iso') v.fit() v.save('example1_post.png') post.translate((unit, unit, 0.0)) for x in range(xsize - 1): for y in range(ysize - 1): brick = brick + cm.translated(post, (x * unit, y * unit, 0.0)) v.clear() v.display(brick) v.viewstandard(viewtype='bottom') v.fit() v.save('example1_brickpost.png') brick_images.generate_images(4, 2)
#!/usr/bin/env python # coding: utf-8 r"""Generation script for ISO 4014 screw""" from ccad.model import prism, filling, ngon, cylinder, translated k_max = 1.225 s_max = 3.2 l_g_max = 3.0 d_s_max = 1.6 d_s_min = 1.46 l_max = 12.35 head = translated( prism(filling(ngon(2 / 3**.5 * s_max / 2., 6)), (0, 0, k_max)), (0., 0., -k_max)) threaded = cylinder(d_s_min / 2., l_max) unthreaded = cylinder(d_s_max / 2., l_g_max) __shape__ = (head + threaded + unthreaded).shape __anchors__ = { "head_bottom": { "p": (0., 0., 0.), "u": (0., 0., -1.), "v": (1., 0., 0.), "dimension": d_s_max, "description": "screw head on plane" } }
def test_translated(self): delta = (0.1, 0.2, 0.3) s1 = cm.sphere(1.0) s2 = cm.translated(s1, delta) self.assert_(close(s2.center(), delta))
# e = 15 # l = 20 # w = 30 input = {"e": 5, "l": 20, "w": 30} e = input["e"] l = input["l"] w = input["w"] hole_d = 2 hole_positions = ((l / 4, -w / 4), (l / 4, w / 4), (-l / 4, -w / 4), (-l / 4, w / 4)) plate = translated(box(l, w, e), (-l / 2, -w / 2, 0)) cylinders = list() for (x, y) in hole_positions: cylinders.append(translated(cylinder(hole_d / 2., e), (x, y, 0))) for c in cylinders: plate -= c __shape__ = plate.shape __anchors__ = dict() for i, (x, y) in enumerate(hole_positions, 1): __anchors__[str(i)] = { "p": (x, y, e),
def transform(self, shape): return cm.translated( cm.rotatedx(cm.rotatedy(cm.rotatedz(shape, self.rz), self.ry), self.rx), (self.tx, self.ty, self.tz))
def write_components(self): r""" Write individual components of the assembly Notes ----- Write unique components to their own step files in a subdirectory of the folder containing the original file """ if os.path.isfile(self.origin): # directory = os.path.dirname(self.origin) # basename = os.path.basename(self.origin) # subdirectory = os.path.join(directory, # os.path.splitext(basename)[0]) subdirectory = self.get_dirname() if not os.path.isdir(subdirectory): os.mkdir(subdirectory) else: msg = "The components of the assembly should already exist" raise ValueError(msg) # get the list of step files or json files in subdirectory filelist = [ f for f in os.listdir(subdirectory) if (f.endswith(".stp") or f.endswith(".json")) ] for f in filelist: os.remove(os.path.join(subdirectory, f)) # creates dataframe self.df_nodes = pd.DataFrame(columns=('name', 'count', 'nodes', 'volume', 'assembly')) self.dnodes = {} for k in self.node: # calculate point cloud signature # pcloudk = self.node[k]['pcloud'] # # solidk : uncentered solid # solidk_centered : centered solid # solidk = self.node[k]['shape'] ptc = np.array(solidk.center()) # warning : center of gravity is obtained # from solid not from pointcloud solidk_centered = cm.translated(solidk, -ptc) pcloudk = pc.PointCloud() pcloudk = pcloudk.from_solid(solidk_centered) Npoints = pcloudk.p.shape[0] pcloudk.sorting() pcloudk.ordering() pcloudk.signature() V = pcloudk.V Npoints = pcloudk.Npoints self.node[k]['pc'] = ptc self.node[k]['flip'] = False self.node[k]['Npoints'] = Npoints if np.linalg.det(V) > 0: self.node[k]['V'] = V else: V[:, 2] = -V[:, 2] self.node[k]['V'] = V self.node[k]['flip'] = True # V is a assert as a rotation if np.linalg.det(V) <= 0: raise AssertionError("") assembly = self.node[k]['assembly'] # # Transfer solidk to the origin # # The order of the geometrical operations is important # solidk.translate(-ptc) if self.node[k]['flip']: solidk.mirrorz() solidk.unitary(V.T) # assert(np.allclose(solidk.center(),0)) # # Point cloud of the solid centered and transformed # pcloudk_transformed = pc.PointCloud() pcloudk_transformed = pcloudk_transformed.from_solid(solidk) pcloudk_transformed.sorting() pcloudk_transformed.ordering() pcloudk_transformed.signature() self.node[k]['sig'] = pcloudk_transformed.sig name = pcloudk_transformed.name self.node[k]['name'] = name self.node[k]['pcloud'] = pcloudk_transformed filename = pcloudk_transformed.name + ".stp" filename = os.path.join(subdirectory, filename) lnames = self.df_nodes['name'].values # if not os.path.isfile(filename): if not (name in lnames): # save translated transformed unique shape to filename solidk.to_step(filename) index = len(self.df_nodes) self.df_nodes = self.df_nodes.set_value(index, 'name', name) self.df_nodes = self.df_nodes.set_value( index, 'volume', solidk.volume()) self.df_nodes = self.df_nodes.set_value(index, 'count', 1) self.df_nodes = self.df_nodes.set_value(index, 'nodes', [k]) self.df_nodes = self.df_nodes.set_value( index, 'assembly', assembly) else: # get solid from origin file # solid_orig = cm.from_step(filename) # TODO : why not used? _ = cm.from_step(filename) # transform it around origin # node_solid = self.df_nodes[self.df_nodes['name']==name]['nodes'].values[0][0] # print("Node_solid",k,node_solid) # solid.unitary(V_orig) # pcloud_orig = pc.PointCloud() # pcloud_orig = pcloud_orig.from_solid(solid_orig) # pcloud_orig.sorting() # pcloud_orig.ordering() # d0,d1 = pcloud_orig.distance(pcloudk_transformed) # S = np.dot(V.T,V_orig) # T1 = np.dot(pcloud_orig.p.T,pcloudk_transformed.p) # T2 = np.dot(pcloudk_transformed.p.T,pcloud_orig.p) # print(k, d0, d1) # SI = np.diag(1./Sk) # U3 = Uk[:,:3] # H1 = np.dot(pcloud_orig.p.T,U3) # H2 = np.dot(H1,SI) # T3 = np.dot(H2,Vk) # if k==7: # pdb.set_trace() # self.node[k]['V'] = V_orig # print(d0,d1) # if pcloudk != pcloud_orig: # V1 = pcloud_orig.get_transform(pcloudk) # V2 = pcloudk.get_transform(pcloud_orig) # fig,ax = pcloudk.show(c = 'r') # fig,ax = pcloud_orig.show(fig=fig, ax=ax, c='b') # plt.show() # pdb.set_trace() dfname = self.df_nodes[self.df_nodes['name'] == name] dfname['count'] += 1 dfname.iloc[0]['nodes'].append(k) self.df_nodes[self.df_nodes['name'] == name] = dfname self.dnodes[k] = index