def from_json(cls, filepath): """Construct an assembly from the data contained in a JSON file. Parameters ---------- filepath : str Path to the file containing the data. Returns ------- Assembly An assembly data structure. Examples -------- .. code-block:: python assembly = Assembly.from_json('assembly.json') """ from compas_assembly.datastructures import Block with open(filepath, 'r') as fo: data = json.load(fo) # vertex keys in an assembly can be of any hashable type # keys in the blocks dict should be treated the same way! assembly = cls.from_data(data['assembly']) assembly.blocks = { int(key): Block.from_data(data['blocks'][key]) for key in data['blocks'] } return assembly
def assembly_interfaces_xfunc(data, **kwargs): """Convenience wrapper for ``assembly_interfaces_numpy`` that can be used with ``XFunc`` or ``RPC``. Parameters ---------- data : dict The data dictionary representing an assembly data structure. The dict has the following items: * assembly: the assembly data * blocks: the data per block Returns ------- dict A data dict with the same structure as the input dict. Notes ----- For additional named parameters that can be passed to this function, see ``assembly_interfaces_numpy``. Examples -------- .. code-block:: python assembly_interfaces_xfunc = XFunc('compas_assembly.datastructures.assembly_interfaces_xfunc') data = {'assembly': assembly.to_data(), 'blocks': {str(key): assembly.blocks[key].to_data() for key in assembly.vertices()}} result = assembly_interfaces_xfunc(data) assembly.data = result['assembly'] assembly.blocks = {int(key): Block.from_data(data) for key, data in result['blocks']} """ from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import Block assembly = Assembly.from_data(data['assembly']) assembly.blocks = { int(key): Block.from_data(data['blocks'][key]) for key in data['blocks'] } assembly_interfaces_numpy(assembly, **kwargs) return { 'assembly': assembly.to_data(), 'blocks': {str(key): assembly.blocks[key].to_data() for key in assembly.blocks} }
def add_blocks_from_rhinomeshes(self, guids): """Add multiple blocks from their representation as as Rhino meshes. Parameters ---------- guids : list of str A list of GUIDs identifying the meshes representing the blocks of the assembly. Returns ------- list The keys of the added blocks. Warning ------- This method only works in Rhino. Examples -------- .. code-block:: python assembly = Assembly() guids = compas_rhino.select_meshes() assembly.add_blocks_from_rhinomeshes(guids) """ from compas_assembly.datastructures import Block onames = compas_rhino.get_object_names(guids) keys = [] for i, (guid, oname) in enumerate(zip(guids, onames)): try: attr = ast.literal_eval(oname) except (TypeError, ValueError): attr = {} name = attr.get('name', 'B{0}'.format(i)) block = Block.from_rhinomesh(guid) block.attributes['name'] = name key = self.add_block(block, attr_dict=attr) keys.append(key) return keys
def compute_interface_forces_xfunc(data, backend='cvx', **kwargs): from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import Block assembly = Assembly.from_data(data['assembly']) assembly.blocks = { int(key): Block.from_data(data['blocks'][key]) for key in data['blocks'] } if backend == 'cvx': compute_interface_forces_cvx(assembly, **kwargs) if backend == 'cvxopt': compute_interface_forces_cvxopt(assembly, **kwargs) return { 'assembly': assembly.to_data(), 'blocks': {str(key): assembly.blocks[key].to_data() for key in assembly.blocks} }
def from_json(cls, filepath): """Construct an assembly from the data contained in a JSON file. Parameters ---------- filepath : str Path to the file containing the data. Returns ------- Assembly An assembly data structure. Examples -------- >>> """ from compas_assembly.datastructures import Block with open(filepath, 'r') as fo: data = json.load(fo) assembly = cls.from_data(data['assembly']) assembly.blocks = {int(key): Block.from_data(data['blocks'][key]) for key in data['blocks']} return assembly
# block dimensions W = 2.0 H = 0.5 D = 1.0 # ============================================================================== # Assembly # ============================================================================== assembly = Assembly() # default block box = Box.from_width_height_depth(W, H, D) brick = Block.from_shape(box) # make all blocks # place each block on top of previous # shift block randomly in XY plane for i in range(N): block = brick.copy() block.transform(Translation.from_vector([0, 0, 0.5 * H + i * H])) shift(block) assembly.add_block(block) # mark the bottom block as support assembly.node_attribute(0, 'is_support', True)
def arch_from_rise_and_span(height, span, depth, thickness, n): """Create a semicircular arch from rise and span. Parameters ---------- height : float ... span : float Dimension of the span in meter measured at the impost level (intrados-intrados). depth : float Depth in meter of the arch perpendicular to the front view plane. thickness : float Thickness in meter of the arch. n: int number of voussoirs. Returns ------- Assembly Data structure of the semicircular arch. """ assembly = Assembly() if height > span / 2: raise Exception("Not a semicircular arch.") radius = height / 2 + (span**2 / (8 * height)) base = [0.0, 0.0, 0.0] top = [0.0, 0.0, height] left = [-span / 2, 0.0, 0.0] center = [0.0, 0.0, height - radius] vector = subtract_vectors(left, center) springing = angle_vectors(vector, [-1.0, 0.0, 0.0]) sector = radians(180) - 2 * springing angle = sector / n a = top b = add_vectors(top, [0, depth, 0]) c = add_vectors(top, [0, depth, thickness]) d = add_vectors(top, [0, 0, thickness]) R = Rotation.from_axis_and_angle([0, 1.0, 0], 0.5 * sector, center) bottom = transform_points([a, b, c, d], R) blocks = [] for i in range(n): R = Rotation.from_axis_and_angle([0, 1.0, 0], -angle, center) top = transform_points(bottom, R) vertices = bottom + top faces = [[0, 1, 2, 3], [7, 6, 5, 4], [3, 7, 4, 0], [6, 2, 1, 5], [7, 3, 2, 6], [5, 1, 0, 4]] block = Block.from_vertices_and_faces(vertices, faces) assembly.add_block(block) bottom = top assembly.node_attribute(0, 'is_support', True) assembly.node_attribute(n - 1, 'is_support', True) return assembly
number_of_courses = 7 # brick dimensions width = 0.240 height = 0.052 depth = 0.116 # horizontal joints gap = 0.02 # brick geometry box = Box.from_width_height_depth(width, height, depth) brick = Block.from_vertices_and_faces(box.vertices, box.faces) # halfbrick geometry box = Box.from_width_height_depth(0.5 * (width - gap), height, depth) halfbrick = Block.from_vertices_and_faces(box.vertices, box.faces) # empty assembly assembly = Assembly() # add bricks in a staggered pattern for i in range(number_of_courses): dy = i * height
""" cls = type(self) sub = cls() for key, attr in self.nodes(True): if key in keys: block = self.blocks[key].copy() sub.add_node(key=key, **attr) sub.blocks[key] = block for u, v, attr in self.edges(True): if u in keys and v in keys: sub.add_edge(u, v, **attr) return sub # ============================================================================== # Main # ============================================================================== if __name__ == "__main__": from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import Block assembly = Assembly() for i in range(2): block = Block.from_polyhedron(6) assembly.add_block(block) print(assembly.summary())
# block dimensions W = 2.0 H = 0.5 D = 1.0 # ============================================================================== # Assembly # ============================================================================== assembly = Assembly() # default block box = Box.from_width_height_depth(W, H, D) brick = Block.from_shape(box) # make all blocks # place each block on top of previous # shift block randomly in XY plane for i in range(N): block = brick.copy() block.transform(Translation([0, 0, 0.5 * H + i * H])) shift(block) assembly.add_block(block) # mark the bottom block as support assembly.node_attribute(0, 'is_support', True)
proxy.package = 'compas_rbe.equilibrium' data = { 'assembly': assembly.to_data(), 'blocks': {str(key): assembly.blocks[key].to_data() for key in assembly.blocks} } data = proxy.compute_interface_forces_xfunc(data, backend='CVX', solver='CPLEX') assembly.data = data['assembly'] assembly.blocks = { int(key): Block.from_data(data['blocks'][key]) for key in data['blocks'] } # ============================================================================== # Visualize # ============================================================================== artist = AssemblyArtist(assembly, layer="Arch") artist.clear_layer() artist.draw_blocks() # artist.draw_edges() artist.draw_nodes(color={ key: (255, 0, 0) for key in assembly.nodes_where({'is_support': True}) })
import compas from compas.datastructures import mesh_transform from compas.geometry import Translation from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import Block from compas_assembly.datastructures import assembly_interfaces from compas_assembly.viewer import AssemblyViewer from compas_rbe.equilibrium import compute_interface_forces_cvx assembly = Assembly() b1 = Block.from_polyhedron(6) b2 = Block.from_polyhedron(6) u, v = list(b1.edges())[0] l = b1.edge_length(u, v) T1 = Translation([0, 0, -0.5 * l]) T2 = Translation([0, 0, +0.5 * l]) mesh_transform(b1, T1) mesh_transform(b2, T2) assembly.add_block(b1, is_support=True) assembly.add_block(b2)
from compas.datastructures import mesh_weld from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import Block from compas_rhino.utilities import get_meshes # get support meshes and block meshes from Rhino rhino_supports = get_meshes("Supports") rhino_blocks = get_meshes("Blocks") # create and weld compas meshes supports = [] for i in rhino_supports: support = Block.from_rhinomesh(i) support = mesh_weld(support) supports.append(support) blocks = [] for i in rhino_blocks: block = Block.from_rhinomesh(i) block = mesh_weld(block) blocks.append(block) # create an assembly assembly = Assembly() for i in supports: assembly.add_block(i, is_support=True) for i in blocks: assembly.add_block(i, is_support=False) # export the assembly in a .json file
# list the coordinates of all vertices of all blocks points = [] for key in assembly.vertices(): block = assembly.blocks[key] xyz = block.get_vertices_attributes('xyz') points.extend(xyz) # compute the XY bounding box of all listed vertices bbox = bounding_box_xy(points) # make a support block of the same size as the bounding box support = Block.from_vertices_and_faces(bbox, [[0, 1, 2, 3]]) # scale the support lx = length_vector(subtract_vectors(bbox[1], bbox[0])) ly = length_vector(subtract_vectors(bbox[2], bbox[1])) sx = (0.0 + lx) / lx sy = (0.0 + ly) / ly S = Scale([sx, sy, 1.0]) mesh_transform(support, S) # align the centroid of the support with the centroid of the bounding box b = centroid_points(bbox) a = support.centroid()
data = {} assembly_data = assembly.to_data() blocks_data = {key: block.to_data() for key, block in assembly.blocks.items()} data['assembly'] = assembly_data data['blocks'] = blocks_data with Proxy('compas_assembly.datastructures') as dt: data = dt.assembly_interfaces_xfunc(data) with Proxy('compas_rbe.equilibrium') as eq: data = eq.compute_interface_forces_xfunc(data) assembly = Assembly.from_data(data['assembly']) assembly.blocks = {int(key): Block.from_data(data['blocks'][key]) for key in data['blocks']} # ============================================================================== # Visualize # ============================================================================== assembly.to_json(FILE_OUT) artist = AssemblyArtist(assembly, layer="Wall") artist.clear_layer() artist.draw_blocks() artist.draw_interfaces() artist.draw_resultants(scale=0.05) #has an issue with division by zero #artist.color_interfaces(mode=1)
# from compas_assembly.geometry import Arch from compas_assembly.datastructures import Block, Assembly, assembly_interfaces_numpy # from compas_assembly.rhino import AssemblyArtist # from compas_assembly.blender import AssemblyArtist # from compas.rpc import Proxy from compas_view2.app import App from compas_view2.objects import Object, MeshObject, NetworkObject Object.register(Block, MeshObject) Object.register(Assembly, NetworkObject) # proxy = Proxy('compas_assembly.datastructures') # proxy.restart_server() b1 = Block.from_shape(Box.from_width_height_depth(1, 1, 1)) T = Translation.from_vector([0, 0, 1]) R = Rotation.from_axis_and_angle([0, 0, 1], radians(45)) b2 = b1.transformed(T * R) assembly = Assembly() assembly.add_block(b1) assembly.add_block(b2) # arch = Arch(rise=5, span=10, thickness=0.7, depth=0.5, n=40) # assembly = Assembly.from_geometry(arch) assembly_interfaces_numpy(assembly)