from compas.geometry import Pointcloud, Polygon, Line from compas.geometry import Translation from compas.geometry import intersection_line_segment_xy from compas.utilities import grouper, pairwise from compas_plotters import GeometryPlotter pcl = Pointcloud.from_bounds(10, 5, 0, 50) polygon = Polygon.from_sides_and_radius_xy(5, 1.0) polygon.transform(Translation.from_vector([5, 2.5, 0])) plotter = GeometryPlotter(show_axes=True, figsize=(12, 7.5)) plotter.add(polygon, edgecolor=(0, 0, 1), facecolor=(0.7, 0.7, 1.0)) lines = [] for a, b in grouper(pcl.points, 2): line = Line(a, b) lines.append(line) plotter.add(line, color=(0.5, 0.5, 0.5)) plotter.redraw() plotter.zoom_extents() plotter.show()
from compas.datastructures import Mesh from compas.geometry import Line, Plane, Frame, Box box = Box(Frame.worldXY(), 3, 1, 2) mesh = Mesh.from_shape(box) line = Line(*box.diagonal) N = 9 slices = [] a = line.start for i in range(1, N + 1): b = a + line.direction * i * 0.1 * line.length plane = Plane(b, line.direction) mesh, B = mesh.slice_plane(plane) slices.append(B) slices.append(mesh)
def generate_raft(slicer, raft_offset=10, distance_between_paths=10, direction="xy_diagonal", raft_layers=1, raft_layer_height=None): """Creates a raft. Parameters ---------- slicer: :class:`compas_slicer.slicers.BaseSlicer` An instance of one of the compas_slicer.slicers.BaseSlicer classes. raft_offset: float Distance (in mm) that the raft should be offsetted from the first layer. Defaults to 10mm distance_between_paths: float Distance (in mm) between the printed lines of the raft. Defaults to 10mm direction: str x_axis: Create a raft aligned with the x_axis y_axis: Create a raft aligned with the y_axis xy_diagonal: Create a raft int the diagonal direction in the xy_plane raft_layers: int Number of raft layers to add. Defaults to 1 raft_layer_height: float Layer height of the raft layers. Defaults to same value as used in the slicer. """ # check if a raft_layer_height is specified, if not, use the slicer.layer_height value if not raft_layer_height: raft_layer_height = slicer.layer_height logger.info("Generating raft") # find if slicer has vertical or horizontal layers, and select which paths are to be offset. if isinstance(slicer.layers[0], compas_slicer.geometry.VerticalLayer): # Vertical layers # then find all paths that lie on the print platform and make them brim. paths_to_offset, _ = slicer.find_vertical_layers_with_first_path_on_base() else: # Horizontal layers # then replace the first layer with a raft layer. paths_to_offset = slicer.layers[0].paths # get flat lists of points in bottom layer all_pts = [] for path in paths_to_offset: for pt in path.points: all_pts.append(pt) # get xy bounding box of bottom layer and create offset bb_xy = bounding_box_xy(all_pts) bb_xy_offset = offset_polygon(bb_xy, -raft_offset) # bring points in the xy_offset to the correct height for pt in bb_xy_offset: pt[2] = slicer.layers[0].paths[0].points[0][2] # calculate x range, y range, and number of steps x_range = abs(bb_xy_offset[0][0] - bb_xy_offset[1][0]) y_range = abs(bb_xy_offset[0][1] - bb_xy_offset[3][1]) # get maximum values of the bounding box bb_max_x_right = bb_xy_offset[1][0] bb_max_y_top = bb_xy_offset[3][1] # get point in bottom left corner as raft start point raft_start_pt = Point(bb_xy_offset[0][0], bb_xy_offset[0][1], bb_xy_offset[0][2]) # create starting line for diagonal direction if direction == "xy_diagonal": c = math.sqrt(2*(distance_between_paths**2)) pt1 = Point(raft_start_pt[0] + c, raft_start_pt[1], raft_start_pt[2]) pt2 = Point(pt1[0] - y_range, pt1[1] + y_range, pt1[2]) line = Line(pt1, pt2) # move all points in the slicer up so that raft layers can be inserted for i, layer in enumerate(slicer.layers): for j, path in enumerate(layer.paths): for k, pt in enumerate(path.points): slicer.layers[i].paths[j].points[k] = Point(pt[0], pt[1], pt[2] + (raft_layers)*raft_layer_height) for i in range(raft_layers): iter = 0 raft_points = [] # create raft points depending on the chosen direction while iter < 9999: # to avoid infinite while loop in case something is not correct # =============== # VERTICAL RAFT # =============== if direction == "y_axis": raft_pt1 = Point(raft_start_pt[0] + iter*distance_between_paths, raft_start_pt[1], raft_start_pt[2] + i*raft_layer_height) raft_pt2 = Point(raft_start_pt[0] + iter*distance_between_paths, raft_start_pt[1] + y_range, raft_start_pt[2] + i*raft_layer_height) if raft_pt2[0] > bb_max_x_right or raft_pt1[0] > bb_max_x_right: break # =============== # HORIZONTAL RAFT # =============== elif direction == "x_axis": raft_pt1 = Point(raft_start_pt[0], raft_start_pt[1] + iter*distance_between_paths, raft_start_pt[2] + i*raft_layer_height) raft_pt2 = Point(raft_start_pt[0] + x_range, raft_start_pt[1] + iter*distance_between_paths, raft_start_pt[2] + i*raft_layer_height) if raft_pt2[1] > bb_max_y_top or raft_pt1[1] > bb_max_y_top: break # =============== # DIAGONAL RAFT # =============== elif direction == "xy_diagonal": # create offset of the initial diagonal line offset_l = offset_line(line, iter*distance_between_paths, Vector(0, 0, -1)) # get intersections for the initial diagonal line with the left and bottom of the bb int_left = intersection_line_line(offset_l, [bb_xy_offset[0], bb_xy_offset[3]]) int_bottom = intersection_line_line(offset_l, [bb_xy_offset[0], bb_xy_offset[1]]) # get the points at the intersections raft_pt1 = Point(int_left[0][0], int_left[0][1], int_left[0][2] + i*raft_layer_height) raft_pt2 = Point(int_bottom[0][0], int_bottom[0][1], int_bottom[0][2] + i*raft_layer_height) # if the intersection goes beyond the height of the left side of the bounding box: if int_left[0][1] > bb_max_y_top: # create intersection with the top side int_top = intersection_line_line(offset_l, [bb_xy_offset[3], bb_xy_offset[2]]) raft_pt1 = Point(int_top[0][0], int_top[0][1], int_top[0][2] + i*raft_layer_height) # if intersection goes beyond the length of the top side, break if raft_pt1[0] > bb_max_x_right: break # if the intersection goes beyond the length of the bottom side of the bounding box: if int_bottom[0][0] > bb_max_x_right: # create intersection with the right side int_right = intersection_line_line(offset_l, [bb_xy_offset[1], bb_xy_offset[2]]) raft_pt2 = Point(int_right[0][0], int_right[0][1], int_right[0][2] + i*raft_layer_height) # if intersection goes beyond the height of the right side, break if raft_pt2[1] > bb_xy_offset[2][1]: break # append to list alternating if iter % 2 == 0: raft_points.extend((raft_pt1, raft_pt2)) else: raft_points.extend((raft_pt2, raft_pt1)) iter += 1 # create raft layer raft_layer = Layer([Path(raft_points, is_closed=False)]) raft_layer.is_raft = True # insert raft layer in the correct position into the slicer slicer.layers.insert(i, raft_layer)
compas_rhino.clear() # draw movement boundaries left points = [[0, 0, 0], [0, 0, HEIGHT], [0, TABLE, HEIGHT], [0, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::HotWire::Left", color=(255, 0, 0)) artist.draw(show_edges=True, show_face=False) # draw movement boundaries right points = [[WIRE, 0, 0], [WIRE, 0, HEIGHT], [WIRE, TABLE, HEIGHT], [WIRE, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::Hotwire::Right", color=(0, 255, 0)) artist.draw(show_edges=True, show_face=False) # draw the wire line = Line([0, 0, 0], [WIRE, 0, 0]) artist = LineArtist(line, color=(255, 255, 255), layer="ITA20::HotWire::Wire") artist.draw()
def test_is_line_line_colinear(): assert is_line_line_colinear(Line(Point(0, 0, 0), Point(1, 1, 1)), Line(Point(3, 3, 3), Point(2, 2, 2))) is True assert is_line_line_colinear(Line(Point(0, 0, 0), Point(1, 1, 1)), Line(Point(4, 1, 0), Point(5, 2, 1))) is False
def diagonal(self): vertices = self.vertices return Line(vertices[0], vertices[-2])
from math import pi from compas.geometry import Point from compas.geometry import Vector from compas.geometry import Plane from compas.geometry import Line from compas.geometry import Polygon from compas.geometry import matrix_from_axis_and_angle M = matrix_from_axis_and_angle([0, 0, 1], pi / 2) point = Point(0.0, 0.0, 0.0) normal = Vector(0.0, 0.0, 1.0) plane = Plane(point, normal) line = Line([0.0, 0.0, 0.0], [1.0, 0.0, 0.0]) triangle = Polygon([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0]]) polygon = Polygon([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.0]]) p = Point(1.0, 1.0, 1.0) p.transform(M) print(*p) print(repr(p)) print(p.distance_to_point(point)) print(p.distance_to_line(line)) print(p.distance_to_plane(plane))
axis = joint.axis.transformed(transformations[joint.name]) axis.name = joint.name axes.append(axis) # Visualization for frame in frames: artist = FrameArtist(frame, scale=0.3, layer="Frames::{}".format(frame.name)) artist.clear_layer() artist.draw() for a, b in pairwise(frames): line = Line(a.point, b.point) artist = LineArtist(line, layer="Links::{}".format(a.name)) artist.draw() tpl = Cylinder(Circle(Plane(Point(0, 0, 0), Vector(0, 0, 1)), 0.05), 0.2) for frame, axis in zip(frames, axes): point = frame.point normal = Vector(axis.x, axis.y, axis.z) plane = Plane(point, normal) frame = Frame.from_plane(plane) X = Transformation.from_frame(frame) cylinder = tpl.transformed(X) artist = CylinderArtist(cylinder, layer="Axes::{}".format(axis.name)) artist.clear_layer() artist.draw()
viewer = ObjectViewer() viewer.add(mesh, settings={ 'color': '#cccccc', 'opacity': 0.7, 'vertices.on': False }) for i in range(len(intersections) - 132): p = intersections[i] r = reflections[i] n = normals[i] c = centers[i] viewer.add(Line(base, p), settings={ 'edges.color': '#ff0000', 'edges.width': 2 }) viewer.add(Line(p, r), settings={ 'edges.color': '#0000ff', 'edges.width': 2 }) viewer.add(Line(p, n), settings={'edges.width': 2}) viewer.add(Point(*c), settings={ 'vertices.size': 10, 'vertices.on': True,
# Visualisation # ============================================================================== Object.register(Block, MeshObject) viewer = App() for node in assembly.nodes(): point = Point(*assembly.node_attributes(node, 'xyz')) block = assembly.node_attribute(node, 'block') viewer.add(point, size=10, color=(0, 0, 0)) viewer.add(block, show_faces=assembly.node_attribute(node, 'is_support'), show_edges=True, facecolor=(1.0, 0, 0)) for edge in assembly.edges(): line = Line(*assembly.edge_coordinates(*edge)) interface = assembly.edge_attribute(edge, 'interface') viewer.add(line, linewidth=3, color=(0, 0.7, 0)) viewer.add(Mesh.from_polygons([interface.points]), show_edges=False, facecolor=(0.5, 0.5, 1.0), linecolor=(0, 0, 1.0)) viewer.show()
model.optimize_mesh(niter=10) # ============================================================================== # COMPAS mesh # ============================================================================== mesh = model.mesh_to_compas() # ============================================================================== # Visualization with viewer # ============================================================================== viewer = App(width=1600, height=900) viewer.view.camera.rx = -75 viewer.view.camera.tx = -1 viewer.view.camera.ty = 0 viewer.add(mesh) for u, v in mesh.edges(): a = mesh.vertex_coordinates(u) b = mesh.vertex_coordinates(v) if mesh.halfedge[u][v] is None: viewer.add(Line(a, b), linewidth=10, color=(1, 0, 0)) elif mesh.halfedge[v][u] is None: viewer.add(Line(a, b), linewidth=10, color=(1, 0, 0)) viewer.run()
if hits: base, vector = ray index = hits[0][0] distance = hits[0][3] face = index_face[index] point = base + vector * distance intersections.append(point) # ============================================================================== # Visualisation # ============================================================================== viewer = ObjectViewer() viewer.add(mesh, settings={ 'color': '#cccccc', 'opacity': 0.5, 'edges.on': False }) for intersection in intersections: viewer.add(Line(base, intersection), settings={ 'edges.color': '#ff0000', 'edges.width': 3 }) viewer.update() viewer.show()
points = [[0, 0, 0], [0, 0, HEIGHT], [0, TABLE, HEIGHT], [0, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::HotWire::Left", color=(255, 0, 0)) artist.draw(show_edges=True, show_face=False) points = [[WIRE, 0, 0], [WIRE, 0, HEIGHT], [WIRE, TABLE, HEIGHT], [WIRE, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::HotWire::Right", color=(0, 255, 0)) artist.draw(show_edges=True, show_face=False) line = Line([0, 0, 0], [WIRE, 0, 0]) artist = LineArtist(line, color=(255, 255, 255), layer="ITA20::HotWire::Wire") artist.draw() # blank and block artist = MeshArtist(block, layer="ITA20::HotWire::Block") artist.draw_faces(color={left: (255, 0, 0), right: (0, 255, 0)}) artist = BoxArtist(blank, layer="ITA20::HotWire::Blank") artist.draw(show_edges=True, show_faces=False) # movement paths artist = PolylineArtist(left_poly, color=(255, 0, 0),
geometry[0][2]) end = Rhino.Geometry.Point3d(geometry[1][0], geometry[1][1], geometry[1][2]) geometry = Rhino.Geometry.Line(start, end) line = cls() line.geometry = geometry return line def to_compas(self): return Line(self.start, self.end) # ============================================================================== # Main # ============================================================================== if __name__ == '__main__': line = RhinoLine.from_geometry(Line([0.0, 0.0, 0.0], [1.0, 0.0, 0.0])) print(line.guid) print(line.object) print(line.geometry) print(line.type) print(line.name) print(line.start) print(line.end) print(line.to_compas())
compas.json_dump(blocks, FILE) # ============================================================================== # Visualization # ============================================================================== plotter = GeometryPlotter(figsize=(16, 9)) plotter.add(controlpoly, linestyle='dotted', linewidth=0.5, color=(0.5, 0.5, 0.5)) for point in controlpoints: plotter.add(point, edgecolor=(1.0, 0.0, 0.0)) plotter.add(poly0, color=(0.7, 0.7, 0.7), linewidth=0.5) plotter.add(poly1, color=(0.7, 0.7, 0.7), linewidth=0.5) plotter.add(poly2, color=(0.7, 0.7, 0.7), linewidth=0.5) for frame in frames: point = frame.point xaxis = Line(point, point + frame.xaxis * 0.1) yaxis = Line(point, point + frame.yaxis * 0.1) plotter.add(point, edgecolor=(0, 0, 1.0), size=2) plotter.add(xaxis, color=(1.0, 0, 0), draw_as_segment=True) plotter.add(yaxis, color=(0, 1.0, 0), draw_as_segment=True) for block in polygons: plotter.add(block) plotter.zoom_extents() plotter.show()
def to_compas(self): return Line(self.start, self.end)
# Viz # ============================================================================== viewer = App() nodes = [] blocks = [] interfaces = [] interactions = [] for node in assembly.nodes(): nodes.append(Point(* assembly.node_coordinates(node))) blocks.append(assembly.node_attribute(node, 'block')) for edge in assembly.edges(): interface = assembly.edge_attribute(edge, 'interface') polygon = Polygon(interface.points) interfaces.append(Mesh.from_polygons([polygon])) for edge in assembly.edges(): a = Point(* assembly.node_coordinates(edge[0])) b = Point(* assembly.node_coordinates(edge[1])) interactions.append(Line(a, b)) viewer.add(Collection(nodes)) viewer.add(Collection(blocks), show_faces=False, show_edges=True) viewer.add(Collection(interfaces), show_edges=False, color=(0, 0, 1), opacity=0.5) viewer.add(Collection(interactions)) viewer.run()
# ============================================================================== # Main # ============================================================================== if __name__ == '__main__': from compas.geometry import Point from compas.geometry import Line from compas.geometry import Frame from compas.datastructures import Mesh scene = Scene() a = Point(1.0, 1.0, 0.0) b = Point(5.0, 5.0, 0.0) ab = Line(a, b) world = Frame.worldXY() mesh = Mesh.from_polyhedron(6) scene.add(a, name="A", color=(0, 0, 0), layer="A") scene.add(b, name="B", color=(255, 255, 255), layer="B") scene.add(ab, name="AB", color=(128, 128, 128), layer="AB") scene.add(world, name="World", layer="World") scene.add(mesh, name="Cube", layer="Cube") scene.update()
# Intersections # ============================================================================== index_face = {index: face for index, face in enumerate(mesh.faces())} hits_per_ray = igl.intersection_rays_mesh(rays, mesh.to_vertices_and_faces()) intersections = [] for ray, hits in zip(rays, hits_per_ray): if hits: base, vector = ray index = hits[0][0] distance = hits[0][3] face = index_face[index] point = base + vector * distance intersections.append(point) # ============================================================================== # Visualisation # ============================================================================== viewer = ObjectViewer() viewer.add(mesh, settings={'color': '#cccccc', 'opacity': 0.5, 'edges.on': False}) for intersection in intersections: viewer.add(Line(base, intersection), settings={'edges.color': '#ff0000', 'edges.width': 3}) viewer.update() viewer.show()
def data(self, data): self.line = Line.from_data(data['line']) self.radius = data['radius']
# Main # ============================================================================== if __name__ == '__main__': from math import radians from compas.geometry import Point from compas.geometry import Vector from compas.geometry import Line from compas.geometry import Rotation from compas_plotters import GeometryPlotter plotter = GeometryPlotter() a = Point(3.0, 2.0) b = Point(3.0, 5.0) line = Line(a, b) R = Rotation.from_axis_and_angle(Vector(0.0, 0.0, 1.0), radians(10), point=line.end) plotter.add(line, draw_points=True, draw_as_segment=False) plotter.redraw(pause=1.0) for i in range(9): line.transform(R) plotter.redraw(pause=0.01) plotter.show()