def __init__(self): points = [ Point(0.000, 0.000, 0.375), Point(0.000, 0.020, 0.775), Point(0.450, 0.020, 0.775), Point(0.520, 0.020, 0.775) ] super(Staubli_TX260LKinematics, self).__init__(points)
def __init__(self): points = [ Point(0.175, 0.000, 0.495), Point(0.175, 0.000, 1.590), Point(1.446, 0.000, 1.765), Point(1.581, 0.000, 1.765) ] super(ABB_IRB4600_40_255Kinematics, self).__init__(points)
def get_distance(self, point): """ single point distance function """ if not isinstance(point, Point): point = Point(*point) p = closest_point_on_segment(point, self.segment) return point.distance_to_point(p) - self.radius
def __init__(self, o, e=0.01): self.o = o self.e = e self.ex = Point(e, 0, 0) self.ey = Point(0, e, 0) self.ez = Point(0, 0, e) self.k0 = Vector(1, -1, -1) self.k1 = Vector(-1, -1, 1) self.k2 = Vector(-1, 1, -1) self.k3 = Vector(1, 1, 1)
def select_closest_pt_from_list(Point, pt_list): closest_point = None distances = [Point.distance_to_point(pt) for pt in pt_list] distances.sort() min_dis = distances[0] for pt in pt_list: distance = Point.distance_to_point(pt) if distance == min_dis: closest_point = pt return closest_point, min_dis
def to_global_geometry(self, world_frame=Frame.worldXY()): geometry = self.to_local_geometry_xy() transformed_geometry = [] T = Transformation.from_frame_to_frame(self.frame, world_frame) for part in geometry: transformed_part = [] for point in part: p_point = Point(point['x'], point['y'], point['z']) transformed_part.append(p_point.transformed(T)) transformed_geometry.append(transformed_part) return transformed_geometry
def reorder_vertical_layers(slicer, align_with): """Re-orders the vertical layers in a specific way Parameters ---------- slicer: :class:`compas_slicer.slicers.BaseSlicer` An instance of one of the compas_slicer.slicers classes. align_with: str or :class:`compas.geometry.Point` x_axis = reorders the vertical layers starting from the positive x-axis y_axis = reorders the vertical layers starting from the positive y-axis Point(x,y,z) = reorders the vertical layers starting from a given Point """ if align_with == "x_axis": align_pt = Point(2**32, 0, 0) elif align_with == "y_axis": align_pt = Point(0, 2**32, 0) elif isinstance(align_with, Point): align_pt = align_with else: raise NameError("Unknown align_with : " + str(align_with)) logger.info( "Re-ordering vertical layers to start with the vertical layer closest to: %s" % align_with) for layer in slicer.layers: assert layer.min_max_z_height[0] is not None and layer.min_max_z_height[1] is not None, \ "To use the 'reorder_vertical_layers function you need first to calculate the layers' z_bounds. To do " \ "that use the function 'Layer.calculate_z_bounds()'" # group vertical layers based on the min_max_z_height grouped_iter = itertools.groupby(slicer.layers, lambda x: x.min_max_z_height) grouped_layer_list = [list(group) for _key, group in grouped_iter] reordered_layers = [] for grouped_layers in grouped_layer_list: distances = [] for vert_layer in grouped_layers: # recreate head_centroid_pt as compas.Point head_centroid_pt = Point(vert_layer.head_centroid[0], vert_layer.head_centroid[1], vert_layer.head_centroid[2]) # measure distance distances.append(distance_point_point(head_centroid_pt, align_pt)) # sort lists based on closest distance to align pt grouped_new = [x for _, x in sorted(zip(distances, grouped_layers))] reordered_layers.append(grouped_new) # flatten list slicer.layers = [item for sublist in reordered_layers for item in sublist]
def get_gradient(self, point): """ central differences, with tetrahedron technique. 30-40% faster regular `get_gradient_regular`. """ d0 = self.o.get_distance(Point(point.x + self.e, point.y - self.e, point.z - self.e)) d1 = self.o.get_distance(Point(point.x - self.e, point.y - self.e, point.z + self.e)) d2 = self.o.get_distance(Point(point.x - self.e, point.y + self.e, point.z - self.e)) d3 = self.o.get_distance(Point(point.x + self.e, point.y + self.e, point.z + self.e)) v = Vector(d0 - d1 - d2 + d3, -d0 - d1 + d2 + d3, -d0 + d1 - d2 + d3) v.unitize() return v
def get_distance(self, point): """ single point distance function """ if not isinstance(point, Point): point = Point(*point) point.transform(self.inversetransform) dxy = length_vector_xy(point) # distance_point_point_xy(self.torus.center, point) d2 = sqrt((dxy - self.torus.radius_axis)**2 + point.z**2) return d2 - self.torus.radius_pipe
def to_global_geometry(self, world_frame=Frame.worldXY()): geometry = self.to_local_geometry_xy() transformed_geometry = [] gusset_local_frame = Frame([0, 0, 0], [1, 0, 0], [0, 1, 0]) T1 = Transformation.from_frame_to_frame(gusset_local_frame, self.frame) T2 = Transformation.from_frame_to_frame(self.frame, world_frame) transformed_part = [] # default for part in geometry: transformed_part = [] for point in part: p_point = Point(point['x'], point['y'], point['z']) transformed_part.append(p_point.transformed(T1)) transformed_geometry.append(transformed_part) return transformed_geometry
def convert_data_pts_list_to_compas_pts(pt_data_list, ROUND=False): """ pt_coordinates looks like this; pt_coordinates = [x, y, z] """ compasPt_list = [] for pt_data in pt_data_list: if ROUND: compasPt = Point(round(pt_data[0], 3), round(pt_data[1], 3), round(pt_data[2], 3)) else: compasPt = Point(pt_data[0], pt_data[1], pt_data[2]) compasPt_list.append(compasPt) return compasPt_list
def get_distance(self, point): """ single point distance function """ if not isinstance(point, Point): point = Point(*point) point.transform(self.inversetransform) dxy = length_vector_xy( point) # distance_point_point_xy(self.cylinder.center, point) d = dxy - self.cylinder.radius d = max(d, abs(point.z) - self.cylinder.height / 2.0) return d
def get_distance(self, point): if not isinstance(point, Point): point = Point(*point) point.transform(self.inversetransform) x, y, z = point # Tetrahedron if self.type == 0: return (max(abs(x + y) - z, abs(x - y) + z) - self.radius) / self.sqrt3 # Octahedron elif self.type == 1: s = abs(x) + abs(y) + abs(z) return (s - self.radius) * self.tan30 # Dodecahedron elif self.type == 2: v = Vector((1+sqrt(5))/2, 1, 0) v.unitize() px = abs(x / self.radius) py = abs(y / self.radius) pz = abs(z / self.radius) p = Vector(px, py, pz) a = p.dot(v) b = p.dot(Vector(v.z, v.x, v.y)) c = p.dot(Vector(v.y, v.z, v.x)) q = (max(max(a, b), c) - v.x) * self.radius return q # Icosahedron elif self.type == 3: r = self.radius * 0.8506507174597755 v = Vector((sqrt(5) + 3)/2, 1, 0) v.unitize() w = sqrt(3)/3 px = abs(x / r) py = abs(y / r) pz = abs(z / r) p = Vector(px, py, pz) a = p.dot(v) b = p.dot(Vector(v.z, v.x, v.y)) c = p.dot(Vector(v.y, v.z, v.x)) d = p.dot([w,w,w]) - v.x q = max(max(max(a, b), c) - v.x, d) * r return q else: return 0
def face_subdiv_frame(self, fkey, rel_pos=None, move_z=None, **kwattr): if rel_pos == 1 or rel_pos == [1, 1, 1]: return self.face_subdiv_pyramid(fkey, move_z=move_z, **kwattr) face_center_pt = Point(*self.face_center(fkey)) face_normal = Vector(*self.face_normal(fkey)) face_coordinates = self.face_coordinates(fkey) face_halfedges = self.face_halfedges(fkey) self.delete_face(fkey) if move_z is None: move_z = cycle(to_list(0)) if not isinstance(move_z, cycle): move_z = cycle(to_list(move_z)) if rel_pos is None: rel_pos = cycle(to_list(0.5)) if not isinstance(rel_pos, cycle): rel_pos = cycle(to_list(rel_pos)) new_vkeys = [] for x, y, z in face_coordinates: pt = Point(x, y, z) factor = next(rel_pos) v = face_center_pt - pt pt += v * factor if move_z: z_factor = next(move_z) pt += face_normal * z_factor new_vkeys.append(self.add_vertex(x=pt.x, y=pt.y, z=pt.z)) new_fkeys = [] for i, uv in enumerate(face_halfedges): u, v = uv vkeys = [] vkeys.append(u) vkeys.append(v) vkeys.append(new_vkeys[(i + 1) % len(new_vkeys)]) vkeys.append(new_vkeys[i]) new_fkeys.append(self.add_face(vkeys)) # add new center face new_fkeys.append(self.add_face(new_vkeys)) return new_vkeys, new_fkeys
def __init__(self, scene, arrow, **kwargs): super(ArrowObject, self).__init__(scene, arrow, **kwargs) length = np.linalg.norm(arrow.direction) plane = Plane(arrow.point + arrow.direction * 0.7, arrow.direction) circle = Circle(plane, length * 0.15) cone = Cone(circle, length * 0.3) line = Line(Point(*arrow.point), Point(*(arrow.point + arrow.direction * 0.7))) self.view = ArrowView(arrow, ConeObject(None, cone, 3), LineObject(None, line))
def create_overhang_texture(slicer, overhang_distance): """Creates a cool overhang texture""" print("Creating cool texture") for i, layer in enumerate(slicer.layers): if i % 10 == 0 and i > 0: # for every 10th layer, except for the brim # print(layer) for j, path in enumerate(layer.paths): # print(path) # create an empty layer in which we can store our modified points new_path = [] for k, pt in enumerate(path.points): # for every second point (only even points) if k % 2 == 0: # get the normal of the point in relation to the mesh normal = get_normal_of_path_on_xy_plane(k, pt, path, mesh=None) # scale the vector by a number to move the point normal_scaled = scale_vector(normal, -overhang_distance) # create a new point by adding the point and the normal vector new_pt = add_vectors(pt, normal_scaled) # recreate the new_pt values as compas_points pt = Point(new_pt[0], new_pt[1], new_pt[2]) # append the points to the new path new_path.append(pt) # replace the current path with the new path that we just created layer.paths[j] = Path(new_path, is_closed=path.is_closed)
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 generate_paths(self): """Generates the planar slicing paths.""" z = [ self.mesh.vertex_attribute(key, 'z') for key in self.mesh.vertices() ] min_z, max_z = min(z), max(z) d = abs(min_z - max_z) no_of_layers = int(d / self.layer_height) + 1 normal = Vector(0, 0, 1) planes = [ Plane(Point(0, 0, min_z + i * self.layer_height), normal) for i in range(no_of_layers) ] # planes.pop(0) # remove planes that are on the print platform if self.slicer_type == "default": logger.info('') logger.info("Planar slicing using default function ...") self.layers = compas_slicer.slicers.create_planar_paths( self.mesh, planes) elif self.slicer_type == "cgal": logger.info('') logger.info("Planar slicing using CGAL ...") self.layers = compas_slicer.slicers.create_planar_paths_cgal( self.mesh, planes) else: raise NameError("Invalid slicing type : " + self.slicer_type)
def from_data(cls, data): """Construct a BSpline surface from its data representation. Parameters ---------- data : dict The data dictionary. Returns ------- :class:`compas.geometry.NurbsSurface` The constructed surface. """ points = [[Point.from_data(point) for point in row] for row in data['points']] weights = data['weights'] u_knots = data['u_knots'] v_knots = data['v_knots'] u_mults = data['u_mults'] v_mults = data['v_mults'] u_degree = data['u_degree'] v_degree = data['v_degree'] is_u_periodic = data['is_u_periodic'] is_v_periodic = data['is_v_periodic'] return cls.from_parameters(points, weights, u_knots, v_knots, u_mults, v_mults, u_degree, v_degree, is_u_periodic, is_v_periodic)
def main(): compas_mesh = Mesh.from_obj(os.path.join(DATA, MODEL)) move_mesh_to_point(compas_mesh, Point(0, 0, 0)) # Slicing slicer = PlanarSlicer(compas_mesh, slicer_type="cgal", layer_height=5.0) slicer.slice_model() # Sorting into vertical layers and reordering sort_into_vertical_layers(slicer, max_paths_per_layer=10) reorder_vertical_layers(slicer, align_with="x_axis") # Post-processing generate_brim(slicer, layer_width=3.0, number_of_brim_offsets=5) simplify_paths_rdp_igl(slicer, threshold=0.7) seams_smooth(slicer, smooth_distance=10) slicer.printout_info() save_to_json(slicer.to_data(), OUTPUT_DIR, 'slicer_data.json') # PlanarPrintOrganization print_organizer = PlanarPrintOrganizer(slicer) print_organizer.create_printpoints() set_extruder_toggle(print_organizer, slicer) add_safety_printpoints(print_organizer, z_hop=10.0) set_linear_velocity_constant(print_organizer, v=25.0) set_blend_radius(print_organizer, d_fillet=10.0) print_organizer.printout_info() printpoints_data = print_organizer.output_printpoints_dict() utils.save_to_json(printpoints_data, OUTPUT_DIR, 'out_printpoints.json')
def face_subdiv_mid2center(self, fkey, rel_pos=None, move_z=None, **kwattr): xyz = Point(*self.face_center(fkey)) x, y, z = self._move_center_pt(xyz, fkey, rel_pos, move_z) face_halfedges = self.face_halfedges(fkey) new_vkeys, new_fkeys, deleted_faces = self._split_edges(fkey, face_halfedges) deleted_faces.append((fkey, self.face_vertices(fkey))) self.delete_face(fkey) center_vkey = self.add_vertex(x=x, y=y, z=z) for i, face_halfedge in enumerate(face_halfedges): face_vertex, _ = face_halfedge edge_mid = new_vkeys[i] prev_edge_mid = new_vkeys[(i - 1) % len(new_vkeys)] vkeys = [face_vertex, edge_mid, center_vkey, prev_edge_mid] new_fkeys.append(self.add_face(vkeys)) new_vkeys.append(center_vkey) return new_vkeys, new_fkeys, deleted_faces
def draw(self, point=None, show_point=False): """Draw the vector. Parameters ---------- point : [float, float, float] or :class:`compas.geometry.Point`, optional Point of application of the vector. Default is ``Point(0, 0, 0)``. show_point : bool, optional If True, draw the base point of the vector. Returns ------- list[System.Guid] The GUIDs of the created Rhino objects. """ if not point: point = [0, 0, 0] start = Point(*point) end = start + self.primitive start = list(start) end = list(end) guids = [] if show_point: points = [{'pos': start, 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_points(points, layer=self.layer, clear=False, redraw=False) lines = [{'start': start, 'end': end, 'arrow': 'end', 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False) return guids
def face_subdiv_mid_cent(self, fkey, rel_pos=None, move_z=None, **kwattr): xyz = Point(*self.face_center(fkey)) x, y, z = self._move_center_pt(xyz, fkey, rel_pos, move_z) face_vertices = self.face_vertices(fkey) face_halfedges = self.face_halfedges(fkey) self.delete_face(fkey) center_vkey = self.add_vertex(x=x, y=y, z=z) new_vkeys = [] for u, v in face_halfedges: x, y, z = self.edge_midpoint(u, v) new_vkeys.append(self.add_vertex(x=x, y=y, z=z)) new_fkeys = [] for i, face_vertex in enumerate(face_vertices): edge_mid = new_vkeys[i] prev_edge_mid = new_vkeys[(i - 1) % len(new_vkeys)] vkeys = [face_vertex, edge_mid, center_vkey, prev_edge_mid] new_fkeys.append(self.add_face(vkeys)) new_vkeys.append(center_vkey) return new_vkeys, new_fkeys
def create_base_boundaries(self): """ Creates one BaseBoundary per vertical_layer.""" bs = [] root_vs = utils.get_mesh_vertex_coords_with_attribute( self.slicer.mesh, 'boundary', 1) root_boundary = BaseBoundary(self.slicer.mesh, [Point(*v) for v in root_vs]) if len(self.vertical_layers) > 1: for i, vertical_layer in enumerate(self.vertical_layers): parents_of_current_node = self.topo_sort_graph.get_parents_of_node( i) if len(parents_of_current_node) == 0: boundary = root_boundary else: boundary_pts = [] for parent_index in parents_of_current_node: parent = self.vertical_layers[parent_index] boundary_pts.extend(parent.paths[-1].points) boundary = BaseBoundary(self.slicer.mesh, boundary_pts) bs.append(boundary) else: bs.append(root_boundary) # save intermediary outputs b_data = {i: b.to_data() for i, b in enumerate(bs)} utils.save_to_json(b_data, self.OUTPUT_PATH, 'boundaries.json') return bs
def get_mid_pt_base(mesh): """Gets the middle point of the base (bottom) of the mesh. Parameters ---------- mesh: :class:`compas.datastructures.Mesh` A compas mesh. Returns ------- mesh_mid_pt: :class:`compas.geometry.Point` Middle point of the base of the mesh. """ # get center bottom point of mesh model bbox = mesh_bounding_box(mesh) corner_pts = [bbox[0], bbox[2]] x = [p[0] for p in corner_pts] y = [p[1] for p in corner_pts] z = [p[2] for p in corner_pts] mesh_mid_pt = Point((sum(x) / 2), (sum(y) / 2), (sum(z) / 2)) return mesh_mid_pt
def pick_frame_from_grid(index, bullet_height): """Get next picking frame. Parameters ---------- index : int Counter to iterate through picking positions. bullet_height : float Height of bullet to pick up. Returns ------- list of `class`:compas.geometry.Frame """ # If index is larger than amount on picking plate, start from zero again index = index % (fab_conf["pick"]["xnum"].get() * fab_conf["pick"]["ynum"].get()) xpos = index % fab_conf["pick"]["xnum"].get() ypos = index // fab_conf["pick"]["xnum"].get() x = (fab_conf["pick"]["origin_grid"]["x"].get() + xpos * fab_conf["pick"]["grid_spacing"].get()) y = (fab_conf["pick"]["origin_grid"]["y"].get() + ypos * fab_conf["pick"]["grid_spacing"].get()) z = bullet_height * fab_conf["pick"]["compression_height_factor"].get() frame = Frame( Point(x, y, z), Vector(*fab_conf["pick"]["xaxis"].get()), Vector(*fab_conf["pick"]["yaxis"].get()), ) log.debug("Picking frame {:03d}: {}".format(index, frame)) return frame
def simplify_paths_rdp(slicer, threshold): """Simplifies a path using the Ramer–Douglas–Peucker algorithm, implemented in the rdp python library. https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm Parameters ---------- slicer: :class:`compas_slicer.slicers.BaseSlicer` An instance of one of the compas_slicer.slicers classes. threshold: float Controls the degree of polyline simplification. Low threshold removes few points, high threshold removes many points. """ logger.info("Paths simplification rdp") remaining_pts_num = 0 with progressbar.ProgressBar(max_value=len(slicer.layers)) as bar: for i, layer in enumerate(slicer.layers): if not layer.is_raft: # no simplification necessary for raft layer for path in layer.paths: pts_rdp = rdp.rdp(np.array(path.points), epsilon=threshold) path.points = [ Point(pt[0], pt[1], pt[2]) for pt in pts_rdp ] remaining_pts_num += len(path.points) bar.update(i) logger.info('%d Points remaining after rdp simplification' % remaining_pts_num)
def quad_to_face(points: Quad) -> TopoDS_Face: """Convert a quad to a BRep face with an underlying ruled surface. Parameters ---------- points : [point, point, point, point] Four points defining a quad. Returns ------- TopoDS_Face Raises ------ AssertionError If the number of points is not 4. """ assert len(points) == 4, "The number of input points should be four." points = [Point(*point) for point in points] curve1 = GeomAPI_PointsToBSpline( array1_from_points1([points[0], points[1]])).Curve() curve2 = GeomAPI_PointsToBSpline( array1_from_points1([points[3], points[2]])).Curve() srf = geomfill_Surface(curve1, curve2) return BRepBuilderAPI_MakeFace(srf, 1e-6).Face()
def simplify_paths_rdp_igl(slicer, threshold): """ https://libigl.github.io/libigl-python-bindings/igl_docs/#ramer_douglas_peucker Parameters ---------- slicer: :class:`compas_slicer.slicers.BaseSlicer` An instance of one of the compas_slicer.slicers classes. threshold: float Controls the degree of polyline simplification. Low threshold removes few points, high threshold removes many points. """ try: utils.check_package_is_installed('igl') logger.info("Paths simplification rdp - igl") remaining_pts_num = 0 for i, layer in enumerate(slicer.layers): if not layer.is_raft: # no simplification necessary for raft layer for path in layer.paths: pts = np.array([[pt[0], pt[1], pt[2]] for pt in path.points]) S, J, Q = igl.ramer_douglas_peucker(pts, threshold) path.points = [Point(pt[0], pt[1], pt[2]) for pt in S] logger.info('%d Points remaining after rdp simplification' % remaining_pts_num) except PluginNotInstalledError: logger.info( "Libigl is not installed. Falling back to python rdp function") simplify_paths_rdp(slicer, threshold)
def test_sphere_scaling(): s = Sphere(Point(1, 1, 1), 10) s.transform(Scale.from_factors([2, 3, 4])) assert s.point.x == 2 assert s.point.y == 3 assert s.point.z == 4 assert s.radius == 40