class GroundGen(object): def __init__(self, max_r): self.max_r = max_r format = GeomVertexFormat.getV3c4() vdata = GeomVertexData('point', format, Geom.UHDynamic) self._pos_writer = GeomVertexWriter(vdata, 'vertex') self._color_writer = GeomVertexWriter(vdata, 'color') line_num = 60 vdata.setNumRows(line_num) angles = np.linspace(0, np.pi * 2 - np.pi * 2 / line_num, line_num) other_rgba = (0., 0., 0.3, 0.1) other2_rgba = (0.1, 0.1, 0.4, 0.4) axis_rgba = (0.2, 0.2, 0.5, 1.0) max_r = 250 for indx, angle in enumerate(angles): if indx % 5 == 0: rgba = axis_rgba else: rgba = other_rgba self._pos_writer.addData3d(0, 0, 0.) self._color_writer.addData4f(rgba[0], rgba[1], rgba[2], rgba[3]) self._pos_writer.addData3d(max_r * np.sin(angle), max_r * np.cos(angle), 0.) self._color_writer.addData4f(rgba[0], rgba[1], rgba[2], rgba[3]) grnd_prmtv = GeomLines(Geom.UHStatic) grnd_prmtv.addConsecutiveVertices(0, 2 * line_num) grnd_prmtv.closePrimitive() ground_geom = Geom(vdata) ground_geom.addPrimitive(grnd_prmtv) snode = GeomNode('ground_lines') snode.addGeom(ground_geom) self.points_node = base.render.attachNewNode(snode) self.points_node.setTwoSided(True) for rad in range(int(max_r)): color = axis_rgba pp = makeArc(angleDegrees=360, numSteps=160, scale=rad, color=color) tn = TextNode('dd') tn.setText(str(rad)) tn.setTextScale(0.2) tn.setTextColor(color) text_geom = GeomNode('text') text_geom.addChild(tn) tp = NodePath(text_geom) tp.setPos((0, rad - 0.2, 0)) tp.setHpr((0, -90, 0)) tp.reparentTo(self.points_node) pp.reparentTo(self.points_node)
def _get_geom_data_plate(build_plate_size: LVector2d, name: str = "") -> GeomVertexData: """Generate build plate GeomVertexData. Parameters ---------- build_plate_size : LVector2d Build plate size. name : str Name for the generated GeomVertexData. """ # noinspection PyArgumentList geom_data = GeomVertexData(name, GeomVertexFormat.get_v3t2(), Geom.UHStatic) geom_data.setNumRows(4) writer_vertex = GeomVertexWriter(geom_data, "vertex") writer_texture = GeomVertexWriter(geom_data, "texcoord") # Add build plate vertices writer_vertex.addData3d(0, 0, 0) writer_vertex.addData3d(build_plate_size.x, 0, 0) writer_vertex.addData3d(build_plate_size.x, build_plate_size.y, 0) writer_vertex.addData3d(0, build_plate_size.y, 0) for uv in [(0, 0), (1, 0), (1, 1), (0, 1)]: writer_texture.addData2(*uv) return geom_data
def _get_geom_data_grid_y( cls, build_plate_size: LVector2d, grid_spacing: float = _GRID_SPACING, name: str = "", ) -> GeomVertexData: """Generate GeomVertexData for build plate grid in Y axis. Parameters ---------- build_plate_size : LVector2d Build plate size. grid_spacing : float Grid spacing; distance between successive grid lines. name : str Generated GeomVertexData name. """ geom_data = GeomVertexData(name, cls._GEOM_VERTEX_FORMAT_GRID, Geom.UHStatic) geom_data.setNumRows(int(math.ceil(build_plate_size.y / grid_spacing))) writer_vertex = GeomVertexWriter(geom_data, "vertex") writer_color = GeomVertexWriter(geom_data, "color") current_y = grid_spacing while current_y < build_plate_size.y: writer_vertex.addData3d(LVecBase3d(0, current_y, 0)) writer_vertex.addData3d( LVecBase3d(build_plate_size.x, current_y, 0)) for _ in range(2): writer_color.addData4(cls._GRID_COLOR) current_y += grid_spacing return geom_data
def _write_geom_data_coords_and_normals( cls, geom_data: GeomVertexData, layer: Layer, width: float, height: float, ): """Write vertex coords and normals into the provided GeomVertexData. Parameters ---------- geom_data : GeomVertexData GeomVertexData to write coords and normals into. layer : Layer Layer for which the coords and normals should be generated and written. width : float Segment width (nozzle diameter). height : float Segment height (layer height, thickness) """ writer_vertex = GeomVertexWriter(geom_data, "vertex") writer_normal = GeomVertexWriter(geom_data, "normal") for toolpath in layer.paths: for index, path_point in enumerate(toolpath): wall_tilt_angle = cls._get_wall_tilt_angle(toolpath, index) width_scale_factor = cls._get_wall_width_scale_factor( toolpath, index) # VERTEX COORDS # Calculate 2D points, rotated x_shift = LVector2d(width / 2, 0) * width_scale_factor v0_2d = path_point v1_2d = vec_rotated(vector=v0_2d - x_shift, pivot=v0_2d, angle=wall_tilt_angle) v3_2d = vec_rotated(vector=v0_2d + x_shift, pivot=v0_2d, angle=wall_tilt_angle) # Create 3D vertices. Take Z into account. v0_3d = LVecBase3d(*v0_2d, 0) # v0 3D v1_3d = LVecBase3d(*v1_2d, -height / 2) # v1 3D v2_3d = LVecBase3d(*v0_2d, -height) # v2 3D v3_3d = LVecBase3d(*v3_2d, -height / 2) # v3_3D for vertex_coords in [v0_3d, v1_3d, v2_3d, v3_3d]: writer_vertex.addData3d(vertex_coords) # VERTEX NORMALS if 0 < index < len(toolpath) - 1: # Intermediate wall n0 = LVecBase3d(0, 0, 1) n1 = LVecBase3d( *((toolpath[index] - toolpath[index - 1]).normalized() + (toolpath[index] - toolpath[index + 1]).normalized()), 0, ).normalized() n2 = -n0 n3 = -n1 else: # Start or end wall if index == 0: # Start wall # v[0] - v[1] ref_vec: LVecBase2d = LVecBase2d(*(toolpath[1] - toolpath[0])) normal_rot_angle = math.pi / -4 else: # index == toolpath_point_count-1: # End wall # v[-1] - v[-2] ref_vec: LVecBase2d = LVecBase2d(*(toolpath[-1] - toolpath[-2])) normal_rot_angle = math.pi / 4 ref_vec.normalize() # Top and bottom n0 = LVecBase3d(*ref_vec, 1).normalized() n2 = LVecBase3d(*ref_vec, -1).normalized() # Sides n1 = LVecBase3d( *vec_rotated(vector=ref_vec, pivot=v1_2d, angle=normal_rot_angle), 0, ) n3 = LVecBase3d( *vec_rotated(vector=ref_vec, pivot=v1_2d, angle=normal_rot_angle), 0, ) for normal in [n0, n1, n2, n3]: writer_normal.addData3d(normal)
def _get_geom_vertex_data(cls, size: LVector3d, name: str) -> GeomVertexData: """Generate GeomVertexData for the bounding box. Parameters ---------- size : LVector3d Bounding box size. name : str Name for generated GeomVertexData. Returns ------- GeomVertexData Bounding box GeomVertexData. """ geom_data = GeomVertexData(name, cls._GEOM_VERTEX_FORMAT, Geom.UHStatic) geom_data.setNumRows(8) # 8 cube vertices writer_color = GeomVertexWriter(geom_data, "color") writer_vertex = GeomVertexWriter(geom_data, "vertex") # VERTEX COLORS for i in range(8): writer_color.addData4(cls._COLOR_BOUNDING_BOX_DEFAULT) # VERTEX COORDS # Bounding box writer_vertex.addData3d(0, 0, 0) writer_vertex.addData3d(size.x, 0, 0) writer_vertex.addData3d(size.x, 0, size.z) writer_vertex.addData3d(0, 0, size.z) writer_vertex.addData3d(0, size.y, 0) writer_vertex.addData3d(size.x, size.y, 0) writer_vertex.addData3d(size.x, size.y, size.z) writer_vertex.addData3d(0, size.y, size.z) return geom_data