def calculate(FILE_IN, plot_flag): for file in FILE_IN: #print("Calculating",file) assembly = Assembly.from_json(file) # ============================================================================== # Identify interfaces # ============================================================================== assembly_interfaces_numpy(assembly, tmax=0.02) # ============================================================================== # Equilibrium # ============================================================================== compute_interface_forces_cvx(assembly, solver='CPLEX', verbose=False) #compute_interface_forces_cvx(assembly, solver='ECOS', verbose=True) # ============================================================================== # Export # ============================================================================== assembly.to_json(output_path(file)) if plot_flag: R = Rotation.from_axis_and_angle([1.0, 0, 0], -pi / 2) assembly.transform(R) plotter = AssemblyPlotter(assembly, figsize=(16, 10), tight=True) plotter.draw_nodes(radius=0.05) plotter.draw_edges() plotter.draw_blocks( facecolor={ key: '#ff0000' for key in assembly.nodes_where({'is_support': True}) }) plotter.show()
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 RunCommand(is_interactive): try: if 'compas_assembly' not in sc.sticky: raise Exception('Initialise the Assembly plugin first!') settings = sc.sticky['compas_assembly']['settings'] # the default path points to the wrong location path = compas_rhino.select_file(folder=compas_assembly.DATA, filter='JSON files (*.json)|*.json||') if not path: return assembly = Assembly.from_json(path) sc.sticky['compas_assembly']['assembly'] = assembly assembly.draw(settings) except Exception as error: print(error) print(traceback.format_exc())
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 RunCommand(is_interactive): try: if 'compas_assembly' not in sc.sticky: raise Exception('Initialise the Assembly plugin first!') settings = sc.sticky['compas_assembly']['settings'] guids = compas_rhino.select_surfaces() assembly = Assembly() assembly.add_blocks_from_polysurfaces(guids) assembly.draw(settings) sc.sticky['compas_assembly']['assembly'] = assembly except Exception as error: print(error) print(traceback.format_exc())
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 if i % 2 == 0: # in the even rows # add (number_of_even_bricks) full bricks for j in range(number_of_even_bricks): block = brick.copy() mesh_transform(block, Translation([j * (width + gap), 0, dy])) assembly.add_block(block) else:
import compas from compas_assembly.datastructures import Assembly from compas_assembly.geometry import Arch from compas_assembly.rhino import AssemblyArtist FILE = os.path.join(os.path.dirname(__file__), 'arch_assembly.json') rise = 5 span = 10 thickness = 0.7 depth = 0.5 n = 40 arch = Arch(rise, span, thickness, depth, n) assembly = Assembly.from_geometry(arch) assembly.node_attribute(0, 'is_support', True) assembly.node_attribute(n - 1, 'is_support', True) compas.json_dump(assembly, FILE) artist = AssemblyArtist(assembly, layer="Arch::Assembly") artist.clear_layer() artist.draw_nodes(color={ key: (255, 0, 0) for key in assembly.nodes_where({'is_support': True}) }) artist.draw_blocks()
try: HERE = os.path.dirname(__file__) except NameError: HERE = os.getcwd() DATA = os.path.join(HERE, '../../../data') FILE_I = os.path.join(DATA, 'dome.json') FILE_O = os.path.join(DATA, 'dome.json') # ============================================================================== # Load assembly from file # ============================================================================== assembly = Assembly.from_json(FILE_I) # ============================================================================== # Identify interfaces # ============================================================================== assembly_interfaces_numpy(assembly, tmax=0.05) # ============================================================================== # Export # ============================================================================== assembly.to_json(FILE_O) # ============================================================================== # Visualize
""" 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())
""" import os from compas_assembly.datastructures import Assembly from compas_rbe.equilibrium import compute_interface_forces_cvx HERE = os.path.dirname(__file__) DATA = os.path.join(HERE, '../data') PATH_FROM = os.path.join(DATA, '090_wall_courses.json') PATH_TO = os.path.join(DATA, '091_wall_equilibrium.json') # load an assembly from a JSON file assembly = Assembly.from_json(PATH_FROM) # check the supports supports = list(assembly.vertices_where({'is_support': True})) if not supports: raise Exception('The assembly has no supports.') # compute the interface forces compute_interface_forces_cvx(assembly, solver='CPLEX', verbose=True) # serialise to json assembly.to_json(PATH_TO)
# number of blocks N = 10 # 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)
i_index = {i: index for index, i in enumerate(vertices)} vertices = [points[index] for index in vertices] faces = [[i_index[i] for i in face] for face in faces] if unify: faces = unify_cycles(vertices, faces) return vertices, faces # ============================================================================== # Main # ============================================================================== if __name__ == '__main__': import compas_assembly from compas.datastructures import Mesh from compas.viewers import MeshViewer from compas_assembly.datastructures import Assembly assembly = Assembly.from_json(compas_assembly.get('assembly.json')) vertices, faces = assembly_hull_numpy(assembly) hull = Mesh.from_vertices_and_faces(vertices, faces) viewer = MeshViewer() viewer.mesh = hull viewer.show()
""" from math import pi import compas_assembly from compas.geometry import Rotation from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import assembly_transform from compas_rbe.equilibrium import compute_interface_forces_cvx from compas_assembly.plotter import AssemblyPlotter # load assembly assembly = Assembly.from_json(compas_assembly.get('stack.json')) # compute interface forces compute_interface_forces_cvx(assembly, solver='CVXOPT', verbose=True) # serialise assembly.to_json(compas_assembly.get('stack.json')) # visualise R = Rotation.from_axis_and_angle([1.0, 0, 0], -pi / 2) assembly_transform(assembly, R) plotter = AssemblyPlotter(assembly, tight=True)
from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import assembly_interfaces_numpy from compas_rbe.equilibrium import compute_interface_forces_cvx # load assembly assembly = Assembly.from_json('assembly_taubman.json') # identify_interfaces assembly_interfaces_numpy(assembly, nmax=10, amin=0.0001) # compute equilibrium compute_interface_forces_cvx(assembly, solver='CPLEX', verbose=True) # export to json assembly.to_json('equilibrium_taubman.json')
# brick geometry box = Box.from_width_height_depth(width, height, depth) brick = Block.from_shape(box) # halfbrick geometry box = Box.from_width_height_depth(0.5 * (width - gap), height, depth) halfbrick = Block.from_shape(box) # ============================================================================== # Assembly # ============================================================================== assembly = Assembly() for i in range(number_of_courses): dy = (0.5 + i) * height if i % 2 == 0: # in the even rows # add (number_of_even_bricks) full bricks for j in range(number_of_even_bricks): dx = 0.5 * width + j * (width + gap) T = Translation.from_vector([dx, 0, dy]) block = brick.copy() block.transform(T) assembly.add_block(block) else: # add a half brick
from __future__ import absolute_import from __future__ import division import compas import compas_rbe from compas_assembly.datastructures import Assembly from compas_assembly.interfaces import assembly_interfaces_bestfit from compas_assembly.interfaces import planarize_interfaces from compas_assembly.viewer import AssemblyViewer from compas_rbe.equilibrium import compute_interface_forces # initialize assembly and blocks from json file assembly = Assembly.from_json(compas_rbe.get('simple_stack_curvedsrf2.json')) # print(list(assembly.vertices_where({'is_support': True}))) # identify block interfaces and update block_model assembly_interfaces_bestfit( assembly, nmax=10, tmax=0.5, amin=0.01, lmin=0.01, ) # TODO: Planerize all interfaces first before compute interface forces # planarize_interfaces(assembly.edge)
DATA = os.path.join(HERE, '../data') PATH = os.path.join(DATA, 'stack.json') # number of blocks N = 10 # block dimensions W = 2.0 H = 0.5 D = 1.0 # empty assembly assembly = Assembly() # default block box = Box.from_width_height_depth(W, H, D) block = Block.from_vertices_and_faces(box.vertices, box.faces) # make all blocks # place each block on top of previous # shift block randomly in XY plane for i in range(N): b = block.copy() factor = choice([0.01, -0.01, 0.05, -0.05, 0.1, -0.1]) axis = choice([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
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
from compas_view2.objects import Collection FILE_I = os.path.join(os.path.dirname(__file__), 'crossvault_meshes.json') FILE_O = os.path.join(os.path.dirname(__file__), 'crossvault_assembly.json') # ============================================================================== # Load meshes # ============================================================================== meshes = compas.json_load(FILE_I) # ============================================================================== # Construct assembly # ============================================================================== assembly = Assembly() for mesh in meshes: block = mesh.copy(cls=Block) assembly.add_block(block) # ============================================================================== # Export # ============================================================================== compas.json_dump(assembly, FILE_O) # ============================================================================== # Viz # ============================================================================== viewer = App()
import os import compas_rhino from compas_assembly.datastructures import Assembly from compas_assembly.rhino import AssemblyHelper HERE = os.path.abspath(os.path.dirname(__file__)) drawsettings = { 'show.vertices': True, 'layer': 'Assembly', } wall = Assembly() guids = compas_rhino.select_surfaces() wall.add_blocks_from_polysurfaces(guids) wall.draw(drawsettings) while True: keys = AssemblyHelper.select_vertices(wall) if not keys: break if AssemblyHelper.update_vertex_attributes(wall, keys): wall.draw(drawsettings) wall.to_json(os.path.join(HERE, '../data/frompolysurfaces.json'))
import os from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import assembly_block_building_sequence from compas_assembly.rhino import AssemblyArtist from compas_assembly.rhino import AssemblyHelper # just so Rhino(Mac) gets the filepaths right HERE = os.path.dirname(__file__) # load an assembly from a JSON file assembly = Assembly.from_json(os.path.join(HERE, '../data/wall_courses.json')) # make a list of the blocks that were already placed placed = list(assembly.vertices_where({'is_placed': True})) # draw the assembly artist = AssemblyArtist(assembly, layer="Assembly") artist.clear_layer() artist.draw_vertices() artist.draw_blocks(show_faces=False, show_edges=True) # draw filled in blocks for the placed ones
from compas_assembly.datastructures import Assembly import rhinoscriptsyntax as rs from compas.geometry import centroid_points import math as mt # load assembly assembly = Assembly.from_json('equilibrium_taubman.json') # plot assembly in Rhino assembly.draw({ 'layer': 'Assembly', 'show.selfweight': True, 'show.vertices': True, 'show.edges': True, 'show.forces': True, 'show.forces_as_vectors': True, 'show.interfaces': True, 'mode.interface': 0, 'mode.force': 0, 'scale.force': 10.0 }) rs.CurrentLayer('Assembly') rs.LayerVisible('Blocks', False) rs.LayerVisible('Supports', False) rs.AddLayer('forces') rs.LayerColor('forces', (255, 0, 0)) rs.DeleteObjects(rs.ObjectsByLayer('forces')) rs.CurrentLayer('forces')
from math import pi import compas_assembly from compas.utilities import i_to_red from compas.geometry import Rotation from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import assembly_transform from compas_assembly.plotter import AssemblyPlotter assembly = Assembly.from_json(compas_assembly.get('wall_courses.json')) # visualise R = Rotation.from_axis_and_angle([1.0, 0, 0], -pi / 2) assembly_transform(assembly, R) plotter = AssemblyPlotter(assembly, figsize=(16, 6), tight=True) plotter.assembly_plotter.defaults['vertex.fontsize'] = 10 courses = assembly.get_vertices_attribute('course') c_min = min(courses) c_max = max(courses) c_spn = c_max - c_min facecolor = { key: i_to_red((attr['course'] - c_min) / c_spn) for key, attr in assembly.vertices(True)
i_index = {i: index for index, i in enumerate(vertices)} vertices = [points[index] for index in vertices] faces = [[i_index[i] for i in face] for face in faces] if unify: faces = unify_cycles(vertices, faces) return vertices, faces # ============================================================================== # Main # ============================================================================== if __name__ == '__main__': import compas_assembly from compas.datastructures import Mesh from compas_viewers.meshviewer import MeshViewer from compas_assembly.datastructures import Assembly assembly = Assembly.from_json(compas_assembly.get('wall_interfaces.json')) vertices, faces = assembly_hull_numpy(assembly) hull = Mesh.from_vertices_and_faces(vertices, faces) viewer = MeshViewer() viewer.mesh = hull viewer.show()
import os import compas from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import Block from compas_assembly.rhino import AssemblyArtist FILE_I = os.path.join(os.path.dirname(__file__), 'armadillo_meshes.json') FILE_O = os.path.join(os.path.dirname(__file__), 'armadillo_assembly.json') meshes = compas.json_load(FILE_I) assembly = Assembly() for mesh in meshes: block = mesh.copy(cls=Block) assembly.add_block(block) compas.json_dump(assembly, FILE_O) artist = AssemblyArtist(assembly, layer="Armadillo::Assembly") artist.clear_layer() artist.draw_nodes(color={ key: (255, 0, 0) for key in assembly.nodes_where({'is_support': True}) }) artist.draw_blocks()
from compas.geometry import Rotation from compas_assembly.datastructures import Assembly from compas_assembly.datastructures import assembly_transform from compas_rbe.equilibrium import compute_interface_forces_cvx from compas_assembly.plotter import AssemblyPlotter HERE = os.path.dirname(__file__) DATA = os.path.join(HERE, '../data') PATH = os.path.join(DATA, 'stack.json') # load assembly assembly = Assembly.from_json(PATH) # compute interface forces compute_interface_forces_cvx(assembly, solver='CPLEX', verbose=True) # serialise assembly.to_json(PATH) # visualise R = Rotation.from_axis_and_angle([1.0, 0.0, 0.0], -pi / 2) assembly_transform(assembly, R) plotter = AssemblyPlotter(assembly, figsize=(10, 7))
HERE = os.path.dirname(__file__) DATA = os.path.join(HERE, '../data') # number of blocks N = 10 # block dimensions W = 2.0 H = 0.5 D = 1.0 # empty assembly assembly = Assembly() # default block box = Box.from_width_height_depth(W, H, D) block = Block.from_vertices_and_faces(box.vertices, box.faces) # make all blocks # place each block on top of previous # shift block randomly in XY plane for i in range(N): b = block.copy() factor = choice([0.01, -0.01, 0.05, -0.05, 0.1, -0.1]) axis = choice([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
from compas_assembly.rhino import AssemblyArtist from compas.rpc import Proxy # prepare proxy for RPC proxy = Proxy('compas_assembly.datastructures') # load meshes FILE = os.path.join(os.path.dirname(__file__), 'armadillo.json') meshes = compas.json_load(FILE) # construct assembly assembly = Assembly() for mesh in meshes: block = mesh.copy(cls=Block) assembly.add_block(block) # identify interfaces assembly = proxy.assembly_interfaces_numpy(assembly, tmax=0.02, amin=0.0001) # ============================================================================== # Visualization # ============================================================================== artist = AssemblyArtist(assembly, layer="Armadillo") artist.clear_layer()
# number of blocks N = 10 # 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)