The examples shown in this section were created using RV2 v1.0.0. They will be updated soon, and be compatible with the latest release of RV2.
from compas.datastructures import Meshfrom compas_rhino.artists import MeshArtistFILE_I1 ='form_idos.json'FILE_I2 ='form_edos.json'FILE_O ='blocks.json'idos = Mesh.from_json(FILE_I1)edos = Mesh.from_json(FILE_I2)blocks = []for face in idos.faces(): bottom = idos.face_coordinates(face) top = edos.face_coordinates(face) f =len(bottom) faces = [list(range(f)),list(range(f + f -1, f -1, -1))]for i inrange(f -1): faces.append([i, i + f, i + f +1, i +1]) faces.append([f -1, f + f -1, f, 0]) block = Mesh.from_vertices_and_faces(bottom + top, faces) blocks.append(block)withopen(FILE_O, 'w+')as f: data = [block.to_data()for block in blocks] json.dump(data, f)artist =MeshArtist(None, layer="RV2::Blocks")artist.clear_layer()for block in blocks: artist.mesh = block artist.draw_faces(color=(0, 255, 255), join_faces=True)artist.redraw()
Blocks with flat top surface
The block geometries generated using the intrados and extrados, which are offsets of the initial mesh, contain two main hexagonal faces that are not planar. If the blocks are to be milled using stone blanks, milling both sides of the stone would be not only time intensive, but also result in loss of precision during the flipping of the blocks.
One way to address this problem, would be to make one of the two hexagonal faces planar so that the block is only milled on one side and does not need to be flipped. This technique was used for the Armadillo Vault, where the inner face of the blocks had double curvature, while the top face remained flat.
import osimport jsonfrom compas.datastructures import Meshfrom compas.geometry import intersection_line_planefrom compas_rhino.artists import MeshArtistfrom compas_cloud import Proxyfrom compas_rv2.rhino import ErrorHandlererrorHandler =ErrorHandler(title="Server side Error", showLocalTraceback=False)proxy =Proxy(errorHandler=errorHandler, background=False)# proxy.restart()bestfit = proxy.function('compas.geometry.bestfit_plane_numpy')HERE = os.path.dirname(__file__)FILE_I = os.path.join(HERE, 'blocks.json')FILE_O = os.path.join(HERE, 'blocksflat.json')withopen(FILE_I, 'r')as f: blocks = [Mesh.from_data(data)for data in json.load(f)]for block in blocks: bottom = block.face_vertices(0) top = block.face_vertices(1)[::-1] bottom_points = block.vertices_attributes('xyz', keys=bottom) top_points = block.vertices_attributes('xyz', keys=top) plane =bestfit(top_points) top_new = []for a, b inzip(bottom_points, top_points): b =intersection_line_plane((a, b), plane) top_new.append(b)for vertex, point inzip(top, top_new): block.vertex_attributes(vertex, 'xyz', point)withopen(FILE_O, 'w+')as f: data = [block.to_data()for block in blocks] json.dump(data, f)artist =MeshArtist(None, layer="RV2::BlocksFlat")artist.clear_layer()for block in blocks: artist.mesh = block artist.draw_faces(color=(0, 255, 0), join_faces=True)artist.redraw()
Blocks to origin with flat face on bottom
import osimport jsonfrom compas.geometry import subtract_vectors, cross_vectorsfrom compas.geometry import Frame, Transformationfrom compas.datastructures import Meshfrom compas_rhino.artists import MeshArtistHERE = os.path.dirname(__file__)FILE_I = os.path.join(HERE, 'blocksflat.json')withopen(FILE_I, 'r')as f: blocks = [Mesh.from_data(data)for data in json.load(f)]world = Frame.worldXY()for block in blocks: point = block.face_centroid(1) normal = block.face_normal(1) vertices = block.face_vertices(1) xaxis =subtract_vectors(block.vertex_attributes(vertices[0], 'xyz'), point) yaxis =cross_vectors(xaxis, normal) local =Frame(point, xaxis, yaxis) X = Transformation.from_frame_to_frame(local, world) block.transform(X)artist =MeshArtist(None, layer="RV2::BlocksTransformed")artist.clear_layer()for block in blocks: artist.mesh = block artist.draw_faces(color=(0, 255, 0), join_faces=True)artist.redraw()