| 赞 | 15 |
| VIP | |
| 好人卡 | |
| 积分 | 19 |
| 经验 | |
| 最后登录 | 2026-5-25 |
| 在线时间 | 404 小时 |
- 梦石
- 0
- 星屑
- 1944
- 在线时间
- 404 小时
- 注册时间
- 2015-8-30
- 回帖
- 322
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有账号?注册会员
×
本帖最后由 有丘直方 于 2018-9-9 20:40 编辑
这个东西貌似已经有人搞过了??[pre lang="ruby"]# Color
class Color
# 根据HSL数据来生成颜色对象,第四个参数是不透明度
def self.hsl(hue, saturation, lightness, alpha = 1.0)
saturation = saturation.clamp(0.0, 1.0)
lightness = lightness.clamp(0.0, 1.0)
alpha = alpha.clamp(0.0, 1.0)
times = (hue * 3 / Math::PI).modulo(6)
amount1 = (1 - (2 * lightness - 1).abs) * saturation
amount2 = amount1 * (1 - (times % 2 - 1).abs)
correction = lightness - amount1 / 2
translation = (times.to_i + 1) % 6
args = [0, 0, 0]
args[translation / 2] = amount1
args[2 - translation % 3] = amount2
new(*args.map {|origin| (origin + correction) * 255 }, alpha * 255)
end
# 在此颜色之上按正常方式叠加另一个颜色时呈现的颜色
def blend(other)
alpha1 = alpha / 255.0
alpha2 = other.alpha / 255.0
calc_blend = proc do |c1, c2|
c1 /= 255.0
c2 /= 255.0
blend = c1 * alpha1 * (1 - alpha2) + c2 * alpha2
blend /= alpha1 + alpha2 - alpha1 * alpha2
blend *= 255
end
result = Color.new
result.alpha = (alpha1 + alpha2 - alpha1 * alpha2) * 255
result.red = calc_blend.call(red, other.red)
result.green = calc_blend.call(green, other.green)
result.blue = calc_blend.call(blue, other.blue)
result
end
# blend的破坏型方法
def blend!(other)
set(blend(other))
self
end
end
# Comparable
module Comparable
# 返回在min和max的范围内最接近self的对象
def clamp(min, max)
return min if self <=> min < 0
return max if self <=> max > 0
self
end
end
# 关于x的以mean为期望,variance为方差的正态分布函数
# 不给出mean和variance参数时是标准正态分布函数
def Math.normal_distribution(x, mean = 0.0, variance = 1.0)
exp(-(x - mean) ** 2 / (2 * variance)) / sqrt(2 * self::PI * variance)
end
# Complex
class Complex
# 获取此复数对应的定义域着色
# lightness_base: 用于计算亮度的函数中的底数,越小越亮,必须在0和1之间
# saturation: 饱和度
def to_color(lightness_base = 0.5, saturation = 1.0)
raise unless lightness_base.between?(0, 1)
exponent = abs
hue = exponent == 0 ? 0.0 : arg
lightness = 1 - lightness_base ** exponent
Color.hsl(hue, saturation, lightness)
end
# 获取此复数对应的结构化的定义域着色
# 这种着色方案有特殊效果,具体看参数说明
# discontinuity_base: 当此复数的模是达到参数的整数次幂时,亮度骤然变为最低
# saturation: 饱和度
# min_lightness: 不考虑网格和射线时能达到的最低亮度
# lightness_range: 不考虑网格和射线时能达到的最高和最低亮度之差
# grid_hue: 网格的色相
# rays_hue: 射线的色相
# grid_lightness: 网格的亮度
# rays_lightness: 射线的亮度
# grid_density: 网格线的密度,复数的实部或虚部是参数的倒数的整数倍时出现网格
# rays_density: 射线的密度,复数的俯角是参数的倒数的整数倍时出现射线
# grid_radius: 网格线的宽度的一半,不包括扩散出去的部分
# rays_radius: 射线的宽度的一半,不包括扩散出去的部分
# grid_restraint: 网格线的扩散度,越大越模糊
# rays_restraint: 射线的扩散度,越大越模糊
# grid_opacity: 网格的不透明度,如果不想显示网格请设为0.0
# rays_opacity: 射线的不透明度,如果不想显示射线请设为0.0
def to_color_structured(discontinuity_base = 2.0, saturation = 1.0,
min_lightness = 0.3, lightness_range = 0.4, grid_hue = 0.0,
rays_hue = 0.0, grid_lightness = 0.0, rays_lightness = 1.0,
grid_density = 1.0, rays_density = 6.0, grid_radius = 0.005,
rays_radius = 0.01, grid_restraint = 60.0, rays_restraint = 50.0,
grid_opacity = 0.2, rays_opacity = 0.8)
antilog = abs
hue = antilog == 0 ? 0.0 : arg
lightness_phase = Math.log(antilog, discontinuity_base).modulo(1)
lightness_phase = 0.0 if lightness_phase.nan?
lightness = lightness_phase * lightness_range + min_lightness
color = Color.hsl(hue, saturation, lightness)
f = Math.sqrt(2 * Math::PI)
dense_real = real * grid_density
real_distance = (dense_real - dense_real.round).abs
dense_imaginary = imaginary * grid_density
imaginary_distance = (dense_imaginary - dense_imaginary.round).abs
grid_distance = [[real_distance, imaginary_distance].min, grid_radius].max
grid_excursion = (grid_distance - grid_radius) * grid_restraint
grid_alpha = Math.normal_distribution(grid_excursion) * f * grid_opacity
grid_color = Color.hsl(grid_hue, saturation, grid_lightness, grid_alpha)
color.blend!(grid_color)
rays_distances = Array.new(rays_density) do |i|
slope = Math.tan(i / rays_density * Math::PI)
(slope * real - imaginary).abs / Math.hypot(slope, -1)
end
rays_distance = [rays_distances.min, rays_radius].max
rays_excursion = (rays_distance - rays_radius) * rays_restraint
rays_alpha = Math.normal_distribution(rays_excursion) * f * rays_opacity
rays_color = Color.hsl(rays_hue, saturation, rays_lightness, rays_alpha)
color.blend!(rays_color)
end
end
# Bitmap
class Bitmap
# 绘制复变函数的函数图像
# function: 需要绘制的函数,提供接受一个复数参数并返回复数的call方法
# delta_x: 图中1像素的距离代表的大小
# structured: 是否采用结构化的图像,见Complex#to_color_structured
# ox: 自变量取0+0i时所在的位置的相对于位图的x坐标
# oy: 自变量取0+0i时所在的位置的相对于位图的y坐标
def draw_function(function, delta_x, structured = false,
ox = Graphics.width / 2, oy = Graphics.height / 2)
width.times do |x|
height.times do |y|
real = (x - ox) * delta_x
imaginary = (oy - y) * delta_x
complex = function.call(Complex(real, imaginary))
color = structured ? complex.to_color_structured : complex.to_color
set_pixel(x, y, color)
end
end
end
end
[/pre]一个简单的用于玩耍的代码(依赖这玩意)(由于我用了RGD所以无视分辨率限制了)(虽然不用多线程能画得更快,但是那样就看不到图像慢慢绘制出来的过程了):[pre lang="ruby"]# 玩耍方法:在控制台输入你想要画的函数,然后等待即可
Graphics.resize_screen(1024, 768)
sprite = Sprite.new
sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
Thread.start do
loop do
print("f(z) = ")
string = $stdin.gets
function = eval("->(z) { #{string} }")
puts("Please wait...")
time = Time.now
sprite.bitmap.draw_function(function, 0.008, true) rescue puts($!.message)
printf("Completed after %d seconds.\n", Time.now - time)
end
end
rgss_stop
[/pre]配上CMath后玩耍体验更佳:[pre lang="ruby"]#==============================================================================
# * CMath
#------------------------------------------------------------------------------
# Trigonometric and transcendental functions for complex numbers.
# CMath is a library that provides trigonometric and transcendental functions
# for complex numbers. The functions in this module accept integers, floating-
# point numbers or complex numbers as arguments.
# Note that the selection of functions is similar, but not identical, to that
# in module math. The reason for having two modules is that some users aren't
# interested in complex numbers, and perhaps don't even know what they are. They
# would rather have Math.sqrt(-1) raise an exception than return a complex
# number.
# For more information you can see Complex class.
#==============================================================================
module CMath
include Math
alias exp! exp
alias log! log
alias log2! log2
alias log10! log10
alias sqrt! sqrt
alias cbrt! cbrt
alias sin! sin
alias cos! cos
alias tan! tan
alias sinh! sinh
alias cosh! cosh
alias tanh! tanh
alias asin! asin
alias acos! acos
alias atan! atan
alias atan2! atan2
alias asinh! asinh
alias acosh! acosh
alias atanh! atanh
#--------------------------------------------------------------------------
# * exp(z)
#--------------------------------------------------------------------------
# Math::E raised to the z power
#--------------------------------------------------------------------------
def exp(z)
if z.real?
exp!(z)
else
ere = exp!(z.real)
Complex(ere * cos!(z.imag),
ere * sin!(z.imag))
end
end
#--------------------------------------------------------------------------
# * log(z, b=::Math::E)
#--------------------------------------------------------------------------
# Returns the natural logarithm of Complex. If a second argument is given,
# it will be the base of logarithm.
#--------------------------------------------------------------------------
def log(*args)
z, b = args
if z.real? and z >= 0 and (b.nil? or b >= 0)
log!(*args)
else
a = Complex(log!(z.abs), z.arg)
if b
a /= log(b)
end
a
end
end
#--------------------------------------------------------------------------
# * log2(z)
#--------------------------------------------------------------------------
# Returns the base 2 logarithm of z
#--------------------------------------------------------------------------
def log2(z)
if z.real? and z >= 0
log2!(z)
else
log(z) / log!(2)
end
end
#--------------------------------------------------------------------------
# * log10(z)
#--------------------------------------------------------------------------
# Returns the base 10 logarithm of z
#--------------------------------------------------------------------------
def log10(z)
if z.real? and z >= 0
log10!(z)
else
log(z) / log!(10)
end
end
#--------------------------------------------------------------------------
# * sqrt(z)
#--------------------------------------------------------------------------
# Returns the non-negative square root of Complex.
#--------------------------------------------------------------------------
def sqrt(z)
if z.real?
if z < 0
Complex(0, sqrt!(-z))
else
sqrt!(z)
end
else
if z.imag < 0 ||
(z.imag == 0 && z.imag.to_s[0] == '-')
sqrt(z.conjugate).conjugate
else
r = z.abs
x = z.real
Complex(sqrt!((r + x) / 2), sqrt!((r - x) / 2))
end
end
end
#--------------------------------------------------------------------------
# * cbrt(z)
#--------------------------------------------------------------------------
# Returns the principal value of the cube root of z
#--------------------------------------------------------------------------
def cbrt(z)
if z.real?
cbrt!(z)
else
Complex(z) ** (1.0/3)
end
end
#--------------------------------------------------------------------------
# * sin(z)
#--------------------------------------------------------------------------
# Returns the sine of z, where z is given in radians
#--------------------------------------------------------------------------
def sin(z)
if z.real?
sin!(z)
else
Complex(sin!(z.real) * cosh!(z.imag),
cos!(z.real) * sinh!(z.imag))
end
end
#--------------------------------------------------------------------------
# * cos(z)
#--------------------------------------------------------------------------
# Returns the cosine of z, where z is given in radians
#--------------------------------------------------------------------------
def cos(z)
if z.real?
cos!(z)
else
Complex(cos!(z.real) * cosh!(z.imag),
-sin!(z.real) * sinh!(z.imag))
end
end
#--------------------------------------------------------------------------
# * tan(z)
#--------------------------------------------------------------------------
# Returns the tangent of z, where z is given in radians
#--------------------------------------------------------------------------
def tan(z)
if z.real?
tan!(z)
else
sin(z) / cos(z)
end
end
#--------------------------------------------------------------------------
# * sinh(z)
#--------------------------------------------------------------------------
# Returns the hyperbolic sine of z, where z is given in radians
#--------------------------------------------------------------------------
def sinh(z)
if z.real?
sinh!(z)
else
Complex(sinh!(z.real) * cos!(z.imag),
cosh!(z.real) * sin!(z.imag))
end
end
#--------------------------------------------------------------------------
# * cos(z)
#--------------------------------------------------------------------------
# Returns the hyperbolic cosine of z, where z is given in radians
#--------------------------------------------------------------------------
def cosh(z)
if z.real?
cosh!(z)
else
Complex(cosh!(z.real) * cos!(z.imag),
sinh!(z.real) * sin!(z.imag))
end
end
#--------------------------------------------------------------------------
# * tanh(z)
#--------------------------------------------------------------------------
# Returns the hyperbolic tangent of z, where z is given in radians
#--------------------------------------------------------------------------
def tanh(z)
if z.real?
tanh!(z)
else
sinh(z) / cosh(z)
end
end
#--------------------------------------------------------------------------
# * asin(z)
#--------------------------------------------------------------------------
# Returns the arc sine of z
#--------------------------------------------------------------------------
def asin(z)
if z.real? and z >= -1 and z <= 1
asin!(z)
else
(-1.0).i * log(1.0.i * z + sqrt(1.0 - z * z))
end
end
#--------------------------------------------------------------------------
# * acos(z)
#--------------------------------------------------------------------------
# Returns the arc cosine of z
#--------------------------------------------------------------------------
def acos(z)
if z.real? and z >= -1 and z <= 1
acos!(z)
else
(-1.0).i * log(z + 1.0.i * sqrt(1.0 - z * z))
end
end
#--------------------------------------------------------------------------
# * atan(z)
#--------------------------------------------------------------------------
# Returns the arc tangent of z
#--------------------------------------------------------------------------
def atan(z)
if z.real?
atan!(z)
else
1.0.i * log((1.0.i + z) / (1.0.i - z)) / 2.0
end
end
#--------------------------------------------------------------------------
# * atan2(z)
#--------------------------------------------------------------------------
# returns the arc tangent of y divided by x using the signs of y and x to
# determine the quadrant
#--------------------------------------------------------------------------
def atan2(y,x)
if y.real? and x.real?
atan2!(y,x)
else
(-1.0).i * log((x + 1.0.i * y) / sqrt(x * x + y * y))
end
end
#--------------------------------------------------------------------------
# * asinh(z)
#--------------------------------------------------------------------------
# returns the inverse hyperbolic sine of z
#--------------------------------------------------------------------------
def asinh(z)
if z.real?
asinh!(z)
else
log(z + sqrt(1.0 + z * z))
end
end
#--------------------------------------------------------------------------
# * acosh(z)
#--------------------------------------------------------------------------
# returns the inverse hyperbolic cosine of z
#--------------------------------------------------------------------------
def acosh(z)
if z.real? and z >= 1
acosh!(z)
else
log(z + sqrt(z * z - 1.0))
end
end
#--------------------------------------------------------------------------
# * atanh(z)
#--------------------------------------------------------------------------
# returns the inverse hyperbolic tangent of z
#--------------------------------------------------------------------------
def atanh(z)
if z.real? and z >= -1 and z <= 1
atanh!(z)
else
log((1.0 + z) / (1.0 - z)) / 2.0
end
end
module_function :exp!
module_function :exp
module_function :log!
module_function :log
module_function :log2!
module_function :log2
module_function :log10!
module_function :log10
module_function :sqrt!
module_function :sqrt
module_function :cbrt!
module_function :cbrt
module_function :sin!
module_function :sin
module_function :cos!
module_function :cos
module_function :tan!
module_function :tan
module_function :sinh!
module_function :sinh
module_function :cosh!
module_function :cosh
module_function :tanh!
module_function :tanh
module_function :asin!
module_function :asin
module_function :acos!
module_function :acos
module_function :atan!
module_function :atan
module_function :atan2!
module_function :atan2
module_function :asinh!
module_function :asinh
module_function :acosh!
module_function :acosh
module_function :atanh!
module_function :atanh
module_function :frexp
module_function :ldexp
module_function :hypot
module_function :erf
module_function :erfc
module_function :gamma
module_function :lgamma
end
[/pre]
顺便一提,虽然绘制速度慢到让人吐血,但是由于不支持后台运行,请将焦点保持在窗口上,慢慢看着它画完;我也不是很清楚为什么RGD不支持这个
再顺便一提,要是RGD有更高的Ruby版本就好了,我就不用写Complex(1, 2),直接写1+2i了 |
评分
-
查看全部评分
|