module GR3
OverView of GR.rb
+--------------------+ +--------------------+ | GR module | | GR3 module | | +----------------+ | | +----------------+ | | | GR::FFI | | | | GR3::FFI | | | | + libGR.so | | | | + libGR3.so | | | +----------------+ | | +----------------+ | | | define_method | | | define_method | | +----------------+ | | +----------------+ | | | | GR::GRBase | | | | | GR3::GR3Base | | | | v (Pri^ate) | | | | v (Pri^ate) | | | +++--------------+ | | +++--------------+ | | | Extend | | | Extend | | v | | v +-------+ | | +-----------+ | | | Check | | | | GR::Plot | | | <--+ Error | | | +-----------+ | | +-------+ | +--------------------+ +----------+---------+ ^ ^ | +------------------+ | Extend | | GRCommons module | | Extend | | +--------------+ | | | | | Fiddley | | | | | +--------------+ | | | | +--------------+ | | +----+ CommonUtils +----+ | | +--------------+ | | | | +--------------+ | | +----+ Version +----+ | | +--------------+ | | | +--------------+ | +----+JupyterSupport| | | +--------------+ | +------------------+
(You can edit the above AA diagram with asciiflow.com/)
Fiddley is Ruby-FFI compatible API layer for Fiddle.
@note
Why not GR::GR3? * kojix2 did not want to force gr3 to be loaded when gr is loaded. * kojix2 did not want to write `GR3 = GR::GR3` or something. * This is a opinion of kojix2 and may be changed by future maintainers.
@note
GR3 uses Numo::Narrray. * It is difficult to write GR3 modules with only Ruby arrays. * Numo::Narray has better performance and is easier to read. * Numo::Narray does not work with JRuby. * https://github.com/ruby-numo/numo-narray/issues/147
This is a procedural interface to the GR3
in GR
plotting library, github.com/sciapp/gr
Constants
- ATOM_COLORS
- ATOM_NUMBERS
- ATOM_RADII
- ATOM_VALENCE_RADII
- DRAWABLE_GKS
- DRAWABLE_OPENGL
Drawable
- ERROR_CAMERA_NOT_INITIALIZED
- ERROR_CANNOT_OPEN_FILE
- ERROR_EXPORT
- ERROR_INIT_FAILED
- ERROR_INVALID_ATTRIBUTE
- ERROR_INVALID_VALUE
- ERROR_NONE
- ERROR_NOT_INITIALIZED
- ERROR_OPENGL_ERR
- ERROR_OUT_OF_MEM
- ERROR_UNKNOWN_FILE_EXTENSION
- IA_END_OF_LIST
InitAttribute
- IA_FRAMEBUFFER_HEIGHT
- IA_FRAMEBUFFER_WIDTH
- IA_NUM_THREADS
- PROJECTION_ORTHOGRAPHIC
- PROJECTION_PARALLEL
- PROJECTION_PERSPECTIVE
Projection
- QUALITY_OPENGL_16X_SSAA
- QUALITY_OPENGL_2X_SSAA
- QUALITY_OPENGL_4X_SSAA
- QUALITY_OPENGL_8X_SSAA
- QUALITY_OPENGL_NO_SSAA
Quality
- QUALITY_POVRAY_16X_SSAA
- QUALITY_POVRAY_2X_SSAA
- QUALITY_POVRAY_4X_SSAA
- QUALITY_POVRAY_8X_SSAA
- QUALITY_POVRAY_NO_SSAA
- SURFACE_DEFAULT
SurfaceOption
- SURFACE_FLAT
- SURFACE_GRCOLOR
- SURFACE_GRTRANSFORM
- SURFACE_GRZSHADED
- SURFACE_NORMALS
- VERSION
Attributes
Public Class Methods
This function creates an indexed mesh from vertex information (position, normal and color) and triangle information (indices). Returns a mesh.
@param num_vertices [Integer] the number of vertices in the mesh @param vertices [Array, NArray] the vertex positions @param normals [Array, NArray] the vertex normals @param colors [Array, NArray] the vertex colors, they should be
white (1,1,1) if you want to change the color for each drawn mesh
@param num_indices [Integer] the number of indices in the mesh
(three times the number of triangles)
@param indices [Array, NArray] the index array (vertex indices for
each triangle)
@return [Integer]
# File lib/gr3.rb, line 278 def createindexedmesh(num_vertices, vertices, normals, colors, num_indices, indices) inquiry_int do |mesh| super(mesh, num_vertices, vertices, normals, colors, num_indices, indices) end end
This function creates a mesh from vertex position, normal and color data.
@return [Integer]
# File lib/gr3.rb, line 255 def createindexedmesh_nocopy(num_vertices, vertices, normals, colors, num_indices, indices) inquiry_int do |mesh| super(mesh, num_vertices, vertices, normals, colors, num_indices, indices) end end
This function creates an isosurface from voxel data using the marching cubes algorithm. Returns a mesh.
@param grid [NArray] 3D narray array containing the voxel data @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction @param isolevel [Integer] isovalue at which the surface will be created
@return [Integer]
# File lib/gr3.rb, line 417 def createisosurfacemesh(grid, step, offset, isolevel) args = _preprocess_createslicemesh(grid, step, offset) grid = args.shift inquiry_int do |mesh| super(mesh, uint16(grid), isolevel, *args) end end
This function creates a int from vertex position, normal and color data. Returns a mesh.
@param n [Integer] the number of vertices in the mesh @param vertices [Array, NArray] the vertex positions @param normals [Array, NArray] the vertex normals @param colors [Array, NArray] the vertex colors, they should be
white (1,1,1) if you want to change the color for each drawn mesh
@return [Integer]
# File lib/gr3.rb, line 246 def createmesh(n, vertices, normals, colors) inquiry_int do |mesh| super(mesh, n, vertices, normals, colors) end end
This function creates a mesh from vertex position, normal and color data.
@return [Integer]
# File lib/gr3.rb, line 229 def createmesh_nocopy(n, vertices, normals, colors) inquiry_int do |mesh| super(mesh, n, vertices, normals, colors) end end
Creates meshes for slices through the given data, using the current GR
colormap. Use the parameters x, y or z to specify what slices should be drawn and at which positions they should go through the data. If neither x nor y nor z are set, 0.5 will be used for all three. Returns meshes for the yz-slice, the xz-slice and the xy-slice.
@param grid [NArray] 3D narray array containing the voxel data @param x [Numeric] the position of the slice through the xz-plane (0 to 1) @param y [Numeric] the position of the slice through the xz-plane (0 to 1) @param z [Numeric] the position of the slice through the xz-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction
# File lib/gr3.rb, line 608 def createslicemeshes(grid, x = nil, y = nil, z = nil, step = nil, offset = nil) if [x, y, z].all?(&:nil?) x = 0.5 y = 0.5 z = 0.5 end mesh_x = (createxslicemesh(grid, x, step, offset) if x) mesh_y = (createyslicemesh(grid, y, step, offset) if y) mesh_z = (createzslicemesh(grid, z, step, offset) if z) [mesh_x, mesh_y, mesh_z] end
Create a mesh of a surface plot similar to gr_surface. Uses the current colormap. To apply changes of the colormap a new mesh has to be created.
@param nx [Integer] number of points in x-direction @param ny [Integer] number of points in y-direction @param x [Array, NArray] an array containing the x-coordinates @param y [Array, NArray] an array containing the y-coordinates @param z [Array, NArray] an array of length nx * ny containing the z-coordinates @param option [Integer] option for the surface mesh; the GR3_SURFACE constants can be combined with bitwise or. See the table below.
* 0 : GR3_SURFACE_DEFAULT * default behavior * 1 : GR3_SURFACE_NORMALS * interpolate the vertex normals from the gradient * 2 : GR3_SURFACE_FLAT * set all z-coordinates to zero * 4 : GR3_SURFACE_GRTRANSFORM * use gr_inqwindow, gr_inqspace and gr_inqscale to transform the data to NDC coordinates * 8 : GR3_SURFACE_GRCOLOR * color the surface according to the current gr colormap * 16 : GR3_SURFACE_GRZSHADED * like GR3_SURFACE_GRCOLOR, but use the z-value directly as color index
@return [Integer]
# File lib/gr3.rb, line 449 def createsurfacemesh(nx, ny, x, y, z, option = 0) inquiry_int do |mesh| super(mesh, nx, ny, x, y, z, option) end end
Create a mesh object in the shape of a tube following a path given by a list of points. The colors and radii arrays specify the color and radius at each point.
@param n [Integer] the number of points given @param points [Array, NArray] the points the tube should go through @param colors [Array, NArray] the color at each point @param radii [Array, NArray] the desired tube radius at each point @param num_steps [Integer] the number of steps between each point,
allowing for a more smooth tube
@param num_segments [Integer] the number of segments each ring of the
tube consists of, e.g. 3 would yield a triangular tube
@return [Integer]
# File lib/gr3.rb, line 527 def createtubemesh(n, points, colors, radii, num_steps = 10, num_segments = 20) inquiry_uint do |mesh| # mesh should be Int? super(mesh, n, points, colors, radii, num_steps, num_segments) end end
Creates a meshes for a slices through the yz-plane of the given data, using the current GR
colormap. Use the x parameter to set the position of the yz-slice. Returns a mesh for the yz-slice.
@param grid [NArray] 3D narray array containing the voxel data @param x [Numeric] the position of the slice through the xz-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction
# File lib/gr3.rb, line 629 def createxslicemesh(grid, x = 0.5, step = nil, offset = nil) args = _preprocess_createslicemesh(grid, step, offset) grid = args.shift x = (x.clamp(0, 1) * args[0]).floor inquiry_int do |mesh| super(mesh, uint16(grid), x, *args) end end
Creates a meshes for a slices through the xz-plane of the given data, using the current GR
colormap. Use the y parameter to set the position of the xz-slice. Returns a mesh for the xz-slice.
@param grid [NArray] 3D narray array containing the voxel data @param y [Numeric] the position of the slice through the xz-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction
# File lib/gr3.rb, line 648 def createyslicemesh(grid, y = 0.5, step = nil, offset = nil) args = _preprocess_createslicemesh(grid, step, offset) grid = args.shift y = (y.clamp(0, 1) * args[1]).floor inquiry_int do |mesh| super(mesh, uint16(grid), y, *args) end end
Creates a meshes for a slices through the xy-plane of the given data, using the current GR
colormap. Use the z parameter to set the position of the xy-slice. Returns a mesh for the xy-slice.
@param grid [NArray] 3D narray array containing the voxel data @param z [Numeric] the position of the slice through the xz-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction
# File lib/gr3.rb, line 667 def createzslicemesh(grid, z = 0.5, step = nil, offset = nil) args = _preprocess_createslicemesh(grid, step, offset) grid = args.shift z = (z.clamp(0, 1) * args[2]).floor inquiry_int do |mesh| super(mesh, uint16(grid), z, *args) end end
drawmolecule
# File lib/gr3.rb, line 543 def drawmolecule(positions, colors = nil, radii = nil, spins = nil, bond_radius = nil, bond_color = nil, bond_delta = nil, set_camera = true, rotation = 0, tilt = 0) # Should `drawmolecule` take keyword arguments? # Setting default values later for now. # Should it be RubyArray instead of Narray? # If NArray is required, add no NArray error. positions = Numo::SFloat.cast(positions) n = positions.shape[0] colors = if colors.nil? Numo::SFloat.ones(n, 3) else Numo::SFloat.cast(colors).reshape(n, 3) end radii = if radii.nil? Numo::SFloat.new(n).fill(0.3) else Numo::SFloat.cast(radii).reshape(n) end bond_color ||= [0.8, 0.8, 0.8] bond_color = Numo::SFloat.cast(bond_color).reshape(3) bond_delta ||= 1.0 bond_radius ||= 0.1 if set_camera deg2rad = ->(degree) { degree * Math::PI / 180 } # room for improvement cx, cy, cz = *positions.mean(axis: 0) dx, dy, dz = *positions.ptp(axis: 0) d = [dx, dy].max / 2 / 0.4142 + 3 r = dz / 2 + d rx = r * Math.sin(deg2rad.call(tilt)) * Math.sin(deg2rad.call(rotation)) ry = r * Math.sin(deg2rad.call(tilt)) * Math.cos(deg2rad.call(rotation)) rz = r * Math.cos(deg2rad.call(tilt)) ux = Math.sin(deg2rad.call(tilt + 90)) * Math.sin(deg2rad.call(rotation)) uy = Math.sin(deg2rad.call(tilt + 90)) * Math.cos(deg2rad.call(rotation)) uz = Math.cos(deg2rad.call(tilt + 90)) cameralookat(cx + rx, cy + ry, cz + rz, cx, cy, cz, ux, uy, uz) setcameraprojectionparameters(45, d - radii.max - 3, d + dz + radii.max + 3) end super(n, positions, colors, radii, bond_radius, bond_color, bond_delta) if spins spins = Numo::SFloat.cast(spins).reshape(n, 3) drawspins(positions, spins, colors) end end
raw slices through the given data, using the current GR
colormap. Use the parameters x, y or z to specify what slices should be drawn and at which positions they should go through the data. If neither x nor y nor z are set, 0.5 will be used for all three.
@param grid [NArray] 3D narray array containing the voxel data @param x [Numeric] the position of the slice through the yz-plane (0 to 1) @param y [Numeric] the position of the slice through the xz-plane (0 to 1) @param z [Numeric] the position of the slice through the xy-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction @param position [Array, NArray] the positions where the meshes should be drawn @param direction [Array, NArray] the forward directions the meshes should be facing at @param up [Array, NArray] the up directions @param color [Array, NArray] the colors the meshes should be drawn in,
it will be multiplied with each vertex color
@param scale [Array, NArray] the scaling factors
# File lib/gr3.rb, line 757 def drawslicemeshes(grid, x = nil, y = nil, z = nil, step = nil, offset = nil, position = [0, 0, 0], direction = [0, 0, 1], up = [0, 1, 0], color = [1, 1, 1], scale = [1, 1, 1]) meshes = createslicemeshes(grid, x, y, z, step, offset) meshes.each do |mesh| if mesh drawmesh(mesh, 1, position, direction, up, color, scale) deletemesh(mesh) end end end
drawspins
# File lib/gr3.rb, line 534 def drawspins(positions, directions, colors = nil, cone_radius = 0.4, cylinder_radius = 0.2, cone_height = 1.0, cylinder_height = 1.0) n = positions.length colors = [1] * n * 3 if colors.nil? super(n, positions, directions, colors, cone_radius, cylinder_radius, cone_height, cylinder_height) end
Draw a tube following a path given by a list of points. The colors and radii arrays specify the color and radius at each point.
@param n [Integer] the number of points given @param points [Array, NArray] the points the tube should go through @param colors [Array, NArray] the color at each point @param radii [Array, NArray] the desired tube radius at each point @param num_steps [Integer] the number of steps between each point,
allowing for a more smooth tube
@param num_segments [Integer] the number of segments each ring of the tube
consists of, e.g. 3 would yield a triangular tube
@return [Integer]
# File lib/gr3.rb, line 508 def drawtubemesh(n, points, colors, radii, num_steps = 10, num_segments = 20) super(n, points, colors, radii, num_steps, num_segments) end
Draw a yz-slice through the given data, using the current GR
colormap.
@param grid [NArray] 3D narray array containing the voxel data @param x [Numeric] the position of the slice through the yz-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction @param position [Array, NArray] the positions where the meshes should be drawn @param direction [Array, NArray] the forward directions the meshes should be facing at @param up [Array, NArray] the up directions @param color [Array, NArray] the colors the meshes should be drawn in,
it will be multiplied with each vertex color
@param scale [Array, NArray] the scaling factors
# File lib/gr3.rb, line 689 def drawxslicemesh(grid, x = 0.5, step = nil, offset = nil, position = [0, 0, 0], direction = [0, 0, 1], up = [0, 1, 0], color = [1, 1, 1], scale = [1, 1, 1]) mesh = createxslicemesh(grid, x, step, offset) drawmesh(mesh, 1, position, direction, up, color, scale) deletemesh(mesh) end
Draw a xz-slice through the given data, using the current GR
colormap.
@param grid [NArray] 3D narray array containing the voxel data @param y [Numeric] the position of the slice through the xz-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction @param position [Array, NArray] the positions where the meshes should be drawn @param direction [Array, NArray] the forward directions the meshes should be facing at @param up [Array, NArray] the up directions @param color [Array, NArray] the colors the meshes should be drawn in,
it will be multiplied with each vertex color
@param scale [Array, NArray] the scaling factors
# File lib/gr3.rb, line 710 def drawyslicemesh(grid, y = 0.5, step = nil, offset = nil, position = [0, 0, 0], direction = [0, 0, 1], up = [0, 1, 0], color = [1, 1, 1], scale = [1, 1, 1]) mesh = createyslicemesh(grid, y, step, offset) drawmesh(mesh, 1, position, direction, up, color, scale) deletemesh(mesh) end
Draw a xy-slice through the given data, using the current GR
colormap.
@param grid [NArray] 3D narray array containing the voxel data @param z [Numeric] the position of the slice through the xy-plane (0 to 1) @param step [Array, NArray] voxel sizes in each direction @param offset [Array, NArray] coordinate origin in each direction @param position [Array, NArray] the positions where the meshes should be drawn @param direction [Array, NArray] the forward directions the meshes should be facing at @param up [Array, NArray] the up directions @param color [Array, NArray] the colors the meshes should be drawn in,
it will be multiplied with each vertex color
@param scale [Array, NArray] the scaling factors
# File lib/gr3.rb, line 731 def drawzslicemesh(grid, z = 0.5, step = nil, offset = nil, position = [0, 0, 0], direction = [0, 0, 1], up = [0, 1, 0], color = [1, 1, 1], scale = [1, 1, 1]) mesh = createzslicemesh(grid, z, step, offset) drawmesh(mesh, 1, position, direction, up, color, scale) deletemesh(mesh) end
This function returns a string representation of a given error code.
@return [String]
# File lib/gr3.rb, line 180 def geterrorstring(*) super.to_s end
@return [Integer]
# File lib/gr3.rb, line 213 def getimage(width, height, use_alpha = true) bpp = use_alpha ? 4 : 3 inquiry(uint8: width * height * bpp) do |bitmap| super(width, height, (use_alpha ? 1 : 0), bitmap) end end
This function allows the user to find out how his commands are rendered.
If gr3 is initialized, a string in the format: `“gr3 - ” + window toolkit + “ - ” + framebuffer extension + “ - ” + OpenGL version + “ - ” + OpenGL renderer string`. For example `“gr3 - GLX - GL_ARB_framebuffer_object - 2.1 Mesa 7.10.2 - Software Rasterizer”` might be returned on a Linux system (using GLX) with an available GL_ARB_framebuffer_object implementation. If gr3 is not initialized `“Not initialized”` is returned.
@return [String]
# File lib/gr3.rb, line 172 def getrenderpathstring(*) super.to_s end
Create a surface plot with gr3 and draw it with gks as cellarray.
@param x [Array, NArray] an array containing the x-coordinates @param y [Array, NArray] an array containing the y-coordinates @param z [Array, NArray] an array of length nx * ny containing the z-coordinates @param option [Integer] see the option parameter of gr_surface.
OPTION_COLORED_MESH and OPTION_Z_SHADED_MESH are supported.
# File lib/gr3.rb, line 487 def surface(x, y, z, option) nx = x.length ny = y.length # TODO: Check out_of_bounds super(nx, ny, x, y, z, option) end
# File lib/gr3.rb, line 769 def volume(data, algorithm) data = Numo::DFloat.cast(data) if data.is_a? Array inquiry %i[double double] do |dmin, dmax| dmin.write_double(-1) dmax.write_double(-1) nx, ny, nz = data.shape super(nx, ny, nz, data, algorithm, dmin, dmax) end end
Private Class Methods
# File lib/gr3.rb, line 781 def _preprocess_createslicemesh(grid, step, offset) # TODO: raise error when grid is not narray # grid case grid.class::MAX when Integer input_max = grid.class::MAX when Float # floating point values are expected to be in range [0, 1] # Complex narrays are not taken into account input_max = 1 grid[grid > 1] = 1 else raise ArgumentError, 'grid must be three dimensional array of Real numbers' end scaling_factor = Numo::UInt16::MAX / input_max.to_f grid = (grid.cast_to(Numo::UInt64) * scaling_factor).cast_to(Numo::UInt16) # room for improvement # step & offset nx, ny, nz = grid.shape if step.nil? && offset.nil? step = [2.0 / (nx - 1), 2.0 / (ny - 1), 2.0 / (nz - 1)] offset = [-1.0, -1.0, -1.0] elsif offset.nil? offset = [-step[0] * (nx - 1) / 2.0, -step[1] * (ny - 1) / 2.0, -step[2] * (nz - 1) / 2.0] elsif step.nil? step = [-offset[0] * 2.0 / (nx - 1), -offset[1] * 2.0 / (ny - 1), -offset[2] * 2.0 / (nz - 1)] end step_x, step_y, step_z = step offset_x, offset_y, offset_z = offset # strides stride_x = ny * nz stride_y = nz stride_z = 1 [grid, nx, ny, nz, stride_x, stride_y, stride_z, step_x, step_y, step_z, offset_x, offset_y, offset_z] end