def __init__(self, board_layer, identification, board_no_in_layer, board_dimensions, z_value_toppoint, length_dir, width_dir): self.index = identification self.layer = board_layer self.no_in_layer = board_no_in_layer self.dimensions = board_dimensions self.width = self.dimensions[0] self.height = self.dimensions[1] self.length = self.dimensions[2] self.drop_point = Point(0, 0, 0) self.centre_point = Point(0, 0, 0) self.z_drop = z_value_toppoint self.length_direction = length_dir self.width_direction = width_dir self.glue_givers = [] self.glue_receivers = [] self.receiving_neighbours = [] self.giving_neighbours = [] if self.length_direction == 0: self.length_vector = Vector(1, 0, 0) self.width_vector = Vector(0, 1, 0) else: self.length_vector = Vector(0, 1, 0) self.width_vector = Vector(1, 0, 0) self.board_frame = Frame(self.centre_point, self.length_vector, self.width_vector) self.box = Box(self.board_frame, self.length, self.width, self.height)
def get_iso_mesh(distobj, bounds): # for RPC from skimage.measure import marching_cubes_lewiner import numpy as np from compas_vol.primitives import VolBox from compas.geometry import Box bx = bounds[0] by = bounds[1] bz = bounds[2] x, y, z = np.ogrid[bx[0]:bx[1]:bx[2] * 1j, by[0]:by[1]:by[2] * 1j, bz[0]:bz[1]:bz[2] * 1j] #x, y, z = np.ogrid[-30:30:60j, -30:30:60j, -30:30:60j] # spacing: (max-min)/num (or num-1?) sx = (bx[1] - bx[0]) / (bx[2] - 1) sy = (by[1] - by[0]) / (by[2] - 1) sz = (bz[1] - bz[0]) / (bz[2] - 1) b = Box.from_data(distobj['box']) vb = VolBox(b, distobj['radius']) vb.data = distobj dm = vb.get_distance_numpy(x, y, z) verts, faces, norms, vals = marching_cubes_lewiner(dm, 0.0, spacing=(sx, sy, sz)) mesh = get_compas_mesh(verts, faces) #return str(mesh.number_of_vertices()) return str(mesh.to_data())
def test_booleans(): # ============================================================================== # Make a box and a sphere # ============================================================================== box = Box.from_width_height_depth(2, 2, 2) box = Mesh.from_shape(box) box.quads_to_triangles() A = box.to_vertices_and_faces() sphere = Sphere(Point(1, 1, 1), 1) sphere = Mesh.from_shape(sphere, u=30, v=30) sphere.quads_to_triangles() B = sphere.to_vertices_and_faces() # ============================================================================== # Remesh the sphere # ============================================================================== B = remesh(B, 0.3, 10) # ============================================================================== # Compute the boolean mesh # ============================================================================== V, F = boolean_union(A, B) mesh = Mesh.from_vertices_and_faces(V, F)
def board_geometry_setup(): for my_element in self.elements(): my_board = my_element[1] if my_board.layer % 2 == 0: my_frame = self.origin_fr layer_standard_length = self.primary_length else: my_frame = self.sec_fr layer_standard_length = self.secondary_length my_dir1 = normalize_vector(my_frame[1]) my_dir2 = normalize_vector(my_frame[2]) dist = my_board.grid_position if my_board.location == "high": if not my_board.supporter: length_attribute_1 = layer_standard_length - my_board.length / 2 else: length_attribute_1 = layer_standard_length - my_board.width / 2 elif my_board.location == "low": if not my_board.supporter: length_attribute_1 = my_board.length / 2 else: length_attribute_1 = my_board.width / 2 else: length_attribute_1 = layer_standard_length / 2 # position parallel to the boards (if not sup) my_vec1 = scale_vector(my_dir1, length_attribute_1) # position perpendicular to board direction (if not sup) my_vec2 = scale_vector(my_dir2, dist) # height vector my_vec3 = Vector(0, 0, my_board.z_drop - my_board.height / 2) my_centre = self.origin_pt + my_vec1 + my_vec2 + my_vec3 my_board.centre_point = my_centre my_board.drop_point = my_centre + Vector(0, 0, my_board.height / 2) if not my_board.perp: my_board.length_vector = normalize_vector(my_vec1) my_board.width_vector = normalize_vector(my_vec2) else: my_board.length_vector = normalize_vector(my_vec2) my_board.width_vector = normalize_vector(my_vec1) old_centre = my_board.center T = Translation(my_centre - old_centre) self.network.node[my_board.global_count]['x'] = my_centre[0] self.network.node[my_board.global_count]['y'] = my_centre[1] self.network.node[my_board.global_count]['z'] = my_centre[2] my_board.transform(T) my_board.board_frame = Frame(my_board.centre_point, my_board.length_vector, my_board.width_vector) my_board.tool_frame = Frame(my_board.drop_point, my_board.length_vector, my_board.width_vector) my_board.box = Box(my_board.board_frame, my_board.length, my_board.width, my_board.height)
def draw_uncut_mesh(self): """Computes and returns the beam geometry. Returns ------- compas.datastructures.Mesh The beam mesh without joint geoemtry """ box = Box(self.frame, self.length,self.width,self.height) box_mesh = Mesh.from_vertices_and_faces(box.vertices, box.faces) return box_mesh
def obb(self, precision=0.0): """Compute the oriented bounding box of the surface. Parameters ---------- precision : float, optional Returns ------- :class:`~compas.geometry.Box` """ box = Bnd_OBB() brepbndlib_AddOBB(self.occ_shape, box, True, True, True) return Box(Frame.from_occ(box.Position()), box.XHSize(), box.YHSize(), box.ZHSize())
def volume(self): if self.radius == 0: return self.box.volume else: xr = self.box.xsize - 2 * self.radius yr = self.box.ysize - 2 * self.radius zr = self.box.zsize - 2 * self.radius # box without the radius layer inner = xr * yr * zr # sides sides = Box.from_width_height_depth(xr, yr, zr).area * self.radius # cylinder along all edges, base circle x height edges = (self.radius**2 * pi) * (xr + yr + zr) # eight time corner, 1/8th of a sphere = 1 sphere corns = 4. / 3. * pi * self.radius**3 return inner + sides + edges + corns
def box_to_compas(box): """Convert a Rhino box to a COMPAS box. Parameters ---------- box: :class:`Rhino.Geometry.Box` Returns ------- :class:`compas.geometry.Box` """ xsize = box.X.Length ysize = box.Y.Length zsize = box.Z.Length frame = plane_to_compas_frame(box.Plane) frame.point.x += 0.5 * xsize frame.point.y += 0.5 * ysize frame.point.z += 0.5 * zsize return Box(frame, xsize, ysize, zsize)
def from_dimensions(cls, length, width, height): """Construct an element with a box primitive with the given dimensions. Parameters ---------- length : float length of the box. width : float width of the box. height : float height of the box. Returns ------- :class:`Element` New instance of element. """ frame = Frame([0., 0., height / 2], [1, 0, 0], [0, 1, 0]) # center of the box frame box = Box(frame, length, width, height) return cls.from_shape(box, frame)
def aabb(self, precision=0.0, optimal=False): """Compute the axis aligned bounding box of the surface. Parameters ---------- precision : float, optional optimal : bool, optional Returns ------- :class:`~compas.geometry.Box` """ box = Bnd_Box() if optimal: add = BndLib_AddSurface_AddOptimal else: add = BndLib_AddSurface_Add add(GeomAdaptor_Surface(self.occ_surface), precision, box) return Box.from_diagonal( (Point.from_occ(box.CornerMin()), Point.from_occ(box.CornerMax())))
def from_data(cls, data): """Construct a volumetric box from its data representation. Parameters ---------- data : :obj:`dict` The data dictionary. Returns ------- VolBox The constructed box. Examples -------- >>> """ box = Box.from_data(data['box']) vbox = cls(box, data['radius']) return vbox
def __init__(self, board_layer, identification, board_no_in_layer, board_dimensions, length_dir, width_dir, grid_pos, position="centre", sup=False): self.index = identification self.layer = board_layer self.no_in_layer = board_no_in_layer self.dimensions = board_dimensions self.width = self.dimensions[0] self.height = self.dimensions[1] self.length = self.dimensions[2] self.drop_point = Point(0, 0, 0) self.centre_point = Point(0, 0, 0) self.length_direction = length_dir self.width_direction = width_dir self.glue_givers = [] self.glue_receivers = [] self.receiving_neighbours = [] self.giving_neighbours = [] self.grid_position = grid_pos self.location = position self.supporter = sup if self.length_direction == 0: self.length_vector = Vector(1, 0, 0) self.width_vector = Vector(0, 1, 0) else: self.length_vector = Vector(0, 1, 0) self.width_vector = Vector(1, 0, 0) self.board_frame = Frame(self.centre_point, self.length_vector, self.width_vector) self.box = Box(self.board_frame, self.length, self.width, self.height)
def __init__(self, board_layer, identification, board_no_in_layer, board_dimensions, z_value_toppoint): self.index = identification self.layer = board_layer self.no_in_layer = board_no_in_layer self.dimensions = board_dimensions self.width = self.dimensions[0] self.height = self.dimensions[1] self.length = self.dimensions[2] self.drop_point = Point(0, 0, 0) self.centre_point = Point(0, 0, 0) self.z_drop = z_value_toppoint if primary_direction == 0: self.primary_vector = (1, 0, 0) self.secondary_vector = (0, 1, 0) else: self.primary_vector = (0, 1, 0) self.secondary_vector = (1, 0, 0) self.board_frame = Frame(self.centre_point, self.primary_vector, self.secondary_vector) self.box = Box(self.board_frame, self.length, self.width, self.height)
def update_joint_mesh(self, BeamRef): """Compute the negative mesh volume of the joint. Returns ------- object A compas.Mesh Note ---- The self.mesh is updated with the new mesh """ TOLEARNCE = 10.0 # Get face_frame from Beam (the parent Beam) face_frame = BeamRef.face_frame(self.face_id) box_frame_origin = face_frame.represent_point_in_global_coordinates([ (self.distance - 50), TOLEARNCE * -1.0, TOLEARNCE * -1.0 ]) box_frame = Frame(box_frame_origin, face_frame.xaxis, face_frame.yaxis) # Compute 3 Box dimensions box_x = self.length box_y = self.width + TOLEARNCE box_z = self.height + 2 * TOLEARNCE # Draw Boolean Box boolean_box = Box(box_frame, box_x, box_y, box_z) boolean_box_mesh = Mesh.from_vertices_and_faces( boolean_box.vertices, boolean_box.faces) # Draw boolean box and assign to self.mesh self.mesh = boolean_box_mesh return self.mesh
from compas.geometry import bounding_box from compas.datastructures import Mesh from compas_view2.app import App from compas_cgal.booleans import boolean_union from compas_cgal.booleans import boolean_difference from compas_cgal.booleans import boolean_intersection from compas_cgal.meshing import remesh # ============================================================================== # Make a box and a sphere # ============================================================================== box = Box.from_width_height_depth(2, 2, 2) box = Mesh.from_shape(box) box.quads_to_triangles() A = box.to_vertices_and_faces() sphere = Sphere(Point(1, 1, 1), 1) sphere = Mesh.from_shape(sphere, u=30, v=30) sphere.quads_to_triangles() B = sphere.to_vertices_and_faces() bbox = bounding_box(box.vertices_attributes('xyz') + sphere.vertices_attributes('xyz')) bbox = Box.from_bounding_box(bbox) width = bbox.xsize
from math import radians from compas.geometry import Pointcloud, Box from compas.geometry import Rotation from compas.geometry import oriented_bounding_box_numpy from compas_view2.app import App cloud = Pointcloud.from_bounds(10, 5, 3, 100) Rz = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], radians(60)) Ry = Rotation.from_axis_and_angle([0.0, 1.0, 0.0], radians(20)) Rx = Rotation.from_axis_and_angle([1.0, 0.0, 0.0], radians(10)) cloud.transform(Rz * Ry * Rx) bbox = oriented_bounding_box_numpy(cloud) box = Box.from_bounding_box(bbox) viewer = App() viewer.add(cloud) viewer.add(box, show_faces=False, linecolor=(1, 0, 0), linewidth=3) viewer.run()
def test_json_shape(): before = Box(Frame(Point(0, 0, 0), Vector(1, 0, 0), Vector(0, 1, 0)), 1, 1, 1) after = compas.json_loads(compas.json_dumps(before)) assert before.dtype == after.dtype assert all(a == b for a, b in zip(before.vertices, after.vertices))
def box_update(self): self.board_frame = Frame(self.centre_point, self.length_vector, self.width_vector) self.box = Box(self.board_frame, self.length, self.width, self.height)
def box_update(elmnt): elmnt.board_frame = Frame(elmnt.centre_point, elmnt.length_vector, elmnt.width_vector) elmnt.box = Box(elmnt.board_frame, elmnt.length, elmnt.width, elmnt.height) return elmnt.board_frame, elmnt.box
# 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)
from compas.geometry import Plane from compas.geometry import centroid_points from compas.datastructures import Mesh from compas.datastructures import mesh_quads_to_triangles from compas.datastructures import mesh_subdivide_quad from compas_viewers.multimeshviewer import MultiMeshViewer from compas_viewers.multimeshviewer.model import MeshObject import compas_libigl as igl origin = Point(0.0, 0.0, 0.0) cube = Box.from_width_height_depth(1.0, 1.0, 1.0) sphere = Sphere(origin, 0.95 * sqrt(0.5 ** 2 + 0.5 ** 2)) xcyl = Cylinder(Circle(Plane(origin, Vector(1.0, 0.0, 0.0)), 0.35), 2.0) ycyl = Cylinder(Circle(Plane(origin, Vector(0.0, 1.0, 0.0)), 0.35), 2.0) zcyl = Cylinder(Circle(Plane(origin, Vector(0.0, 0.0, 1.0)), 0.35), 2.0) a = Mesh.from_vertices_and_faces(cube.vertices, cube.faces) a = mesh_subdivide_quad(a, k=3) b = Mesh.from_vertices_and_faces(* sphere.to_vertices_and_faces(u=30, v=30)) c = Mesh.from_vertices_and_faces(* xcyl.to_vertices_and_faces(u=30)) d = Mesh.from_vertices_and_faces(* ycyl.to_vertices_and_faces(u=30)) e = Mesh.from_vertices_and_faces(* zcyl.to_vertices_and_faces(u=30)) mesh_quads_to_triangles(a) mesh_quads_to_triangles(b)
import rhinoscriptsyntax as rs import Rhino.Geometry as rg from compas_vol.primitives import VolSphere, VolBox from compas_vol.combinations import Union,Subtraction from compas.geometry import Sphere, Box, Frame from compas.rpc import Proxy s = VolSphere(Sphere((0, 0, 0), 6)) b = VolBox(Box(Frame.worldXY(), 10, 10, 10), 1.5) u = Union(s, b) t = Subtraction(b, s) p = Proxy('compas_vol.utilities') #p.stop_server() #p = Proxy('compas_vol.utilities') bounds = ((-25,25,100), (-25,25,100), (-25,25,100)) vs,fs = p.get_vfs_from_tree(str(t), bounds, 1.0) mesh = rg.Mesh() for v1, v2, v3 in vs: mesh.Vertices.Add(v1, v2, v3) for f in fs: if len(set(f))>2: mesh.Faces.AddFace(f[0], f[1], f[2]) mesh.Compact() mesh.Normals.ComputeNormals() a = mesh b = [rs.CreatePoint(v1,v2,v3) for v1, v2, v3 in vs]
def cutting_plane(mesh, ry=10, rz=-50): plane = Plane(mesh.centroid(), Vector(1, 0, 0)) Ry = Rotation.from_axis_and_angle(Vector(0, 1, 0), radians(ry), plane.point) Rz = Rotation.from_axis_and_angle(Vector(0, 0, 1), radians(rz), plane.point) plane.transform(Rz * Ry) return plane # ============================================================================== # Input # ============================================================================== frame = Frame.worldXY() box = Box(frame, 10, 3, 5) mesh = Mesh.from_shape(box) # ============================================================================== # Parts # ============================================================================== red = [] blue = [] plane = cutting_plane(mesh, ry=0, rz=0) A, B = mesh.cut(plane) for _ in range(0, 7): plane = cutting_plane(A, ry=-40, rz=0)
from compas.geometry import Box from compas.geometry import Translation from compas.datastructures import Mesh from compas.datastructures import mesh_quads_to_triangles from compas.datastructures import mesh_subdivide_quad from compas_viewers.multimeshviewer import MultiMeshViewer from compas_viewers.multimeshviewer import MeshObject import compas_libigl as igl # ============================================================================== # Input Geometry # ============================================================================== # create a box mesh around the center of the world box = Box.from_width_height_depth(5.0, 3.0, 1.0) a = Mesh.from_shape(box) mesh_quads_to_triangles(a) # create a box mesh around the center of the world box = Box.from_width_height_depth(1.0, 5.0, 3.0) b = Mesh.from_shape(box) mesh_quads_to_triangles(b) # ============================================================================== # Booleans # ============================================================================== # convert meshes to data
from compas.geometry import Polyline from compas.datastructures import Mesh from compas.utilities import hex_to_rgb from compas_rhino.artists import PointArtist, PolylineArtist, MeshArtist # @me add restart option to init from compas.rpc import Proxy proxy = Proxy() # ============================================================================== # Make a box and a sphere # ============================================================================== box = Box.from_width_height_depth(2, 2, 2) box = Mesh.from_shape(box) box.quads_to_triangles() A = box.to_vertices_and_faces() sphere = Sphere(Point(1, 1, 1), 1) sphere = Mesh.from_shape(sphere, u=30, v=30) sphere.quads_to_triangles() B = sphere.to_vertices_and_faces() # ============================================================================== # Remesh the sphere # ==============================================================================
import compas_rhino from compas_rhino.artists import BoxArtist, MeshArtist # ============================================================================== # Paths # ============================================================================== HERE = os.path.dirname(__file__) FILE_O = os.path.join(HERE, 'data', 'block.json') # ============================================================================== # Block and Blank # ============================================================================== box = Box.from_width_height_depth(200, 200, 200) block = Mesh.from_shape(box) vertex = next( block.vertices_where({ 'x': (float('-inf'), 0), 'y': (0, float('inf')), 'z': (0, float('inf')) })) block.vertex_attribute(vertex, 'z', 120) vertex = next( block.vertices_where({ 'x': (0, float('inf')), 'y': (0, float('inf')), 'z': (0, float('inf'))
return da + self.f * db def get_distance_numpy(self, x, y, z): """ vectorized distance function """ da = self.a.get_distance_numpy(x, y, z) db = self.b.get_distance_numpy(x, y, z) return da + self.f * db if __name__ == "__main__": from compas_vol.primitives import VolSphere, VolBox from compas.geometry import Box, Frame, Point, Sphere s = Sphere(Point(2, 3, 0), 7) b = Box(Frame.worldXY(), 20, 15, 10) vs = VolSphere(s) vb = VolBox(b, 2.5) f = Overlay(vs, vb, 0.2) print(f) for y in range(-15, 15): s = '' for x in range(-30, 30): d = f.get_distance((x * 0.5, y, 0)) if d < 0: s += 'x' else: s += '.' print(s)
# ============================================================================== T = Translation.from_vector(Point(0, 0, 0) - Point(*before.centroid())) S = Scale.from_factors([100, 100, 100]) R = Rotation.from_axis_and_angle([1, 0, 0], radians(90)) before.transform(R * S * T) # ============================================================================== # Remesh # ============================================================================== L = sum(before.edge_length(*edge) for edge in before.edges()) / before.number_of_edges() V, F = trimesh_remesh(before.to_vertices_and_faces(), 3 * L) after = Mesh.from_vertices_and_faces(V, F) # ============================================================================== # Viz # ============================================================================== viewer = App() box = Box.from_bounding_box(before.bounding_box()) dx = 1.5 * box.xsize viewer.add(before) viewer.add(after.transformed(Translation.from_vector([dx, 0, 0]))) viewer.run()
surface = RhinoSurface.from_guid(guid) block = surface.to_compas() block.name = str(guid) bottom = sorted( block.faces(), key=lambda face: dot_vectors(block.face_normal(face), [0, 0, -1]))[-1] plane = block.face_centroid(bottom), block.face_normal(bottom) frame = Frame.from_plane(plane) T = Transformation.from_frame_to_frame(frame, world) block.transform(T) blank = Box.from_bounding_box(block.bounding_box()) blank.xsize += 25 blank.ysize += 25 blank.zsize += 25 block.attributes['blank'] = blank block.attributes['bottom'] = bottom blocks.append(block) # ============================================================================== # Export # ============================================================================== with open(FILE, 'w') as f: json.dump(blocks, f, cls=DataEncoder)
import time from compas.datastructures import Mesh from compas.geometry import Box, Translation from compas_fab.backends import RosClient from compas_fab.robots import CollisionMesh from compas_fab.robots import PlanningScene with RosClient('localhost') as client: robot = client.load_robot() scene = PlanningScene(robot) brick = Box.from_width_height_depth(0.016, 0.012, 0.031) brick.transform(Translation.from_vector([0, 0, brick.zsize / 2.])) for i in range(5): mesh = Mesh.from_shape(brick) cm = CollisionMesh(mesh, 'brick_wall') cm.frame.point.y += 0.5 cm.frame.point.z += brick.zsize * i scene.append_collision_mesh(cm) # sleep a bit before terminating the client time.sleep(1)