def __init__(self, w, t, noflap=False): ## What is w, t and noflap? ## if (noflap or eval_equation(t) > eval_equation(w) / 2): ## eval_equation() just a equation to return a value Face.__init__(self, ((w, 0), (w, t), (0, t))) else: Face.__init__(self, ((w, 0), (w + t, 0), (w, t), (0, t), (-t, 0))) self.edges['f0'] = DrawingEdge("f0", (0, 0), (0, t), Flex()) self.edges['f1'] = DrawingEdge("f1", (w, 0), (w, t), Flex()) self.edges.pop('e0') self.transform(origin=(-w / 2.0, -t / 2.))
def BeamTabSlotHelper(face, faceEdge, thick, widget, **kwargs): '''widget is representing TabDrawing or SlotDrawing, means it is a face''' coords = face.edge_coords(face.edge_index(faceEdge)) globalOrigin = coords[0] theta = arctan2(coords[1][1] - coords[0][1], coords[1][0] - coords[0][0]) length = norm((coords[1][1] - coords[0][1], coords[1][0] - coords[0][0])) try: frac = kwargs['frac'] except: frac = 0.5 try: noflap = kwargs['noflap'] except: noflap = False try: component = kwargs['component'] length = float(eval_equation(length)) except: #not sympy pass n = 0 ## the number of tabs we need. ## tw = thick * 3 ## what is tw? ## while (eval_equation(tw) > eval_equation(thick) * 2): n += 1 d = length * 1.0 / (n * 5 + 1) tw = 2 * d t = widget(w=tw, t=thick * frac, noflap=noflap) t.transform(angle=pi, origin=(-2 * d, thick / 2.)) try: if kwargs["mirror"]: t.mirrorY() t.transform(origin=(0, thick)) except: pass for i in range(n): t.transform(origin=(d * 5, 0)) for (name, edge) in t.edges.iteritems(): e = edge.copy() e.transform(angle=theta, origin=globalOrigin) face.add_decoration( (((e.x1, e.y1), (e.x2, e.y2)), e.edge_type.edge_type)) try: if kwargs["alternating"]: t.mirrorY() t.transform(origin=(0, thick)) except: pass
def __init__(self, length, male=True, **kwargs): coords = CoorForFingerjoint(eval_equation(length), male) edge_names = ["e%d" % i for i in range(len(coords))] edge_names[2] = "attachedge" Face.__init__(self, 'finger_joint', coords, [NON_PARAM_LEN for x in coords], edge_names=edge_names)
def __init__(self, length, width, male=False, **kwargs): coordsOfFinger = maleFemaleFingerJointDrawing(eval_equation(length), width, male) edge_names = ["e%d" % i for i in range(len(coordsOfFinger))] edge_names[2] = "slotedge" Face.__init__(self, 'ffinger_joint', coordsOfFinger, [NON_PARAM_LEN for x in coordsOfFinger], edge_names=edge_names)
def eval_hierarchical_constraints(self): """Evaluates all the constraints imposed on subcomponents Args: None """ for (var, val) in self.hierarchical_constraints.iteritems(): var.set_solved(eval_equation(val))
def to_stl(self, filename): """ Converts the graph to STL Args: filename (str): name of file to write STL data to """ self.place() stlFaces = [] for face in self.faces: if eval_equation(face.area) > 0: tdict = copy.deepcopy(face.get_triangle_dict()) newverts = [] for vert in tdict["vertices"]: newverts.append(tuple(eval_equation(i) for i in vert)) tdict["vertices"] = newverts stlFaces.append( [eval_equation(face.transform_3D), tdict, face.name]) ''' else: print "skipping face:", face.name ''' stl_write(stlFaces, filename)
def maleFemaleFingerJointDecoration(face, faceEdge, thick, widget, male=True, **kwargs): """ help to find how many fingers we need for different subcomponent.And add these fingers into the face. :param face: The face we add decoration; :param faceEdge: the edge we refer to; :param thick: the width of finger, it usually is 3.0mm. :param male: the type of decoration; :param widget: a face object to represent the finger; :param kwargs: kwargs; :return: None. the decoration will be added into selected face after operation """ coords = face.edge_coords(face.edge_index(faceEdge)) globalOrigin = coords[0] theta = arctan2(coords[1][1] - coords[0][1], coords[1][0] - coords[0][0]) length = norm((coords[1][1] - coords[0][1], coords[1][0] - coords[0][0])) length = eval_equation(length) try: component = kwargs['component'] length = float(eval_equation(length)) except: # not sympy pass ## find the number of fingers and create unwanted edges' index. widthOfFinger = 5.0 ## the width of finger. ## spaceOfEdge = 20.0 upperLimitOfMD = eval_equation(length) / (2.0 * widthOfFinger) - 2.5 nOfmFinger = int(eval_equation(upperLimitOfMD)) if eval_equation(length) < eval_equation(spaceOfEdge + widthOfFinger * 3.0): return "This edge is too short to add finger joint." if male: ##maleFinger nOfOFinger = nOfmFinger else: nOfOFinger = nOfmFinger + 1 lengthOfSpace = (length - (2 * nOfOFinger - 1) * widthOfFinger) / 2.0 widthOfFingerForD = widthOfFinger widthOfDecoration = widthOfFinger t_l = widget(length=eval_equation(lengthOfSpace), width=thick) t = widget(length=eval_equation(widthOfDecoration), width=thick) t_r = widget(length=eval_equation(lengthOfSpace), width=thick) ## for left side space****************** for (name, edge) in t_l.edges.iteritems(): e = edge.copy() e.transform(angle=theta, origin=globalOrigin) face.add_decoration( (((e.x1, e.y1), (e.x2, e.y2)), e.edge_type.edge_type)) try: if kwargs["alternating"]: t.mirrorY() t.transform(origin=(0, thick)) except: pass ##**************************** ## add all of the edges into the face we select ## for i in range(1, nOfOFinger): if (i == 1): movementOfOriginal = eval_equation(widthOfFingerForD + lengthOfSpace) else: movementOfOriginal = eval_equation( widthOfFingerForD + widthOfDecoration ) ## need to revise to be able to fit with assembly t.transform(origin=(movementOfOriginal, 0)) for (name, edge) in t.edges.iteritems(): e = edge.copy() e.transform(angle=theta, origin=globalOrigin) face.add_decoration( (((e.x1, e.y1), (e.x2, e.y2)), e.edge_type.edge_type)) try: if kwargs["alternating"]: t.mirrorY() t.transform(origin=(0, thick)) except: pass ## for right side space****************** t_r.transform(origin=((length / 2.0 + widthOfFingerForD * nOfOFinger - widthOfFingerForD / 2.0), 0)) for (name, edge) in t_r.edges.iteritems(): e = edge.copy() e.transform(angle=theta, origin=globalOrigin) face.add_decoration( (((e.x1, e.y1), (e.x2, e.y2)), e.edge_type.edge_type)) try: if kwargs["alternating"]: t.mirrorY() t.transform(origin=(0, thick)) except: pass
def maleFemaleFingerJointDrawing(l, width, male=True): """ :param l: the length of edge which you want to add finger joint; :param width: the width of finger :param male: type of finger joint, male or female :return: return the coordinates of finger joint face. """ ## create the coordinates for male finger joint. ## # thickOfMaterial = 3.0 ## the thickness of material. # l = eval_equation(l) width = eval_equation(width) widthOfFinger = 5.0 ## the width of finger. ## spaceOfEdge = 20.0 ## the space left to avoid overlapping in corner, such as cube. ## extraSpaceOfFingerJoint = 0.0 ## need calibration ## #width = thickOfMaterial# add more parameters for real world assemble. ## upperLimitOfM = l / ( 2.0 * widthOfFinger ) - 2.5 ## the upper boundary for the number of fingers. ## ## calculate the coordinates of finger joint face. ## if l < eval_equation(spaceOfEdge + widthOfFinger * 3.0): return "This edge is too short to add finger joint." else: nOfmFinger = int(eval_equation( upperLimitOfM)) ## Find out how many fingers we need.## ## male or female finger joint. " if male: ##maleFinger nOfFinger = nOfmFinger else: nOfFinger = nOfmFinger + 1 ## maleFingerDecoration, the number of female fingers must bigger than male by 1. This is the rule. ## ## generate the coordinates module for fingerJoint face (male and female are the same). ## fingerModule_rb = ( (l / 2.0 + widthOfFinger * nOfFinger - widthOfFinger / 2.0), extraSpaceOfFingerJoint) ## rb is right and bottom. ## fingerModule_rt = ( (l / 2.0 + widthOfFinger * nOfFinger - widthOfFinger / 2.0), extraSpaceOfFingerJoint + width) ## right and top## fingerModule_lt = ( (l / 2.0 + widthOfFinger * (nOfFinger - 1.0) - widthOfFinger / 2.0), extraSpaceOfFingerJoint + width) ## lt is left and top. ## fingerModule_lb = ( (l / 2.0 + widthOfFinger * (nOfFinger - 1.0) - widthOfFinger / 2.0), extraSpaceOfFingerJoint) ## left and bottom.## fingerModule = (fingerModule_rb, fingerModule_rt, fingerModule_lt, fingerModule_lb) ## define the coordinates of rest points except the fingers. ## coordinatesOfFingerJoint = ((0, extraSpaceOfFingerJoint), (0, 0), (l, 0), (l, extraSpaceOfFingerJoint)) coordinatesOfFingerSeries = ( ) ## to save the coordinates of points of fingers. ## ## generate coordinates for fingers with a for loop.## if nOfFinger == 1: coordinatesOfFingerSeries = fingerModule else: listOfFingerModule = [ list(x) for x in fingerModule ] ## convert the nested tuple into nested list because tuple is immutable. ## for i in range(nOfFinger): if i == 0: ## when i = 0, just append the tuple. ## coordinatesOfFingerSeries += fingerModule else: ## substruct 10 every time for j in range(len(listOfFingerModule)): listOfFingerModule[j][ 0] = listOfFingerModule[j][0] - 2 * widthOfFinger tupleOfFingerModule = tuple( tuple(li) for li in listOfFingerModule ) ##convert the nested list into nested tuple. ## coordinatesOfFingerSeries += tupleOfFingerModule return coordinatesOfFingerJoint + coordinatesOfFingerSeries
def extractFromComponent(c): output = {} output["solved"] = { str(x): x.get_value() for x in c.parameters.values() if isinstance(x, Variable) } print output["solved"] output["faces"] = {} try: graph = {"edges": [], "faces": []} graph["edges"] = c.composables['graph'].edges graph["faces"] = c.composables['graph'].faces except: pass for i in graph["faces"]: #pdb.set_trace() tdict = copy.deepcopy(i.get_triangle_dict(separateHoles=True)) tdict["holes"] = [] print "Tdict:", tdict for vertex in range(len(tdict["vertices"])): try: tpl = tdict["vertices"][vertex] tdict["vertices"][vertex] = [tpl[0], tpl[1]] if isinstance(tdict["vertices"][vertex][0], sympy.Basic): tdict["vertices"][vertex][0] = scheme_list( tdict["vertices"][vertex][0]) if isinstance(tdict["vertices"][vertex][1], sympy.Basic): tdict["vertices"][vertex][1] = scheme_list( tdict["vertices"][vertex][1]) except: try: tdict["vertices"][vertex][1] = scheme_list( tdict["vertices"][vertex][1]) except: pass try: for hole in range(len(tdict["hole_vertices"])): for vertex in range(len(tdict["hole_vertices"][hole])): try: tpl = tdict["hole_vertices"][hole][vertex] tdict["hole_vertices"][hole][vertex] = [ eval_equation(tpl[0]), eval_equation(tpl[1]) ] if isinstance(tdict["hole_vertices"][hole][vertex][0], sympy.Basic): tdict["hole_vertices"][hole][vertex][ 0] = scheme_list( tdict["hole_vertices"][hole][vertex][0]) if isinstance(tdict["hole_vertices"][hole][vertex][1], sympy.Basic): tdict["hole_vertices"][hole][vertex][ 1] = scheme_list( tdict["hole_vertices"][hole][vertex][1]) except: try: tdict["hole_vertices"][hole][vertex][ 1] = scheme_list( tdict["hole_vertices"][hole][vertex][1]) except: pass except: pass output["faces"][i.name] = [[ scheme_list(i.transform_3D[x]) for x in range(getLen(i.transform_3D)) ], tdict] #print i.transform2D.tolist() trans2D = [[scheme_list(p) for p in j] for j in getList(i.transform_2D)] #print trans2D output["faces"][i.name].append(trans2D) output["edges"] = {} for i in graph["edges"]: output["edges"][i.name] = [] for v in range(2): output["edges"][i.name].append([]) for x in range(3): try: if isinstance(i.pts_3D[v][x], sympy.Basic): output["edges"][i.name][v].append( scheme_list(i.pts_3D[v][x])) except: pass output["interfaceEdges"] = {} output["interfaceFaces"] = [] print c.interfaces for k, v in c.interfaces.iteritems(): ports = c.get_interface(k).get_ports() for port in ports: if isinstance(port, edge_port.EdgePort): output["interfaceEdges"][k] = [] for i in port.get_edges(): try: output["interfaceEdges"][k].append(i) except: pass if isinstance(port, face_port.FacePort): output["interfaceFaces"].append(k) return output
def place_faces(self, face, edge_from, transform_2D, placed=None, allow_overlap=False): """Recursively adds faces to the 2D drawing. Args: face: the current face being placed edge_from: the edge by which to attach the current face transform_2D: A tranformation matrix to move the face into its position in 2D space placed: dictionary containing metadata about previously placed entities allow_overlap: Whether or not to allow two face to be placed on top of each other """ if placed is not None and face in placed['faces']: #This face has already been placed, do not place again return if placed is None: #No faces have been placed yet, initialize data structures placed = {'faces': [], 'edges': {}, 'overlapping': []} check_for_overlap = not allow_overlap else: #Overlap checking is handled only in top level call check_for_overlap = False """ Placing faces involves the notion of "pretransformed" and "transformed" values. Pretransformation moves the edge a face is being connected by to the x axis, and can be thought of as a face's relative position to its neighbor. Transformation moves a face to its absolute position in 2D space. """ if edge_from is not None: #Align connected edges pretransform_matrix = face.pre_transform(edge_from) else: #Place edge as is pretransform_matrix = np.eye(4) transform_matrix = np.dot(transform_2D, pretransform_matrix) #4D pts are the homogenous coordinates of the face i.e. [x,y,z,1] pretransformed_pts_4D = np.dot(pretransform_matrix, face.pts_4D) transfromed_pts_4D = np.dot(transform_matrix, face.pts_4D) pretransformed_pts_2D = pretransformed_pts_4D[0:2,:] #Numerical values for the coordinates are required for placement transfromed_pts_2D = eval_equation(transfromed_pts_4D[0:2, :]) if not self.add_face(transfromed_pts_2D): #If face cannot be placed without collisions, attempt to reflect it reflection_matrix = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) #Recompute pretransform and transform with rotation pretransform_matrix = np.dot(reflection_matrix, pretransform_matrix) transform_matrix = np.dot(transform_2D, pretransform_matrix) pretransformed_pts_4D = np.dot(pretransform_matrix, face.pts_4D) transfromed_pts_4D = np.dot(transform_matrix, face.pts_4D) pretransformed_pts_2D = pretransformed_pts_4D[0:2,:] transfromed_pts_2D = eval_equation(transfromed_pts_4D[0:2, :]) if not self.add_face(transfromed_pts_2D) and not allow_overlap: #Face was not able to be placed connected to this edge #Keep track of face and hope it gets placed elsewhere #TODO: Try connecting along other edges or undoing previous placements? placed['overlapping'].append(face) return #Face is being placed placed['faces'].append(face) if face in placed['overlapping']: placed['overlapping'].remove(face) face.transform_2D = transform_matrix #Will this break if a face has to be flipped? ## find out how to transform the decoration. ## for e in face.get_2D_decorations(): self.edges[e[0]] = DrawingEdge(e[0], [eval_equation(x) for x in e[1]], [eval_equation(x) for x in e[2]], EdgeType(e[3])) ## edges here is a dictionary, the key is decoration edge name. e is nested list and its first element is the edge name. ## #Place each edge for (i, edge) in enumerate(face.edges): #HACK: Do not place temporary edges if edge is None or edge.name[:4] == "temp": continue #Get the endpoints of the edge edge_pts_2D = (transfromed_pts_2D[:,i - 1],transfromed_pts_2D[:,i]) if edge.name in placed['edges'].keys(): edge_alias = placed['edges'][edge.name] if diff_edge(edge_alias, edge_pts_2D,2): #If the edge has already been placed in a different place, a cut must be made #Create a new edge self.edges['temp' + edge.name] = DrawingEdge('temp' + edge.name, edge_pts_2D[0], edge_pts_2D[1], Cut()) # Make old edge into a cut self.edges[edge.name] = DrawingEdge(edge.name, edge_alias[0], edge_alias[1], Cut()) else: #Add edge normally if len(edge.faces) == 1: edge_type = Cut() else: edge_type = Fold() self.edges[edge.name] = DrawingEdge(edge.name, edge_pts_2D[0], edge_pts_2D[1], edge_type) placed['edges'][edge.name] = edge_pts_2D if len(edge.faces) <= 1: # No other faces to be found, move on to next edge. continue if edge.is_tab(): # Don't follow faces off of a Tab continue #Compute new transform matrix for next face rotation_matrix = rotate_x_to(pretransformed_pts_2D[:,i],pretransformed_pts_2D[:,i-1]) origin_matrix = move_origin_to(pretransformed_pts_2D[:,i-1]) next_transfrom_2D = np.dot(transform_2D,np.dot(origin_matrix,np.dot(rotation_matrix,np.eye(4)))) #Place faces connected to edge for(f,a) in edge.faces.iteritems(): self.place_faces(f, edge, next_transfrom_2D, placed) if check_for_overlap and len(placed['overlapping']): #Placement has finished, but some edges are still unplaced raise Exception('One or more faces could not be placed without overlap!')
def maleFemaleFingerJointDecorationDrawing(length, width, male=True): """ :param length: the length of edge to add finger joint; :param width: the width of finger joint; :return: return coordinates of finger joint decoration; """ widthOfFingerForD = 5.0 ## the width of finger. ## extraSpaceOfFingerJointForD = 0.0 compensationForAssembly = 0.5 spaceOfEdgeForD = 20.0 ## the space left to avoid overlapping in corner, such as cube. ## upperLimitOfMD = eval_equation(length) / ( 2.0 * widthOfFingerForD ) - 2.5 ## the upper boundary for the number of fingers. ## length = eval_equation(length) width = eval_equation(width) ## calculate the coordinates of finger joint face. ## if length < eval_equation(spaceOfEdgeForD + widthOfFingerForD * 3.0): return "This edge is too short to add finger joint." else: nOfmFinger = int(eval_equation( upperLimitOfMD)) ## Find out how many fingers we need.## # print (nOfmFinger) if male: ##maleFinger nOfOFinger = nOfmFinger adjustment = compensationForAssembly ## nOfOFinger is the number of opposite finger joint. it is the same as finger joints. ## else: nOfOFinger = nOfmFinger + 1 adjustment = -compensationForAssembly ## maleFingerDecoration, the number of female fingers must bigger than male by 1. This is the rule. ## ## the module here is slightly different from finger joint ## fingerModule_rb = ( (length / 2.0 + widthOfFingerForD * nOfOFinger - widthOfFingerForD / 2.0) + adjustment, extraSpaceOfFingerJointForD ) ## rb is right and bottom. ## fingerModule_rt = ( (length / 2.0 + widthOfFingerForD * nOfOFinger - widthOfFingerForD / 2.0) + adjustment, width + extraSpaceOfFingerJointForD) ## right and top## fingerModule_lt = ( (length / 2.0 + widthOfFingerForD * (nOfOFinger - 1.0) - widthOfFingerForD / 2.0) - adjustment, width + extraSpaceOfFingerJointForD) ## lt is left and top. ## fingerModule_lb = ( (length / 2.0 + widthOfFingerForD * (nOfOFinger - 1.0) - widthOfFingerForD / 2.0) - adjustment, extraSpaceOfFingerJointForD) ## left and bottom.## ## the order should be shown as following. ## fingerDecorationModule = (fingerModule_rt, fingerModule_rb, fingerModule_lb, fingerModule_lt) ## define the coordinates of rest points except the fingers. ## # coordinatesOfFingerJoint = ((length, 0), (length, width)) coordinatesOfFingerDecoration = ((0, width + extraSpaceOfFingerJointForD), (0, 0), (length, 0), (length, width + extraSpaceOfFingerJointForD)) coordinatesOfFingerSeriesDecoration = ( ) ## to save the coordinates of points of fingers. ## ## generate coordinates for fingers with a for loop.## if nOfOFinger == 1: coordinatesOfFingerSeriesDecoration = fingerDecorationModule else: listOfDFingerModule = [ list(x) for x in fingerDecorationModule ] ## convert the nested tuple into nested list because tuple is immutable. ## for i in range(nOfOFinger): if i == 0: ## when i = 0, just append the tuple. ## coordinatesOfFingerSeriesDecoration += fingerDecorationModule else: ## subtract 10 every time for j in range(len(listOfDFingerModule)): listOfDFingerModule[j][ 0] = listOfDFingerModule[j][0] - 2 * widthOfFingerForD tupleOfFingerModule = tuple( tuple(li) for li in listOfDFingerModule ) ##convert the nested list into nested tuple. ## coordinatesOfFingerSeriesDecoration += tupleOfFingerModule return coordinatesOfFingerDecoration + coordinatesOfFingerSeriesDecoration
def maleFemaleFingerJointDecoration(face, faceEdge, thick, widget, male=True, **kwargs): """ help to find how many fingers we need for different subcomponent.And add these fingers into the face. :param face: The face we add decoration; :param faceEdge: the edge we refer to; :param thick: the width of finger, it usually is 3.0mm. :param male: the type of decoration; :param widget: a face object to represent the finger; :param kwargs: kwargs; :return: None. the decoration will be added into selected face after operation """ coords = face.edge_coords(face.edge_index(faceEdge)) globalOrigin = coords[0] theta = arctan2(coords[1][1] - coords[0][1], coords[1][0] - coords[0][0]) length = norm((coords[1][1] - coords[0][1], coords[1][0] - coords[0][0])) try: component = kwargs['component'] length = float(eval_equation(length)) except: # not sympy pass t = widget(length=length, width=thick, male=male) try: if kwargs["mirror"]: t.mirrorY() t.transform(origin=(0, thick / 2.0)) except: pass ## find the number of fingers and create unwanted edges' index. widthOfFingerForD = 5.0 ## the width of finger. ## upperLimitOfMD = eval_equation(length) / (2.0 * widthOfFingerForD) - 2.5 nOfmFinger = int(eval_equation(upperLimitOfMD)) if male: ##maleFinger nOfOFinger = nOfmFinger else: nOfOFinger = nOfmFinger + 1 unWantedIndex = range(2, 3 + nOfOFinger * 4, 4) ## 2, 6, 10, 14 and so on. unWantedIndex.append(1) unWantedIndex.append(3) unWantedEdgeNames = ["e%d" % i for i in unWantedIndex] ## add all of the edges into the face we select ## for (name, edge) in t.edges.iteritems(): e = edge.copy() e.transform(angle=theta, origin=globalOrigin) if name in unWantedEdgeNames: ## ignore all the bottom edge. ## continue face.add_decoration( (((e.x1, e.y1), (e.x2, e.y2)), e.edge_type.edge_type)) try: if kwargs["alternating"]: t.mirrorY() t.transform(origin=(0, thick)) except: pass